Repository navigation
feat(cli): pick the wallet, organization, or environment to show on a terminal - #126
Conversation
…-the-cli' into brandon/dev-2953-voltage-cli-add-environments-create Resolve environments create against the layers below it: - EnvironmentCommand flattens DiscoveryCommand (list, get) from #126 and adds create, so `environments list` keeps the --all that #120 added and `environments get` keeps the picker. - Resolver::discover keeps #126's DiscoveryCommand argument and uses this branch's requires_login and login_organization helpers. - pick asks for an environment only for `environments get`, and #120's parse test matches EnvironmentCommand::Discovery(DiscoveryCommand::List). - CHANGELOG, docs/commands.md, the login guide, and check-coverage.py keep both the get and create entries.
tee8z
left a comment
There was a problem hiding this comment.
Approved at 51e7afb. Moving the missing-wallet error from parsing to pick::fill is safe: Session::open calls fill on every path, and wallet_target raises missing_wallet off a terminal, for JSON, and for every non-GET wallet operation, before any credential is resolved or request is sent. The picked wallet goes to resource_id, never the scope, so VOLTAGE_WALLET_ID still cannot aim a wallet command. organizations get and environments get reuse pick::needs, and the not-visible path is tested.
Non-blocking: discover finds the item by comparing id.to_string() with the API string. That depends on the API returning lowercase UUIDs. Parsing item["id"] as a Uuid would not.
CRAP: not run on this head yet; I will add the result when it finishes. CI is green.
|
CRAP on 51e7afb: 875 of 1093 functions measured, 0 violations. Highest: 18.10 |
|
Took the non-blocking suggestion in 8d9618b. |
… terminal On a terminal, a wallet read without WALLET_ID or --wallet (wallets get, wallets ledger list, wallets policies get, wallets payments summary) opens the wallet picker and shows the wallet picked. New organizations get and environments get show the organization or environment the scope selects, and pick it on a terminal when none is selected. Wallet changes still name their wallet. Off a terminal, with --json, --output json|ndjson, or --no-input, nothing is asked and a missing ID fails before any request, as before.
ce12d7a to
49590cc
Compare
tee8z
left a comment
There was a problem hiding this comment.
Reviewed 49590cc against #127 (5f64b27). No blocking findings in this layer.
Wallet reads can pick their explicit target; wallet mutations still fail before discovery when the target is absent. The PTY tests exercise wallet/org/env selection, Esc, and the machine-output/no-input paths.
Local gate passed: formatting, Clippy with warnings denied, dependency hygiene, full tests (210 unit + 156 integration), and contract/docs generation checks. Required CRAP check passed: 877/1097 functions measured, 220 unmeasured, no scores >=20; highest 18.10 (wait_for_payment).
Limits: Linux mock-service/PTY validation; no live staging requests or manual Windows/macOS run. Approval applies to this incremental stack layer.
Fixes DEV-2903
Problem
#22 made a missing
--org,--env, or--walletopen a picker, but only when a command could not run without it. You still could not browse:voltage wallets getwithout an ID failed withwallets get needs a wallet ID … voltage wallets list shows the IDs, and there was no way to look at one organization or environment at all. You still had to copy UUIDs out of a list by hand.Behavior
On a terminal, a read that names one resource but has no ID now picks it with the existing picker, then shows it:
wallets get,wallets ledger list,wallets policies get,wallets payments summarywithoutWALLET_ID/--walletneeds a wallet IDWallet:, then shows that walletorganizations get(new)--orgor the profile selects, or asksOrganization:environments get(new)--envor the profile selects, or asksOrganization:/Environment:wallets update/deletewithout an IDAfter a pick, the CLI prints the usual
Next time, pass --wallet ID …notice. Esc ends with the same error as before.Nothing changes for scripts (DEV-2871). Off a terminal, with
--json,--output json|ndjson, or--no-input, nothing is asked. A wallet read without an ID still fails with exit 2 and the same message and hint, before any credential is resolved or request is sent.organizations getandenvironments getwithout a selection report the usual--org is requiredandExactly one --env is requirederrors.Why this design
get. Every command that needs scope already picks it, and the one command that failed for a missing ID with a "go copy it from the list" hint was a wallet read. So I extended that rather than makinglistinteractive or adding a copy-to-clipboard step. A list stays a list, which is safe to pipe.update,delete) still has to name its wallet. That keeps the existing rule that a delete is never aimed by ambient state, and keeps a picker out of the path of a change.organizations getandenvironments gettake no positional ID. They show the organization or environment the scope selects, so--org,--env, and profiles work as they do in every other command. The pickers then come for free frompick::needs. The auth service has no single-resource route, sogetfinds the item in the same listing thatlistuses, and reportsOrganization ID is not visible to this loginwhen it is not there.VOLTAGE_WALLET_ID. Same rule as feat(cli): pick a missing organization, environment, or wallet #22's--walletchange. The picked wallet goes into the command's own ID, not the scope (pick::Picked.wallet).Code
cli.rs: a wallet operation without an ID now parses toresource_id: Noneinstead of failing in clap validation. The error moves tocli::missing_wallet, whichpickraises.ListCommandbecomesDiscoveryCommand { List, Get }, with help examples for the new commands and forwallets get.pick.rs:wallet_targetdecides between picking and stopping (stopping for a change, off a terminal, or for JSON).asknow returnsPicked { flags, wallet }, sofillcan put the wallet in the scope or in the command's own ID.startup.rs:discoverserveslistandget.auth::Resolver::discovernames the subcommand in its API-key error (organizations get needs a browser login …).guides/login-and-profiles.md(pickers browse),guides/wallets.md, generatedcommands.md, and a CHANGELOG line.Checks
master(CHANGELOG conflict: kept both lines). On the merged head:cargo fmt --check,cargo clippy --locked --all-targets -- -D warnings,cargo machete --with-metadata,cargo test --locked(200 unit, 152 integration),python3 scripts/check-coverage.py: all pass.--jsonand--no-input(no prompt, no request);wallets delete(no prompt); pick an org fororganizations get; pick an env forenvironments get;--jsonwith no env (no prompt, no request).wallets ledger listwith no ID;organizations getwith a visible org, an org that is not visible, and no org; the API-key error fororganizations get.wallet_targetfor each read, change, and terminal/script case, and the newneeds.scripts/crap-report.sh, on the merged head): 0 of 851 measured functions at or above 20. Highest overall 18.10 (api.rswait_for_payment, unchanged). Highest changed:pick::ask14.00 andpick::fill13.00, both 100% covered;auth::Resolver::discover8,startup::discover7,pick::wallet_target5. Line coverage 97.97%.origin/masterwithvoltage-pr-reviewand the Rust style checklist.Try it on staging
Expect: an
Organization:picker. Type to filter, press Enter. The organization's fields follow, and thenNext time, pass --org ORG_ID …. With only one organization, it is taken without asking.Expect: an
Environment:picker, then the environment. Then aWallet:picker (name CURRENCY UUID), then the wallet card with balance and activity, as forwallets get WALLET_ID.Expect: no picker in any of these.
wallets get needs a wallet ID(orwallets delete needs a wallet ID), with the hint, and exit code 2.Merge order with #127
#127 now sits directly below this PR in stack #135, so the picker's pseudo-terminal tests (pick, Esc) run against #127's new terminal guard; the whole suite passes on this head. Merging the layers below also gave
DiscoveryCommand::List#120's--all(and updated #120's parse test toDiscoveryCommand::List) and kept #129'scontext --format envdispatch beside this PR'sdiscover.Open questions
wallets update/delete) pick too? They are describe-only without--execute, but I kept them explicit to stay conservative.payments get,webhooks get,quotes get) could pick the same way. I left them out: their lists can be long and paginated, and they have no names to filter on.Stack
Stack #135, layer 6 of 9 (bottom targets
master):--allonorganizations,environments, andprofiles listVOLTAGE_*variablevoltage context --format envvoltage feedbackand panicsvoltage environments createflake.nixwith a KaifileThe layers are chained with merge commits, because history is not rewritten. Use squash and merge, bottom first.