Skip to content

fix: accept comma-separated values on deployment target and scope flags - #692

Draft
NickJosevski wants to merge 1 commit into
mainfrom
nj/issue-556
Draft

fix: accept comma-separated values on deployment target and scope flags#692
NickJosevski wants to merge 1 commit into
mainfrom
nj/issue-556

Conversation

@NickJosevski

Copy link
Copy Markdown
Contributor

Fixes #556

Root cause

--deployment-target is declared as a pflag StringArray, which does not split on commas:

  • pkg/cmd/release/deploy/deploy.go:173flags.StringArrayVarP(&deployFlags.DeploymentTargets.Value, ...)

Its legacy aliases are registered as StringSlice, which does split on commas:

  • pkg/util/pflagaliases.go:39flags.StringSlice(alias, nil, ""), used by AddFlagAliasesStringSlice
  • pkg/cmd/release/deploy/deploy.go:78FlagAliasSpecificMachines = "specificMachines" // octo wants a comma separated list ... but CSV also works because pflag does it for free

So today --specificMachines "ABC,XYZ" and --target "ABC,XYZ" both work, but the primary
--deployment-target "ABC,XYZ" sends the literal string ABC,XYZ to the server, producing
Unable to locate deployment target(s) named 'ABC,XYZ'. The bug is an inconsistency between a
flag and its own aliases, not a missing feature.

What changed

  • New executionscommon.ExpandCommaSeparated — splits each entry on commas, trims surrounding
    whitespace, drops blanks, preserves order and duplicates. Nil in, nil out.
  • Applied at the top of deployRun and runbookRun to: --environment, --tenant,
    --tenant-tag, --deployment-target / --run-target, --exclude-deployment-target /
    --exclude-run-target.
  • Help text for those flags now reads "(can be specified multiple times, or as a comma-separated list)".

Deliberately not applied to --variable (values are arbitrary text), --skip (step names),
--package / --git-resource (structured specs), --deployment-freeze-name, or --runbook-tag.

The repeat-the-flag form is unchanged, so existing scripts keep working. Expansion happens before
options is built, so the interactive backfill into resolvedFlags and
flag.GenerateAutomationCmd see the already-split values; GenerateAutomationCmd emits []string
as one --flag 'value' per element (pkg/util/flag/flag.go:77-84), so the echoed automation
command stays correct and re-runnable — --deployment-target 'ABC,XYZ' in becomes
--deployment-target 'ABC' --deployment-target 'XYZ' out.

Test evidence

go build ./... — clean.
go test ./pkg/... — 64 packages ok, 0 failures.

New tests:

  • TestExpandCommaSeparated (pkg/executionscommon/executionscommon_test.go) — comma form,
    repeated form, mixed form, values containing spaces, whitespace trimming around the comma,
    tenant-tag canonical values, blank entries, nil.
  • release deploy accepts comma-separated targets and environments; untenanted — asserts the
    wire request carries SpecificMachineNames: ["first Machine", "second Machine", "third Machine"]
    from --deployment-target "first Machine, second Machine" --deployment-target "third Machine".
  • release deploy accepts comma-separated tenants and tenant tags; tenanted.
  • runbook run accepts comma-separated environments and targets.

Open questions / options

1. Scope — this one flag, or the whole multi-value execution flag set?

  • Just --deployment-target: smallest blast radius, but leaves --environment "dev,test"
    still broken while --env "dev,test" works, which is the same bug wearing a different hat.
  • All multi-value flags including --variable and --skip: consistent, but actively harmful —
    --variable "Note:a,b" would silently become two malformed variables.
  • What this PR does — the five "who/where" selection flags on both execution commands.
    Recommendation: keep this. Four of the five (--environment, --tenant-tag, and both
    target flags) already accept CSV through their own legacy aliases, so this removes an
    inconsistency rather than inventing new parsing. --tenant has no alias and is the one genuinely
    new behaviour — included because splitting environments but not tenants would be arbitrary.
    Happy to drop --tenant if reviewers prefer strict "alias precedent only".
    --runbook-tag was left out (no legacy alias, selects runbooks rather than deployment scope) —
    flagging it since it is shaped exactly like --tenant-tag and could reasonably be included.

2. Values that legitimately contain a comma.

A target/environment/tenant named Web, Prod, or a tenant tag whose tag name contains a comma,
can no longer be passed to these flags at all — there is no escape hatch. Options:

  • Accept it (this PR). Commas in these names are rare, and for --environment/--tenant-tag/
    the target flags the aliases already behaved this way, so the regression surface is --tenant
    plus users who were passing commas through the primary flag names.
  • Support a backslash escape (--deployment-target 'Web\, Prod'), mirroring the escaping
    release create --package already does for colons. Costs a documented syntax users must learn.
  • Switch the flags to pflag StringSlice instead of a helper. Gets CSV-quoting for free
    (--deployment-target '"Web, Prod",Other') via encoding/csv, but the quoting is obscure,
    it changes --help type display from stringArray to strings, and it silently reinterprets
    any existing value containing a quote character.

Recommendation: ship as-is, and add escaping later only if a real customer hits a comma in a
name. Worth a reviewer's call since it is technically a breaking change for such names.

🤖 Generated with Claude Code

`--deployment-target "ABC,XYZ"` was sent to the server as a single target
name because the flag is a pflag StringArray, while its legacy aliases
(`--target`, `--specificMachines`) are StringSlice and already split on
commas. Expand comma-separated values for the environment, tenant,
tenant-tag and target flags on `release deploy` and `runbook run`, so the
comma form matches the repeat-the-flag form. Values that can legitimately
contain a comma (--variable, --skip, package/git-resource specs) are left
alone.

Fixes #556

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support comma-delimited values on octopus release deploy --deployment-target command

1 participant