Skip to content

fix(cli): warn when a profile or flag overrides a set VOLTAGE_* variable - #128

Merged
thebrandonlucas merged 5 commits into
brandon/dev-2954-voltage-cli-accept-all-on-environments-list-and-stopfrom
brandon/dev-2956-voltage-cli-commands-ignore-voltage_-variables-under-a
Nov 4, 2026
Merged

thebrandonlucas merged 5 commits into
brandon/dev-2954-voltage-cli-accept-all-on-environments-list-and-stopfrom
brandon/dev-2956-voltage-cli-commands-ignore-voltage_-variables-under-a

Conversation

@thebrandonlucas

@thebrandonlucas thebrandonlucas commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes DEV-2956
Closes #121

Problem

With --profile, or with a flag such as --wallet, the CLI ignores a set VOLTAGE_ORGANIZATION_ID, VOLTAGE_ENVIRONMENT_ID, VOLTAGE_WALLET_ID, VOLTAGE_API_KEY, or VOLTAGE_CONFIG_DIR. Only voltage context said so, in ignored_variables. The voltage-api skill's helper reads the same names and lets them win, so in one shell the helper and the CLI could act on different wallets without any sign.

Behavior

Every command that reads the configuration prints one stderr line per ignored variable, before it prompts or sends a request:

$ VOLTAGE_ENVIRONMENT_ID=ENV_A VOLTAGE_WALLET_ID=WALLET_A voltage wallets list --profile staging
warning: VOLTAGE_ENVIRONMENT_ID is set but ignored because --profile staging is selected
warning: VOLTAGE_WALLET_ID is set but ignored because --profile staging is selected
$ VOLTAGE_WALLET_ID=WALLET_A voltage wallets get --wallet WALLET_B
warning: VOLTAGE_WALLET_ID is set but ignored because --wallet is given
Variable Ignored when Warning says
VOLTAGE_ORGANIZATION_ID, VOLTAGE_ENVIRONMENT_ID, VOLTAGE_WALLET_ID --profile is selected, or --org / --env / --wallet is given --profile NAME is selected, or --org is given (and so on)
VOLTAGE_API_KEY --profile or --account --profile NAME is selected or --account is given
VOLTAGE_CONFIG_DIR --config-dir --config-dir is given
  • stdout and --json results are unchanged. The warning is a stderr line, warning: in the caution color on a terminal, plain when redirected.
  • --quiet keeps it. --quiet hides optional progress and notices; docs/guides/scripting.md says it never hides warnings, and the offset-pagination deprecation already follows that. A silent override is what this issue is about, so hiding it behind --quiet would bring the problem back for scripts.
  • A variable that is actually used gets no warning.
  • auth import-key and profiles create save the organization, environment, and account that their flags name, so they do not warn about those flags. They still warn about a profile or --config-dir.
  • scripts/voltage-staging and scripts/voltage-local now pass their state directory as VOLTAGE_CONFIG_DIR, not --config-dir. Hints the CLI prints, such as the one after profiles create, then do not name a flag the wrapper refuses. feat(cli): print a profile's scope as dotenv lines with context --format env #129 makes the same change, so whichever PR merges second merges cleanly.
  • price, convert, completions, and bare voltage read no scope, so they never warn.

Design notes

  • config::ignored_variables now returns IgnoredVariable { name, precedence }, where Precedence is Flag("--wallet") or Profile, decided from the same ScopeSources as before. auth::ignored_api_key replaces ignores_ambient_api_key the same way.
  • context::ignored_variables joins the two lists. voltage context maps it to names (its JSON is unchanged), and Session::open passes it to context::warn_ignored right after the scope is resolved. One list feeds both, so the warning and voltage context cannot disagree.
  • The profile name in the warning goes through Line::text, which scrubs control characters.
  • Not done: the issue also suggested adding the list to error.detail of --json errors. That changes the error contract, so it is left for a follow-up if wanted.

Try it on staging

Setup: Try a pull request on staging

alias voltage="$PWD/scripts/voltage-staging"
voltage --build
voltage login --account me --credential-store file

The wrapper passes only the VOLTAGE_* variables in .env, so these steps need VOLTAGE_ORGANIZATION_ID and VOLTAGE_ENVIRONMENT_ID set there. They are optional lines in .env.example. Any valid UUIDs show the warnings; use your real IDs from voltage organizations list --account me and voltage environments list --account me --org ORG_ID so the lists succeed.

voltage context --account me

Expect: no warning: line. organization_id and environment_ids show source environment.

voltage wallets list --account me --org ORG_ID

Expect, before the wallet table: warning: VOLTAGE_ORGANIZATION_ID is set but ignored because --org is given.

voltage profiles create try-it --account me --org ORG_ID --env ENV_ID
voltage wallets list --profile try-it --quiet
voltage wallets list --profile try-it --json > /dev/null
voltage profiles delete try-it

