You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue tracks the implementation of the azdo pipelines variable-group variable update command.
Command Description
Update an existing variable within a variable group. The Azure CLI supports renaming, value changes, and secret flag updates while preventing duplicate keys (source). azdo should mirror this capability with strong validation and consistent resolver helpers.
Important REST constraint:
Azure DevOps REST never returns secret variable values. Secret values are write-only: the command may send them to the API, but must not expect to read them back. Human-readable output must redact secret values (e.g., ***), and JSON output must never contain a secret value.
--name string (required): Variable key to update (matched case-insensitively).
--new-name string: Rename the variable (case-insensitive uniqueness enforced).
--value string: Replace the stored value. If the variable is secret, this value is write-only and must not be echoed.
--secret bool: Toggle secret flag (VariableValue.IsSecret). Tri-state: only apply when explicitly set (use Flags().Changed("secret")).
--read-only bool: Toggle read-only flag (VariableValue.IsReadOnly). Tri-state: only apply when explicitly set (use Flags().Changed("read-only")).
--prompt-value: For setting/updating a secret value without --value, prompt securely (error if prompting is not possible).
--clear-value: Clear the stored value for a non-secret variable only; requires confirmation via --yes.
--yes: Skip confirmation prompts for destructive operations (--clear-value).
--from-json string: Apply updates from JSON (see “--from-json semantics”).
JSON export flags (--json, --jq, --template) registered via util.AddJSONFlags.
At least one of --new-name, --value, --secret, --read-only, --prompt-value, --clear-value, or --from-json must be supplied.
--from-json semantics (deterministic)
--from-json accepts:
a file path
- to read from stdin
if the path does not exist, treat the argument as inline JSON
The JSON payload must be a single object with these keys (all optional; absent = “no change”):
newName (string)
value (string)
secret (bool)
readOnly (bool)
clearValue (bool)
Mutual exclusivity:
If --from-json is set, reject any combination with: --new-name, --value, --secret, --read-only, --prompt-value, --clear-value.
Validation rules:
Reject payloads that also try to specify name (the variable key is always provided by --name).
Reject clearValue=true together with value (ambiguous).
If secret=true is being set and neither value is present in JSON nor --prompt-value is available (not allowed with --from-json), return a validation error (write-only secret value required).
Behavior
Parse [ORGANIZATION/]PROJECT/VARIABLE_GROUP_ID_OR_NAME using util.ParseProjectTargetWithDefaultOrganization; wrap parse errors with util.FlagErrorWrap.
Resolve the variable group ID-or-name using the shared helper shared.ResolveVariableGroup (do not re-implement ID/name resolution).
Fetch the variable group and locate the existing variable key case-insensitively; error if missing.
If --new-name (or JSON newName) is set:
Ensure no other variable exists with that name (case-insensitive) before applying the rename.
Rename by removing the old key from the variables map and inserting the updated value under the new key.
Apply only explicitly specified changes:
Bool flags are tri-state (only apply if Flags().Changed(...) or JSON key present).
For --prompt-value: prompt securely and use the entered value (intended for secret rotation); never log or echo it.
--clear-value:
Only valid for non-secret variables.
Prompt unless --yes is set. Prompt text: Clear value of variable 'VARIABLE_NAME' in group 'VARIABLE_GROUP'?. Return util.ErrCancel on decline.
Azure Key Vault variable groups:
If the variable group type indicates Azure Key Vault, reject attempts that modify variable values (e.g., --value, --prompt-value, --clear-value) and return a clear error message.
Persist changes via TaskAgent.UpdateVariableGroup.
Output (single-object command):
Default output is a Go text template summarizing the updated variable (name, group, secret/read-only flags). Never print a secret value; print *** for secret value fields.
Reuse the same masking/redaction behavior already implemented by internal/cmd/pipelines/variablegroup/variable/list/list.go so outputs are consistent across variable-group variable commands.
JSON output:
Emit the updated SDK variable group model returned by UpdateVariableGroup.
util.AddJSONFlags must list fields that match the SDK JSON tags (field-level contract). Suggested list:
Wire command: internal/cmd/pipelines/variablegroup/variable/variable.go must AddCommand(update.NewCmd(ctx)) and be reachable from azdo pipelines variable-group variable.
Parse scope: util.ParseProjectTargetWithDefaultOrganization(ctx, targetArg); wrap parse errors with util.FlagErrorWrap.
Register it from internal/cmd/pipelines/variablegroup/variable/variable.go so azdo pipelines variable-group variable update is part of the CLI hierarchy.
SDK / Client Requirements
Requires the Task Agent client (ClientFactory().TaskAgent(...)). If the client is missing, follow "Handling Missing Azure DevOps SDK Clients" in AGENTS.md.
This issue tracks the implementation of the
azdo pipelines variable-group variable updatecommand.Command Description
Update an existing variable within a variable group. The Azure CLI supports renaming, value changes, and secret flag updates while preventing duplicate keys (source).
azdoshould mirror this capability with strong validation and consistent resolver helpers.Important REST constraint:
***), and JSON output must never contain a secret value.azdoCommand SignatureFlags:
--name string(required): Variable key to update (matched case-insensitively).--new-name string: Rename the variable (case-insensitive uniqueness enforced).--value string: Replace the stored value. If the variable is secret, this value is write-only and must not be echoed.--secret bool: Toggle secret flag (VariableValue.IsSecret). Tri-state: only apply when explicitly set (useFlags().Changed("secret")).--read-only bool: Toggle read-only flag (VariableValue.IsReadOnly). Tri-state: only apply when explicitly set (useFlags().Changed("read-only")).--prompt-value: For setting/updating a secret value without--value, prompt securely (error if prompting is not possible).--clear-value: Clear the stored value for a non-secret variable only; requires confirmation via--yes.--yes: Skip confirmation prompts for destructive operations (--clear-value).--from-json string: Apply updates from JSON (see “--from-json semantics”).--json,--jq,--template) registered viautil.AddJSONFlags.At least one of
--new-name,--value,--secret,--read-only,--prompt-value,--clear-value, or--from-jsonmust be supplied.--from-jsonsemantics (deterministic)--from-jsonaccepts:-to read from stdinnewName(string)value(string)secret(bool)readOnly(bool)clearValue(bool)--from-jsonis set, reject any combination with:--new-name,--value,--secret,--read-only,--prompt-value,--clear-value.name(the variable key is always provided by--name).clearValue=truetogether withvalue(ambiguous).secret=trueis being set and neithervalueis present in JSON nor--prompt-valueis available (not allowed with--from-json), return a validation error (write-only secret value required).Behavior
[ORGANIZATION/]PROJECT/VARIABLE_GROUP_ID_OR_NAMEusingutil.ParseProjectTargetWithDefaultOrganization; wrap parse errors withutil.FlagErrorWrap.shared.ResolveVariableGroup(do not re-implement ID/name resolution).--new-name(or JSONnewName) is set:Flags().Changed(...)or JSON key present).--prompt-value: prompt securely and use the entered value (intended for secret rotation); never log or echo it.--clear-value:--yesis set. Prompt text:Clear value of variable 'VARIABLE_NAME' in group 'VARIABLE_GROUP'?. Returnutil.ErrCancelon decline.--value,--prompt-value,--clear-value) and return a clear error message.TaskAgent.UpdateVariableGroup.***for secret value fields.internal/cmd/pipelines/variablegroup/variable/list/list.goso outputs are consistent across variable-group variable commands.UpdateVariableGroup.util.AddJSONFlagsmust list fields that match the SDK JSON tags (field-level contract). Suggested list:id,name,type,description,variables,variableGroupProjectReferences,providerData,createdBy,createdOn,modifiedBy,modifiedOnImplementation Notes (filled checklist)
internal/cmd/pipelines/variablegroup/variable/update/update.go(type opts struct, NewCmd(ctx), run(ctx, opts)).internal/cmd/pipelines/variablegroup/variable/variable.gomustAddCommand(update.NewCmd(ctx))and be reachable fromazdo pipelines variable-group variable.util.ParseProjectTargetWithDefaultOrganization(ctx, targetArg); wrap parse errors withutil.FlagErrorWrap.ctx.ClientFactory().TaskAgent(ctx.Context(), scope.Organization).--prompt-valueis supported/used.ios.StartProgressIndicator(); defer ios.StopProgressIndicator()and stop before printing.--from-jsonis set: load JSON (file,-, or inline), validate keys and apply changes; reject mixing with other flags.Flags().Changed(...)) and explicitly-present JSON keys.--clear-value: confirm unless--yes; returnutil.ErrCancelon decline.TaskAgent.UpdateVariableGroup.internal/cmd/pipelines/variablegroup/variable/update/update.tpland render it (single-object output).util.AddJSONFlagslist matches the SDK JSON tags used in output.internal/cmd/pipelines/variablegroup/variable/update/update_test.go.--from-jsonmutual exclusivity + validation, secret value redaction in output.Command Wiring
internal/cmd/pipelines/variablegroup/variable/update/update.goexposingNewCmd(ctx util.CmdContext) *cobra.Command.internal/cmd/pipelines/variablegroup/variable/variable.gosoazdo pipelines variable-group variable updateis part of the CLI hierarchy.SDK / Client Requirements
ClientFactory().TaskAgent(...)). If the client is missing, follow "Handling Missing Azure DevOps SDK Clients" inAGENTS.md.References
variable_group_variable_update