mirror of
https://github.com/railwayapp/cli
synced 2026-04-21 14:07:23 +00:00
* Introduce optional replace semantics for variables set as an alternative to upsert * Add a safety prompt for replace and a flag to skip it * Update wordings, simplify function signature and add comment to warn about destructive query
213 lines
4.8 KiB
Go
213 lines
4.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/railwayapp/cli/ui"
|
|
|
|
"github.com/railwayapp/cli/entity"
|
|
)
|
|
|
|
func (h *Handler) Variables(ctx context.Context, req *entity.CommandRequest) error {
|
|
serviceName, err := req.Cmd.Flags().GetString("service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
envs, err := h.ctrl.GetEnvsForCurrentEnvironment(ctx, &serviceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
environment, err := h.ctrl.GetCurrentEnvironment(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Print(ui.Heading(fmt.Sprintf("%s Environment Variables", environment.Name)))
|
|
fmt.Print(ui.KeyValues(*envs))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) VariablesGet(ctx context.Context, req *entity.CommandRequest) error {
|
|
serviceName, err := req.Cmd.Flags().GetString("service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
envs, err := h.ctrl.GetEnvsForCurrentEnvironment(ctx, &serviceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, key := range req.Args {
|
|
fmt.Println(envs.Get(key))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) VariablesSet(ctx context.Context, req *entity.CommandRequest) error {
|
|
serviceName, err := req.Cmd.Flags().GetString("service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
skipRedeploy, err := req.Cmd.Flags().GetBool("skip-redeploy")
|
|
if err != nil {
|
|
// The flag is optional; default to false.
|
|
skipRedeploy = false
|
|
}
|
|
|
|
replace, err := req.Cmd.Flags().GetBool("replace")
|
|
if err != nil {
|
|
// The flag is optional; default to false.
|
|
replace = false
|
|
}
|
|
|
|
yes, err := req.Cmd.Flags().GetBool("yes")
|
|
if err != nil {
|
|
// The flag is optional; default to false.
|
|
yes = false
|
|
}
|
|
|
|
if replace && !yes {
|
|
fmt.Println(ui.Bold(ui.RedText(fmt.Sprintf("Warning! You are about to fully replace all your variables for the service '%s'.", serviceName)).String()))
|
|
confirm, err := ui.PromptYesNo("Continue?")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !confirm {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
variables := &entity.Envs{}
|
|
updatedEnvNames := make([]string, 0)
|
|
|
|
for _, kvPair := range req.Args {
|
|
parts := strings.SplitN(kvPair, "=", 2)
|
|
if len(parts) != 2 {
|
|
return errors.New("invalid variables invocation. See --help")
|
|
}
|
|
key := parts[0]
|
|
value := parts[1]
|
|
|
|
variables.Set(key, value)
|
|
updatedEnvNames = append(updatedEnvNames, key)
|
|
}
|
|
|
|
err = h.ctrl.UpdateEnvs(ctx, variables, &serviceName, replace)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
environment, err := h.ctrl.GetCurrentEnvironment(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
operation := "Updated"
|
|
if replace {
|
|
operation = "Replaced existing variables with"
|
|
}
|
|
|
|
fmt.Print(ui.Heading(fmt.Sprintf("%s %s for \"%s\"", operation, strings.Join(updatedEnvNames, ", "), environment.Name)))
|
|
fmt.Print(ui.KeyValues(*variables))
|
|
|
|
if !skipRedeploy {
|
|
serviceID, err := h.ctrl.GetServiceIdByName(ctx, &serviceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = h.redeployAfterVariablesChange(ctx, environment, serviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) VariablesDelete(ctx context.Context, req *entity.CommandRequest) error {
|
|
serviceName, err := req.Cmd.Flags().GetString("service")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
skipRedeploy, err := req.Cmd.Flags().GetBool("skip-redeploy")
|
|
if err != nil {
|
|
// The flag is optional; default to false.
|
|
skipRedeploy = false
|
|
}
|
|
|
|
err = h.ctrl.DeleteEnvs(ctx, req.Args, &serviceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
environment, err := h.ctrl.GetCurrentEnvironment(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Print(ui.Heading(fmt.Sprintf("Deleted %s for \"%s\"", strings.Join(req.Args, ", "), environment.Name)))
|
|
|
|
if !skipRedeploy {
|
|
serviceID, err := h.ctrl.GetServiceIdByName(ctx, &serviceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = h.redeployAfterVariablesChange(ctx, environment, serviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) redeployAfterVariablesChange(ctx context.Context, environment *entity.Environment, serviceID *string) error {
|
|
deployments, err := h.ctrl.GetDeployments(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Don't redeploy if we don't yet have any deployments
|
|
if len(deployments) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Don't redeploy if the latest deploy for environment came from up
|
|
latestDeploy := deployments[0]
|
|
if latestDeploy.Meta == nil || latestDeploy.Meta.Repo == "" {
|
|
fmt.Printf(ui.AlertInfo("Run %s to redeploy your project"), ui.MagentaText("railway up").Underline())
|
|
return nil
|
|
}
|
|
|
|
ui.StartSpinner(&ui.SpinnerCfg{
|
|
Message: fmt.Sprintf("Redeploying \"%s\" with new variables", environment.Name),
|
|
})
|
|
|
|
err = h.ctrl.DeployEnvironmentTriggers(ctx, serviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ui.StopSpinner("Deploy triggered")
|
|
|
|
deployment, err := h.ctrl.GetLatestDeploymentForEnvironment(ctx, latestDeploy.ProjectID, environment.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("☁️ Deploy Logs available at %s\n", ui.GrayText(h.ctrl.GetServiceDeploymentsURL(ctx, latestDeploy.ProjectID, *serviceID, deployment.ID)))
|
|
return nil
|
|
}
|