Repository navigation
feat(cli): offer a pinned profile after login on a terminal - #75
Conversation
After `voltage login` on a terminal, the CLI offers to save a profile pinned to an organization and environment, so later commands need only `--profile NAME`. It reuses the scope picker, then asks for the name. Esc skips it, and a failure leaves the login saved and names `voltage profiles create`. Ctrl-C exits 130 and says that the login is saved. Nothing is offered when a profile already uses the login, off a terminal, with `--json`, or with `--no-input`. The profile is saved through `Settings::create_profile`, which `profiles create` now uses too: it takes the credential lock and reads the configuration again before adding the profile, so a change another command made while the prompt was open is kept, and a name it took is refused with the same message. The picker now takes the only organization or environment without asking, and says so. A wallet is still always asked for, because a payment spends from it.
8464d7e to
ff8b488
Compare
ff8b488 to
7c1a78a
Compare
tee8z
left a comment
There was a problem hiding this comment.
Approved 7c1a78a against feat/cli-wallets-all-orgs (#74 24cd775). The changes requested on #73 still block this stack.
- The offer runs only when
can_askis true and no profile already uses the login, so--json,--no-input, a pipe and a re-login are unchanged, and send no extra request. - The login is saved before the offer starts. Esc, no environments, a blank or taken name, or a listing failure each leave it saved with a
profiles createnotice, and the login exits 0. - Ctrl-C at a prompt or during the offer's requests reports
profile_offer_interrupted.profile_offeris kept apart fromsession, so the offer's own refresh cannot clear it. The SIGINT test covers that. Settings::create_profiletakes the lock, re-reads the configuration and checks the name again, andprofiles createnow uses it too. A concurrent change is kept, and a concurrent name is refused. Both cases are tested.- Taking the only organization or environment says so on stderr. A wallet is still always asked for, which keeps a keypress before a payment.
Nonblocking: in profiles(), the if let early returns followed by a _ => arm hide future ProfileCommand variants. One match with an explicit arm per variant, each taking the lock where it needs it, would let the compiler flag a new variant.
Validation on this head, in nix develop: cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (130 unit, 119 integration) and python3 scripts/check-coverage.py passed. CRAP: 605 measured functions, none at or above 20, highest wait_for_payment at 19.60 and endpoint at 18.00 (from #74's flag); 173 functions were unmeasured. CI is green.
7c1a78a to
023127a
Compare
023127a to
195f877
Compare
Stack
One stack, merged bottom up:
master)wallets list --all-orgs(base fix(cli): name each candidate's environment when --env is not given #77)Design
This changes login and picker behavior, so here is the design before the code.
Current behavior (checked on
master+ #74):voltage loginsaves the login and printsaccount,email,authenticated,replaced. It pins no organization or environment: a login'sAccounthasorganization_id: None.--profile NAME. There is no default profile, andvoltage profiles createis the only way to make one.New behavior (terminal only):
Save a profile for this login, so later commands need only --profile NAME. Press Esc to skip.Organization: Acme ID (the only one). With several, the picker asks.Profile name:defaulton Enter.Saved profile NAME. Use it with --profile NAME.The login result showsprofile NAME.No profile was saved[: why]. Create one later with voltage profiles create NAME --account ACCOUNT.Login still exits 0.Interrupted while saving a profile; the login for NAME is savedand thevoltage profiles createhint.SubmissionStatemarks the offer as under way, apart from the session change that the offer's own token refresh sets and settles.The picker change applies to every command: the only organization or environment is taken without asking. A wallet is always asked for, even when there is only one, because a payment with
--executespends from it, and a keypress is the confirmation.Saving: the profile is saved through
Settings::create_profile, whichvoltage profiles createnow uses too. It takes the credential lock, re-readsconfig.toml, checks the name again, then inserts and saves. A change another command made while the prompt was open is kept, and a name it took is refused withProfile NAME already exists. Both paths now use that message, whereprofiles createused to sayProfile already exists.What stays the same:
--jsonor--output json|ndjson, with stdout piped, or with--no-input: no prompt, no extra request.voltage login --jsonoutput is unchanged (theprofilefield is omitted whenNone).--profile. I did not add a default profile: it would change which credential every command uses, and it could shadowVOLTAGE_API_KEYin CI. That is a separate product decision.Checks
On head
7c1a78a: the gate passes innix develop(130 unit, 119 integration), and CRAP on this tip shows 0 of 605 measured functions at or above 20 (highestwait_for_paymentat 19.60). The new SIGINT test fails without the fix, withInterrupted before any resource change was submitted.voltage-pr-reviewself-review against feat(cli): list wallets in every organization with --all-orgs #74's head, with the Rust style checklist.profiles createwith a duplicate name, no environments, a profile that already uses the login (no offer, one/users/currentrequest), and the only wallet still asked for. The existing picker tests now assert the "(the only one)" notices, and the Esc test uses two organizations and two environments so that each picker really asks.nix develop:cargo fmt --check,cargo clippy --locked --all-targets -- -D warnings,cargo machete --with-metadata,cargo test --locked, andpython3 scripts/check-coverage.pyall pass.ff8b488: 0 of 602 measured functions at or above 20. The highest score is 19.60 forwait_for_payment, unchanged.