Skip to content

add deployment approve/reject and plan/propose to instance deploy#244

Merged
chrisghill merged 2 commits into
mainfrom
deployment-approve-reject
Jul 13, 2026
Merged

add deployment approve/reject and plan/propose to instance deploy#244
chrisghill merged 2 commits into
mainfrom
deployment-approve-reject

Conversation

@chrisghill

@chrisghill chrisghill commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

Adds deployment approval workflow support to the CLI: you can now propose a
deployment for review, and approve or reject it — mirroring the flow the web UI
already supports. Also adds --plan for dry-run previews on mass instance deploy.

Changes

mass instance deploy

  • --plan — create a dry-run PLAN deployment (preview changes without
    applying). Composes with --params/--patch/--follow. Provision-only.
  • --propose — create the deployment in PROPOSED status instead of
    running it immediately. It runs only once approved. Returns as soon as the
    proposal is created (no polling/log-follow), printing the follow-up
    approve/reject commands.
  • --plan and --propose are mutually exclusive.

mass deployment

  • mass deployment approve <deployment-id> — release a PROPOSED
    deployment to run (→ APPROVED).
  • mass deployment reject <deployment-id> — discard a PROPOSED
    deployment permanently (→ REJECTED).

Implementation

  • DeployAPI gains ProposeDeployment; DeployOptions.Propose short-circuits
    RunDeploy to the SDK's Propose (PLAN is not proposable, per the SDK).
  • Extracted resolveDeployAction, confirmDecommission, and
    reportDeployOutcome helpers to keep runInstanceDeploy within lint limits.

@chrisghill
chrisghill requested a review from coryodaniel as a code owner July 13, 2026 19:17
@chrisghill

Copy link
Copy Markdown
Member Author

@claude review

@claude

claude Bot commented Jul 13, 2026

Copy link
Copy Markdown

Claude finished @chrisghill's task in 2m 42s —— View job


Claude's Review

  • Gather context (read diff, docs, tests)
  • Understand the request (code review)
  • Review code for correctness, security, style
  • Post review feedback

CI is green (Test, golangci-lint, pre-commit all passed), so the SDK surface (Deployments.Approve/Reject/Propose, deployments.ProposeInput) checks out.

Overall

Clean, well-scoped change. The resolveDeployAction/confirmDecommission/reportDeployOutcome extraction reads well, the propose/plan mutual-exclusivity is enforced at the flag level, and the new tests (TestRunDeployWithPlanAction, TestRunDeployProposeDoesNotPoll) cover the new branches, including asserting GetDeployment is never reached on the propose path.

Findings

  1. reject has no confirmation prompt, unlike its abort siblingcmd/deployment.go:311-325 (runDeploymentReject). abort (cmd/deployment.go:255-266) requires typed confirmation of the deployment ID unless --force is passed, and the doc for reject explicitly says it discards the deployment "permanently." For consistency (and to guard against a typo'd deployment ID), it might be worth adding the same typed-confirmation/--force pattern to reject. Not a blocker since a PROPOSED deployment never ran, so the blast radius is low — but worth a conscious call rather than an oversight. Fix this →

  2. DeployOptions.Propose + Action: ActionPlan isn't guarded in RunDeploy itselfinternal/commands/instance/deploy.go:71-73,99-107. The doc comment states propose is "Not valid with ActionPlan," and the CLI enforces this via MarkFlagsMutuallyExclusive("plan", "propose") (cmd/instance.go:132), but RunDeploy is a public function or any future non-CLI caller could pass Action: ActionPlan, Propose: true and it would silently call ProposeDeployment with a plan action rather than erroring. Minor, since the only current caller enforces it, but worth either an explicit check in RunDeploy or dropping the "not valid" language from the comment if it's intentionally the CLI's responsibility.

  3. Nit: cmd/instance.go:304 — the comment "propose is only defined on the deploy command; destroy returns false here" relies on cmd.Flags().GetBool("propose") silently swallowing the "flag not defined" error. This matches the existing pattern for plan in resolveDeployAction (cmd/instance.go:249), so it's consistent, just flagging that both rely on the same implicit behavior — a comment near resolveDeployAction referencing this shared pattern (rather than only near propose) would make the coupling more obvious to future readers.

Nothing here blocks merging — items 1–2 are worth a decision either way, item 3 is a pure nit.

@chrisghill
chrisghill merged commit f786fff into main Jul 13, 2026
6 checks passed
@chrisghill
chrisghill deleted the deployment-approve-reject branch July 13, 2026 21: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.

2 participants