Expect:

  • profiles create prints no warning, because its flags name what it saves.
  • Both lists start with one warning: VOLTAGE_… is set but ignored because --profile try-it is selected line for each VOLTAGE_* variable in .env, --quiet included.
  • With --json, the warnings are still on stderr, and stdout has only the JSON envelope.
  • The delete removes the profile.

Validation

Run on the head after merging master (9c7bc29):

  • cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (202 unit, 150 integration), and python3 scripts/check-coverage.py all pass.
  • New unit tests in context: the warning text for a profile, a flag, and --account; the sentence without a profile name; and that a profile name with escape characters is scrubbed (checked on the unstripped line).
  • Integration: profile_credentials_override_ambient_key_and_scope checks the exact stderr under --profile --quiet (organization, environment, and API key, in that order), and that stdout is still the JSON result. a_flag_over_a_set_variable_warns_and_a_used_variable_does_not checks --org over a set variable, and no warning when the variable is used. profiles create and auth import-key print no warning about their own flags. 9c7bc29 adds a check that profiles create still warns about --config-dir over a set VOLTAGE_CONFIG_DIR, and not about --org.
  • Staging, with the PR's binary: context with a used VOLTAGE_ORGANIZATION_ID printed no warning. wallets list --org over a set variable warned. context --profile NAME --quiet warned once per ignored variable on stderr, and stdout had only the result.
  • CRAP (scripts/crap-report.sh, cargo-llvm-cov 0.8.5, knots 1.16.0): 853 of 1065 functions measured, 0 violations. The highest score is 18.10, wait_for_payment in src/api.rs, which this PR does not change. Changed functions: context::inspect 12.01, Session::open 6.0, ignored_api_key 4.0, config::ignored_variables 3.0, ignored_warning and warn_ignored 2.0, saves_selection 1.0.

Checklist

  • User-visible change: a guide or reference under docs/ and CHANGELOG.md (Unreleased) are updated. (docs/guides/login-and-profiles.md, docs/reference/environment.md)
  • The verification gate in docs/development.md passes.
  • The diff was reviewed against its base with the voltage-pr-review skill, and every new error and early-return path has a test.
  • CRAP report: highest 18.10 (wait_for_payment, unchanged); no function at or above 20.
  • Checks not run, and why: the profiles create try-it staging steps were not run, to avoid changing the shared staging config. The warning is not tested on a real terminal (color) by an automated test; the color comes from the existing important_line path.

Stack

Stack #135, layer 3 of 9 (bottom targets master):

# PR Change
1 #97 Staging setup and a Try it section for each PR
2 #120 --all on organizations, environments, and profiles list
3 #128 (this PR) Warn when a profile or flag overrides a set VOLTAGE_* variable
4 #129 voltage context --format env
5 #127 Replace hand-rolled terminal code with crossterm
6 #126 Pick the wallet, organization, or environment to show
7 #130 Prefilled GitHub issue links from voltage feedback and panics
8 #123 voltage environments create
9 #131 Replace flake.nix with a Kaifile

The layers are chained with merge commits, because history is not rewritten. Use squash and merge, bottom first.

Under --profile, or with a flag such as --wallet, commands ignored set
VOLTAGE_* scope, key, and directory variables without saying so; only
`voltage context` listed them. The voltage-api skill's helper lets the
same variables win, so the two tools could reach different wallets in
one shell. Every command that reads the configuration now prints one
stderr warning per ignored variable before it prompts or sends a
request, from the same list `voltage context` reports. --quiet keeps
it, as it keeps other warnings; stdout is unchanged.
…save

Both commands save the organization, environment, and account their
flags name, so warning that those flags override VOLTAGE_* variables
was noise. They still warn about a profile or --config-dir.

The staging and local wrappers now pass their directory as
VOLTAGE_CONFIG_DIR instead of --config-dir, so the hint after
`profiles create` no longer names a flag the wrappers refuse.
…-list-and-stop' into brandon/dev-2956-voltage-cli-commands-ignore-voltage_-variables-under-a

# Conflicts:
#	CHANGELOG.md

@tee8z tee8z left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at 89b144a. I traced the precedence through sourced_scope: a flag gives Precedence::Flag, and a profile gives Unset for an ambient value, which maps to Profile, so the warning names the right cause in each case. context::ignored_variables feeds both the warning and voltage context, so they cannot disagree. The saves_selection exemption is tested for profiles create and auth import-key, including the --config-dir warning that still applies. Keeping the warning under --quiet matches docs/guides/scripting.md.

Non-blocking: retain matches Precedence::Flag("--config-dir") by its string. variable.name == "VOLTAGE_CONFIG_DIR" would say the same thing without depending on the flag text.

CRAP on this head: 857 of 1069 functions measured, 0 violations. Highest: 18.10 wait_for_payment (unchanged). CI is green.

@thebrandonlucas
thebrandonlucas merged commit 40cead6 into master Nov 4, 2026
7 checks passed
@thebrandonlucas
thebrandonlucas deleted the brandon/dev-2956-voltage-cli-commands-ignore-voltage_-variables-under-a branch November 4, 2026 22:59
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.

Commands ignore VOLTAGE_* variables under a profile without a warning

2 participants