Skip to content

Commit 5282362

Browse files
feat(projects): prompt for the fields projects:update was not given
In a terminal, launch:projects:update now prompts for every updatable field not supplied as a flag - "Update project name (optional)" then "Update project description (optional)" - instead of failing with "Pass at least one of --name, --description". A blank answer, or one equal to the current value, leaves the field out; a flag value is always sent. Length limits are checked inside each prompt so an oversized answer re-prompts. With both flags supplied nothing is fetched or prompted. Success now prints one green "✔ Project updated successfully." in place of a line per field. When nothing is left to send the command prints a yellow "Project not updated. No changes were entered.", sends no PUT and exits 0. Without a terminal behaviour is unchanged: flags are sent as given and supplying neither is still a usage error (exit 2), now raised in run() because a static rule runs before a command can prompt. atLeastOneOf loses its only caller and is kept, listed under "Built ahead of use" in AGENTS.md. Adds green and yellow styles. Talisman flags secret-free lines in the touched files - the fixture project uid and lines containing "key" or "pass". .talismanrc allows exactly those lines, narrowed per file like the existing entries. #claude_code# 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8674855 commit 5282362

12 files changed

Lines changed: 514 additions & 107 deletions

‎.talismanrc‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ fileignoreconfig:
2323
- "headers: \\[\\{ key: '"
2424
- 'name="key"'
2525
- "drops a field with no key"
26+
- filename: src/commands/launch/projects/update.test.ts
27+
allowed_patterns:
28+
- "a1b2c3d4e5f60718293a4b5c"
29+
- "Pass at least one of --name, --description"
30+
- "Object\\.keys\\(ProjectsUpdate\\.flags\\)"
31+
- filename: test/integration/projects-update.test.ts
32+
allowed_patterns:
33+
- "a1b2c3d4e5f60718293a4b5c"
34+
- "mockImplementation\\(\\(key: string\\) => CONFIG\\[key\\]\\)"
35+
- "Pass at least one of --name, --description"
36+
- filename: test/integration/organization-prompt.test.ts
37+
allowed_patterns:
38+
- "a1b2c3d4e5f60718293a4b5c"
39+
- "mockImplementation\\(\\(key: string\\) => values\\[key\\]\\)"
40+
- "Pass --org, set it in \\.cs-launch\\.json"
41+
- "when --org is passed"
42+
- filename: src/commands/launch/projects/update.ts
43+
allowed_patterns:
44+
- "Pass at least one of --name, --description"
2645
- filename: src/projects/project.presenter.ts
2746
allowed_patterns:
2847
- "keyof ProjectUpdate"

‎AGENTS.md‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,20 @@ mirrored as `PROJECT_NAME_MAX_LENGTH` / `PROJECT_DESCRIPTION_MAX_LENGTH` in
316316
`src/projects/project.inputs.ts` and enforced in each flag's `normalize`, so a value from config or
317317
a prompt is checked as well as one from argv.
318318

319-
Supplying neither flag is a usage error raised by `atLeastOneOf('name', 'description')` in
320-
`src/core/rules.ts` - the API would answer `BODY_EMPTY`, and a round trip to be told that is worse
321-
than exit 2. Rules run after the resolution chain, so a `--project <name>` still costs its
322-
name-to-uid lookup before the rule fires; only the `PUT` is avoided. The success lines report the
323-
value the **API confirmed**, falling back to the requested value if the response omits the field, so
324-
a server-side normalisation is not reported as something it was not.
319+
In a terminal, every updatable field not supplied as a flag is prompted for, in order (name, then
320+
description): `promptForProjectUpdate` in `src/projects/project.update.prompt.ts`. Prompts carry no
321+
pre-filled value; a blank answer, or one equal to the current value (read with one `GET` first),
322+
leaves that field out, and a flag value is always sent. The length limits are checked inside each
323+
prompt's `validate`, so an oversized answer re-prompts instead of failing. When both flags are
324+
supplied nothing is fetched or prompted. If nothing is left to send, the command prints a yellow
325+
`Project not updated. No changes were entered.`, sends no `PUT` and exits 0.
326+
327+
Without a terminal nothing is prompted: supplied flags are sent as given, and supplying neither is a
328+
usage error (exit 2) raised in the command's `run()` - the API would answer `BODY_EMPTY`, and a round
329+
trip to be told that is worse than exit 2. It is not a `static rules` entry because a rule runs
330+
inside `init()`, before a command can prompt, and cannot tell a terminal from a pipe. A `--project
331+
<name>` still costs its name-to-uid lookup before the check. Success prints one green
332+
`✔ Project updated successfully.`, whichever fields were sent.
325333

