diff --git a/pkg/cmd/package/upload/upload.go b/pkg/cmd/package/upload/upload.go index 8bee3b77..ecbf5ab1 100644 --- a/pkg/cmd/package/upload/upload.go +++ b/pkg/cmd/package/upload/upload.go @@ -4,12 +4,13 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OctopusDeploy/cli/pkg/apiclient" "io" "os" "path/filepath" "strings" + "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/constants" "github.com/OctopusDeploy/cli/pkg/constants/annotations" @@ -76,7 +77,7 @@ func NewCmdUpload(f factory.Factory) *cobra.Command { } flags := cmd.Flags() - flags.StringSliceVarP(&uploadFlags.Package.Value, uploadFlags.Package.Name, "p", nil, "Package to upload, may be specified multiple times. Any arguments without flags will be treated as packages") + flags.StringArrayVarP(&uploadFlags.Package.Value, uploadFlags.Package.Name, "p", nil, "Package to upload, may be specified multiple times. Any arguments without flags will be treated as packages") flags.StringVarP(&uploadFlags.OverwriteMode.Value, uploadFlags.OverwriteMode.Name, "", "", "Action when a package already exists. Valid values are 'fail', 'overwrite', 'ignore'. Default is 'fail'") flags.BoolVarP(&uploadFlags.ContinueOnError.Value, uploadFlags.ContinueOnError.Name, "", false, "When uploading multiple packages, controls whether the CLI continues after a failed upload. Default is to abort.") flags.SortFlags = false diff --git a/pkg/cmd/project/variables/exclude/exclude.go b/pkg/cmd/project/variables/exclude/exclude.go index b3dbb982..ed29aebd 100644 --- a/pkg/cmd/project/variables/exclude/exclude.go +++ b/pkg/cmd/project/variables/exclude/exclude.go @@ -2,6 +2,8 @@ package exclude import ( "fmt" + "strings" + "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd" "github.com/OctopusDeploy/cli/pkg/cmd/tenant/shared" @@ -15,7 +17,6 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" - "strings" ) const ( @@ -76,7 +77,7 @@ func NewExcludeVariableSetCmd(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&createFlags.Project.Value, createFlags.Project.Name, "p", "", "The project") - flags.StringSliceVarP(&createFlags.VariableSets.Value, createFlags.VariableSets.Name, "", []string{}, "The name of the library variable set") + flags.StringArrayVarP(&createFlags.VariableSets.Value, createFlags.VariableSets.Name, "", []string{}, "The name of the library variable set") return cmd } diff --git a/pkg/cmd/project/variables/include/include.go b/pkg/cmd/project/variables/include/include.go index 110e2bc0..ffde744e 100644 --- a/pkg/cmd/project/variables/include/include.go +++ b/pkg/cmd/project/variables/include/include.go @@ -2,6 +2,8 @@ package include import ( "fmt" + "strings" + "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd" "github.com/OctopusDeploy/cli/pkg/cmd/tenant/shared" @@ -15,7 +17,6 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" - "strings" ) const ( @@ -76,7 +77,7 @@ func NewIncludeVariableSetCmd(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&createFlags.Project.Value, createFlags.Project.Name, "p", "", "The project") - flags.StringSliceVarP(&createFlags.VariableSets.Value, createFlags.VariableSets.Name, "", []string{}, "The name of the library variable set") + flags.StringArrayVarP(&createFlags.VariableSets.Value, createFlags.VariableSets.Name, "", []string{}, "The name of the library variable set") return cmd } diff --git a/pkg/cmd/release/create/create.go b/pkg/cmd/release/create/create.go index 8e282167..0f3b1ba7 100644 --- a/pkg/cmd/release/create/create.go +++ b/pkg/cmd/release/create/create.go @@ -4,13 +4,14 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OctopusDeploy/cli/pkg/apiclient" "io" "os" "regexp" "sort" "strings" + "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd/release/list" @@ -167,7 +168,7 @@ func NewCmdCreate(f factory.Factory) *cobra.Command { flags.StringVarP(&createFlags.Version.Value, createFlags.Version.Name, "v", "", "Override the Release Version") flags.BoolVarP(&createFlags.IgnoreExisting.Value, createFlags.IgnoreExisting.Name, "x", false, "If a release with the same version exists, do nothing instead of failing.") flags.BoolVarP(&createFlags.IgnoreChannelRules.Value, createFlags.IgnoreChannelRules.Name, "", false, "Allow creation of a release where channel rules would otherwise prevent it.") - flags.StringSliceVarP(&createFlags.PackageVersionSpec.Value, createFlags.PackageVersionSpec.Name, "", []string{}, "Version specification a specific packages.\nFormat as {package}:{version}, {step}:{version} or {package-ref-name}:{packageOrStep}:{version}\nYou may specify this multiple times") + flags.StringArrayVarP(&createFlags.PackageVersionSpec.Value, createFlags.PackageVersionSpec.Name, "", []string{}, "Version specification a specific packages.\nFormat as {package}:{version}, {step}:{version} or {package-ref-name}:{packageOrStep}:{version}\nYou may specify this multiple times") // we want the help text to display in the above order, rather than alphabetical flags.SortFlags = false diff --git a/pkg/cmd/release/delete/delete.go b/pkg/cmd/release/delete/delete.go index 759f1f3e..0987b02f 100644 --- a/pkg/cmd/release/delete/delete.go +++ b/pkg/cmd/release/delete/delete.go @@ -3,6 +3,7 @@ package delete import ( "errors" "fmt" + "github.com/OctopusDeploy/cli/pkg/apiclient" "github.com/AlecAivazis/survey/v2" @@ -57,7 +58,7 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&cmdFlags.Project.Value, cmdFlags.Project.Name, "p", "", "Name or ID of the project to delete releases in") - flags.StringSliceVarP(&cmdFlags.Version.Value, cmdFlags.Version.Name, "v", make([]string, 0), "Release version to delete, can be specified multiple times") + flags.StringArrayVarP(&cmdFlags.Version.Value, cmdFlags.Version.Name, "v", make([]string, 0), "Release version to delete, can be specified multiple times") return cmd } diff --git a/pkg/cmd/release/deploy/deploy.go b/pkg/cmd/release/deploy/deploy.go index 9a0715aa..1082406c 100644 --- a/pkg/cmd/release/deploy/deploy.go +++ b/pkg/cmd/release/deploy/deploy.go @@ -4,11 +4,12 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OctopusDeploy/cli/pkg/apiclient" "io" "strings" "time" + "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/constants" @@ -147,18 +148,18 @@ func NewCmdDeploy(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&deployFlags.Project.Value, deployFlags.Project.Name, "p", "", "Name or ID of the project to deploy the release from") flags.StringVarP(&deployFlags.ReleaseVersion.Value, deployFlags.ReleaseVersion.Name, "", "", "Release version to deploy") - flags.StringSliceVarP(&deployFlags.Environments.Value, deployFlags.Environments.Name, "e", nil, "Deploy to this environment (can be specified multiple times)") - flags.StringSliceVarP(&deployFlags.Tenants.Value, deployFlags.Tenants.Name, "", nil, "Deploy to this tenant (can be specified multiple times)") - flags.StringSliceVarP(&deployFlags.TenantTags.Value, deployFlags.TenantTags.Name, "", nil, "Deploy to tenants matching this tag (can be specified multiple times)") + flags.StringArrayVarP(&deployFlags.Environments.Value, deployFlags.Environments.Name, "e", nil, "Deploy to this environment (can be specified multiple times)") + flags.StringArrayVarP(&deployFlags.Tenants.Value, deployFlags.Tenants.Name, "", nil, "Deploy to this tenant (can be specified multiple times)") + flags.StringArrayVarP(&deployFlags.TenantTags.Value, deployFlags.TenantTags.Name, "", nil, "Deploy to tenants matching this tag (can be specified multiple times)") flags.StringVarP(&deployFlags.DeployAt.Value, deployFlags.DeployAt.Name, "", "", "Deploy at a later time. Deploy now if omitted. TODO date formats and timezones!") flags.StringVarP(&deployFlags.MaxQueueTime.Value, deployFlags.MaxQueueTime.Name, "", "", "Cancel the deployment if it hasn't started within this time period.") - flags.StringSliceVarP(&deployFlags.Variables.Value, deployFlags.Variables.Name, "v", nil, "Set the value for a prompted variable in the format Label:Value") + flags.StringArrayVarP(&deployFlags.Variables.Value, deployFlags.Variables.Name, "v", nil, "Set the value for a prompted variable in the format Label:Value") flags.BoolVarP(&deployFlags.UpdateVariables.Value, deployFlags.UpdateVariables.Name, "", false, "Overwrite the release variable snapshot by re-importing variables from the project.") - flags.StringSliceVarP(&deployFlags.ExcludedSteps.Value, deployFlags.ExcludedSteps.Name, "", nil, "Exclude specific steps from the deployment") + flags.StringArrayVarP(&deployFlags.ExcludedSteps.Value, deployFlags.ExcludedSteps.Name, "", nil, "Exclude specific steps from the deployment") flags.StringVarP(&deployFlags.GuidedFailureMode.Value, deployFlags.GuidedFailureMode.Name, "", "", "Enable Guided failure mode (true/false/default)") flags.BoolVarP(&deployFlags.ForcePackageDownload.Value, deployFlags.ForcePackageDownload.Name, "", false, "Force re-download of packages") - flags.StringSliceVarP(&deployFlags.DeploymentTargets.Value, deployFlags.DeploymentTargets.Name, "", nil, "Deploy to this target (can be specified multiple times)") - flags.StringSliceVarP(&deployFlags.ExcludeTargets.Value, deployFlags.ExcludeTargets.Name, "", nil, "Deploy to targets except for this (can be specified multiple times)") + flags.StringArrayVarP(&deployFlags.DeploymentTargets.Value, deployFlags.DeploymentTargets.Name, "", nil, "Deploy to this target (can be specified multiple times)") + flags.StringArrayVarP(&deployFlags.ExcludeTargets.Value, deployFlags.ExcludeTargets.Name, "", nil, "Deploy to targets except for this (can be specified multiple times)") flags.SortFlags = false diff --git a/pkg/cmd/runbook/run/run.go b/pkg/cmd/runbook/run/run.go index 538b94c9..6f3924c3 100644 --- a/pkg/cmd/runbook/run/run.go +++ b/pkg/cmd/runbook/run/run.go @@ -3,12 +3,13 @@ package run import ( "encoding/json" "fmt" - "github.com/OctopusDeploy/cli/pkg/apiclient" "io" "math" "strings" "time" + "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/constants" @@ -135,18 +136,18 @@ func NewCmdRun(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&runFlags.Project.Value, runFlags.Project.Name, "p", "", "Name or ID of the project to run the runbook from") flags.StringVarP(&runFlags.RunbookName.Value, runFlags.RunbookName.Name, "n", "", "Name of the runbook to run") - flags.StringSliceVarP(&runFlags.Environments.Value, runFlags.Environments.Name, "e", nil, "Run in this environment (can be specified multiple times)") - flags.StringSliceVarP(&runFlags.Tenants.Value, runFlags.Tenants.Name, "", nil, "Run for this tenant (can be specified multiple times)") - flags.StringSliceVarP(&runFlags.TenantTags.Value, runFlags.TenantTags.Name, "", nil, "Run for tenants matching this tag (can be specified multiple times)") + flags.StringArrayVarP(&runFlags.Environments.Value, runFlags.Environments.Name, "e", nil, "Run in this environment (can be specified multiple times)") + flags.StringArrayVarP(&runFlags.Tenants.Value, runFlags.Tenants.Name, "", nil, "Run for this tenant (can be specified multiple times)") + flags.StringArrayVarP(&runFlags.TenantTags.Value, runFlags.TenantTags.Name, "", nil, "Run for tenants matching this tag (can be specified multiple times)") flags.StringVarP(&runFlags.RunAt.Value, runFlags.RunAt.Name, "", "", "Run at a later time. Run now if omitted. TODO date formats and timezones!") flags.StringVarP(&runFlags.MaxQueueTime.Value, runFlags.MaxQueueTime.Name, "", "", "Cancel a scheduled run if it hasn't started within this time period.") - flags.StringSliceVarP(&runFlags.Variables.Value, runFlags.Variables.Name, "v", nil, "Set the value for a prompted variable in the format Label:Value") + flags.StringArrayVarP(&runFlags.Variables.Value, runFlags.Variables.Name, "v", nil, "Set the value for a prompted variable in the format Label:Value") flags.StringVarP(&runFlags.Snapshot.Value, runFlags.Snapshot.Name, "", "", "Name or ID of the snapshot to run. If not supplied, the command will attempt to use the published snapshot.") - flags.StringSliceVarP(&runFlags.ExcludedSteps.Value, runFlags.ExcludedSteps.Name, "", nil, "Exclude specific steps from the runbook") + flags.StringArrayVarP(&runFlags.ExcludedSteps.Value, runFlags.ExcludedSteps.Name, "", nil, "Exclude specific steps from the runbook") flags.StringVarP(&runFlags.GuidedFailureMode.Value, runFlags.GuidedFailureMode.Name, "", "", "Enable Guided failure mode (true/false/default)") flags.BoolVarP(&runFlags.ForcePackageDownload.Value, runFlags.ForcePackageDownload.Name, "", false, "Force re-download of packages") - flags.StringSliceVarP(&runFlags.RunTargets.Value, runFlags.RunTargets.Name, "", nil, "Run on this target (can be specified multiple times)") - flags.StringSliceVarP(&runFlags.ExcludeTargets.Value, runFlags.ExcludeTargets.Name, "", nil, "Run on targets except for this (can be specified multiple times)") + flags.StringArrayVarP(&runFlags.RunTargets.Value, runFlags.RunTargets.Name, "", nil, "Run on this target (can be specified multiple times)") + flags.StringArrayVarP(&runFlags.ExcludeTargets.Value, runFlags.ExcludeTargets.Name, "", nil, "Run on targets except for this (can be specified multiple times)") flags.SortFlags = false diff --git a/pkg/cmd/space/create/create.go b/pkg/cmd/space/create/create.go index ec153710..84fd4979 100644 --- a/pkg/cmd/space/create/create.go +++ b/pkg/cmd/space/create/create.go @@ -3,9 +3,10 @@ package create import ( "errors" "fmt" - "github.com/OctopusDeploy/cli/pkg/apiclient" "strings" + "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/OctopusDeploy/cli/pkg/cmd" "github.com/OctopusDeploy/cli/pkg/cmd/tenant/shared" "github.com/OctopusDeploy/cli/pkg/util" @@ -89,8 +90,8 @@ func NewCmdCreate(f factory.Factory) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&createFlags.Name.Value, createFlags.Name.Name, "n", "", "Name of the space") flags.StringVarP(&createFlags.Description.Value, createFlags.Description.Name, "d", "", "Description of the space") - flags.StringSliceVarP(&createFlags.Teams.Value, createFlags.Teams.Name, "t", nil, "The teams to manage the space (can be specified multiple times)") - flags.StringSliceVarP(&createFlags.Users.Value, createFlags.Users.Name, "u", nil, "The users to manage the space (can be specified multiple times)") + flags.StringArrayVarP(&createFlags.Teams.Value, createFlags.Teams.Name, "t", nil, "The teams to manage the space (can be specified multiple times)") + flags.StringArrayVarP(&createFlags.Users.Value, createFlags.Users.Name, "u", nil, "The users to manage the space (can be specified multiple times)") return cmd } diff --git a/pkg/cmd/tenant/connect/connect.go b/pkg/cmd/tenant/connect/connect.go index ad9f325d..0776befb 100644 --- a/pkg/cmd/tenant/connect/connect.go +++ b/pkg/cmd/tenant/connect/connect.go @@ -105,8 +105,8 @@ func ConfigureFlags(cmd *cobra.Command, connectFlags *ConnectFlags) { flags := cmd.Flags() flags.StringVarP(&connectFlags.Tenant.Value, connectFlags.Tenant.Name, "t", "", "Name or Id of the tenant") flags.StringVarP(&connectFlags.Project.Value, connectFlags.Project.Name, "p", "", "Name, ID or Slug of the project to connect to the tenant") - flags.StringSliceVarP(&connectFlags.Environments.Value, connectFlags.Environments.Name, "e", nil, "The environments to connect to the tenant (can be specified multiple times)") - flags.StringSliceVar(&connectFlags.Environments.Value, FlagAliasEnvironment, nil, "The environments to connect to the tenant (can be specified multiple times)") + flags.StringArrayVarP(&connectFlags.Environments.Value, connectFlags.Environments.Name, "e", nil, "The environments to connect to the tenant (can be specified multiple times)") + flags.StringArrayVar(&connectFlags.Environments.Value, FlagAliasEnvironment, nil, "The environments to connect to the tenant (can be specified multiple times)") flags.BoolVar(&connectFlags.EnableTenantDeployments.Value, connectFlags.EnableTenantDeployments.Name, false, "Update the project to support tenanted deployments, if required") } diff --git a/pkg/util/pflagaliases.go b/pkg/util/pflagaliases.go index 79350238..d3f40321 100644 --- a/pkg/util/pflagaliases.go +++ b/pkg/util/pflagaliases.go @@ -1,6 +1,10 @@ package util -import "github.com/spf13/pflag" +import ( + "strings" + + "github.com/spf13/pflag" +) func AddFlagAliasesString(flags *pflag.FlagSet, originalFlag string, aliasMap map[string][]string, aliases ...string) { f := flags.Lookup(originalFlag) @@ -54,7 +58,10 @@ func ApplyFlagAliases(flags *pflag.FlagSet, aliases map[string][]string) { // predictable way that doesn't change. However, there is nothing in the pflag public API that would // allow us to do a better job, as flag values are only exposed via the `Value` interface which // only allows read/write of values using String. - _ = primaryFlag.Value.Set(aliasValueString[1 : len(aliasValueString)-1]) + aliasValues := strings.Split(aliasValueString[1:len(aliasValueString)-1], ",") + for _, aliasValue := range aliasValues { + _ = primaryFlag.Value.Set(aliasValue) + } } else { _ = primaryFlag.Value.Set(aliasValueString) }