Skip to content

feat(cli): print a profile's scope as dotenv lines with context --format env - #129

Draft
thebrandonlucas wants to merge 2 commits into
masterfrom
brandon/dev-2957-voltage-cli-no-way-to-hand-a-profiles-scope-to-another-tool
Draft

thebrandonlucas wants to merge 2 commits into
masterfrom
brandon/dev-2957-voltage-cli-no-way-to-hand-a-profiles-scope-to-another-tool

Conversation

@thebrandonlucas

Copy link
Copy Markdown
Contributor

Fixes DEV-2957
Closes #122

Problem

Profiles hold the CLI's scope, but other Voltage tools cannot read them. The voltage-api skill's helper takes scope only from VOLTAGE_* variables or a dotenv file. After switching profiles, a person or agent had to copy the IDs by hand or turn voltage context --json into variables with jq and knowledge of its shape. A forgotten copy left the helper on the old environment.

Behavior

voltage context --format env prints the effective organization, environment, and wallet as dotenv lines, under the names the helper reads (CONFIG_KEYS in its scripts/request.py):

$ voltage context --profile staging --wallet WALLET_ID --format env
VOLTAGE_ORGANIZATION_ID=ORG_ID
VOLTAGE_ENVIRONMENT_ID=ENV_ID
VOLTAGE_WALLET_ID=WALLET_ID
$ voltage context --profile staging --format env > scope.env
Case Result
A value is unset (no wallet, say) Its line is left out, never printed empty, because the helper treats an empty variable as an override. Nothing set prints nothing, exit 0.
More than one environment (repeated --env) error: --format env takes one environment, but 2 are selected, hint Select one with --env ENV_ID., exit 2, nothing on stdout.
With --json, --output, or --output-file, before or after context error: --format cannot be combined with --json (or the flag given), with a hint to redirect stdout, exit 2.
Credentials Never printed. context reads no saved secret, and neither does this format. The docs say the other tool needs a key from elsewhere, for the printed organization and environment.

Values resolve exactly as voltage context resolves them: flags, then the profile, then the VOLTAGE_* variables.

Design notes

  • LocalCommand::Context becomes Context(ContextFlags) with --format <FORMAT>, a ContextFormat value enum with one value, env. An enum leaves room for another format without a new flag.
  • Context::dotenv builds the lines from the resolved Context, so the format cannot drift from voltage context. startup::execute writes them with write_stdout instead of a result envelope.
  • The conflict with --json, --output, and --output-file is checked on the typed flags (ContextFlags::check, called from Invocation::from_matches). A clap conflicts_with on the subcommand flag does not see a global flag given before context, so voltage --json context --format env would have passed.
  • The help for voltage context gains a --format env > scope.env example; the help-examples test parses it.

Try it on staging

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

Use the organization and environment from context (or voltage organizations list --account me and voltage environments list --account me --org ORG_ID):

voltage profiles create try-it --account me --org ORG_ID --env ENV_ID
voltage context --profile try-it --format env

Expect: exactly two lines, VOLTAGE_ORGANIZATION_ID=ORG_ID and VOLTAGE_ENVIRONMENT_ID=ENV_ID, and nothing that looks like a token or key.

voltage context --profile try-it --wallet WALLET_ID --format env
voltage context --profile try-it --format env --env ENV_ID --env 00000000-0000-4000-8000-000000000000; echo "exit $?"
voltage --json context --profile try-it --format env; echo "exit $?"
voltage profiles delete try-it

Expect: a third line VOLTAGE_WALLET_ID=WALLET_ID; then --format env takes one environment, but 2 are selected and exit 2; then --format cannot be combined with --json and exit 2. The delete removes the profile.

Validation

  • cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (198 unit, 150 integration), and python3 scripts/check-coverage.py all pass.
  • New integration test context_env_format_prints_only_set_scope_and_never_a_credential: exact stdout for a profile plus --wallet, no saved or ambient key in it, only the organization when only --org is set, empty output when nothing is set, and exit 2 with empty stdout for two environments.
  • New unit test context_format_refuses_a_result_format_or_file_before_or_after_the_command: --json before and after context, -o table, and --output-file are each refused with the flag named; context --json alone still parses; --format shell is rejected by clap. The parse test also checks --format env parses to ContextFormat::Env.
  • CRAP (scripts/crap-report.sh, cargo-llvm-cov 0.8.5, knots 1.16.0): 844 of 1055 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: startup::execute 16.0 (was 14.0, at 100% coverage), context::inspect 13.01, Invocation::from_matches 7.01, ContextFlags::check 5.0, Context::dotenv 2.0.

Limits

  • When stdout is redirected (> scope.env), an error is reported as JSON on stderr, like every other command whose stdout is not a terminal. It is still exit 2 with nothing written to stdout.
  • With DEV-2956 (Commands ignore VOLTAGE_* variables under a profile without a warning #121) merged as well, --format env under a profile also gets the stderr warning for each ignored VOLTAGE_* variable, which is the case where handing the scope over matters most.

Checklist

  • User-visible change: a guide or reference under docs/ and CHANGELOG.md (Unreleased) are updated. (docs/guides/login-and-profiles.md, docs/guides/scripting.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 staging steps above were not run by the author.

…mat env

Other Voltage tools, such as the voltage-api skill's helper, take scope
only from VOLTAGE_* variables or a dotenv file, so handing them a
profile's scope meant copying IDs by hand or parsing `context --json`.
`voltage context --format env` prints the effective organization,
environment, and wallet under those names. It leaves out unset values,
never prints a credential, refuses more than one environment with exit
code 2, and refuses --json, --output, and --output-file before or after
the command.
The hint after `profiles create` repeats --config-dir, which the
staging and local wrappers refuse. Passing the directory as a variable
keeps the hint runnable through the wrappers.
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.

No way to hand a profile's scope to another tool

1 participant