326334
`--name` and `--description` live in `src/projects/project.inputs.ts` because their limits are the
327335
project DTO's. When `environments:*` needs its own `--name`, the flat catalog key `name` is already
@@ -589,9 +597,8 @@ request to prove the body is unchanged. **No secret may reach argv** (FR30, G16)
589597
oclif's native `exclusive` / `relationships` on the flag definition, where it also shows in `--help` -
590598
and a simple range does too: `limit` and `skip` carry oclif's own `min`/`max` rather than being
591599
checked later. A rule that must read a *resolved* value (one that config, a prompt or a default may
592-
have supplied) belongs in `src/core/rules.ts` - there are three: `atLeastOneOf` (used by
593-
`projects:update`), `onlyWithValueOf` (used by `projects:create`) and `exactlyOneOf` (no consumer yet;
594-
see "Built ahead of use" below) - declared as a `static rules = [...]` array on the command. `resolveInputs` evaluates them after resolution,
600+
have supplied) belongs in `src/core/rules.ts` - there are three: `atLeastOneOf` and `exactlyOneOf` (no consumer yet;
601+
see "Built ahead of use" below) and `onlyWithValueOf` (used by `projects:create`) - declared as a `static rules = [...]` array on the command. `resolveInputs` evaluates them after resolution,
595602
and a failing rule is a usage error (exit 2).
596603

597604
A rule asks what the **user supplied**, never what a default filled in. `resolveInputs` hands each rule
@@ -603,7 +610,7 @@ gate value `onlyWithValueOf` reads is a value, not a "was it supplied?" question
603610
wherever it came from. Write the next rule when a command needs it; a rule
604611
kept alive only by its own test proves nothing.
605612

606-
**Built ahead of use.** Four pieces of production code have no caller yet, on purpose, each held
613+
**Built ahead of use.** Five pieces of production code have no caller yet, on purpose, each held
607614
for a named ticket whose shape it already fits. Nothing else in `src` is uncalled; add to this list
608615
rather than leave an orphan unexplained.
609616

@@ -613,6 +620,7 @@ rather than leave an orphan unexplained.
613620
| `DeploymentsApi.list` | CL-7170 (`deployments:*`) | a `DeploymentScope` plus paging -> `DeploymentsPage` |
614621
| `src/core/redact.ts` | CL-7169 (variables) | see below |
615622
| `exactlyOneOf` | CL-7172 (`cache:purge`) | "purge these paths, or everything, not both" - and it judges what the user supplied, not defaults |
623+
| `atLeastOneOf` | no ticket yet - its caller, `projects:update`, now prompts for missing fields instead | "at least one of these flags" for the next command that must not prompt - and it judges what the user supplied, not defaults |
616624

617625
**Redaction.** `src/core/redact.ts` (`REDACTED`, `redactedColumn`) has no caller yet; it is kept
618626
ahead of its first use on purpose, so the easy path for the first presenter that renders an

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ DESCRIPTION
323323
Update a Launch project
324324
325325
EXAMPLES
326+
$ csdx launch:projects:update
327+
326328
$ csdx launch:projects:update --org <org-uid> --project <name-or-uid> --name <new-name>
327329
328330
$ csdx launch:projects:update --org <org-uid> --project <name-or-uid> --description <new-description>

0 commit comments

Comments
 (0)