labstack / labstack/onebox

Deploy UX: strong-approval isn't automatable, `-y` is misleading, and a no-op migrate downgrades to changed=unknown

Open
#11 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug enhancement
Dominant language
Go
Stars
3
Forks
0
Avg merge
2h 40m
Merged PRs (30d)
63

Description

Feedback from a real production deploy (pursue → v2026.07.10) driven end-to-end through ob. The tool is genuinely strong — the plan output (risk/reversibility/approval, pinned digests, exact remote commands) and the deploy trace (preflight → transfer → migrate → rolling drain/converge → verify → activate, with a rollback hint) are clear and confidence-inspiring. These are refinements, most-valuable first.

1. Strong-approval path isn't automatable, and -y is misleading

ob deploy -y is documented as "skip the confirmation prompt" (cmd/ob/commands.go:203), but a strong plan still hard-fails without a grant:

✗ ob: strong approval is required for this exact deployment plan; create a bound grant with ob approve --plan PLAN and apply it with ob deploy --plan PLAN --approval APPROVAL

So -y reads as "this will deploy" when it won't (see the structured-deploy guard at cmd/ob/commands.go:609,629). Worse, ob approve exposes only --plan and --out (cmd/ob/commands.go:177-188) — there is no non-interactive confirmation flag. The only way to approve from a non-TTY (CI, an agent, a script) is to pipe the exact release ID into the interactive prompt:

printf '%s\n' "$RELEASE_ID" | ob approve --plan plan.json -o approval.json

That's fragile and clearly not an intended interface.

Suggested:

  • Add a first-class non-interactive approve, e.g. ob approve --plan PLAN --confirm <release-id> (require the ID as an explicit arg so it stays a deliberate act, not a blanket --yes).
  • Clarify -y's help: it does not satisfy strong approval. Ideally ob deploy -y on a strong plan fails fast stating that (it already points to approve+approval, which is good).
  • Consumers wiring ob into just/CI hit this immediately: a just deploy that runs ob deploy --plan … always fails on strong plans because there's no scriptable approve step to put in front of it.

2. A no-op migration downgrades rollback safety to changed=unknown

This deploy touched no schema, and the plan correctly showed job:migrate … changed=false. But at execution:

⚠ migration job migrate: changed=unknown (result file is missing); automatic rollback is unavailable after this step

The gate mounts a result file and reads it back (internal/engine/gate.go:112-165); when the job doesn't write OB_RESULT_FILE, it falls to reason = "result file is missing"changed=unknown (internal/engine/gate.go:171,202). The stock atlas migrate image doesn't write that file on a clean no-op, so a zero-change deploy silently loses automatic rollback.

Suggested: treat a clean migrate exit with no diff as changed=false (keep rollback open), or have the bundled migrate wrapper always write a result on success. A no-op migration shouldn't be scarier than a real one.

3. Tight, shared plan/approval expiry

The bound plan expired ~15 min after generation (expires: 2026-07-14T21:34:51Z), and plan → approve → deploy all share that window. For a flow whose whole point is a human approval pause, 15 min is short. A longer default (or a visible countdown / "regenerate" hint on expiry) would cut down on plan-regeneration churn.

4. Artifact hygiene

Plan and approval artifacts land in CWD (ob approve defaults --out ob-approval.json, cmd/ob/commands.go:186). Over a few releases the repo root accumulates ob-plan-*.json and now ob-approval-*.json (the grant is correctly 0600). Consider defaulting these under an XDG/state dir, plus an ob prune for spent plans and consumed grants.

5. Minor: dirty build in a release tool

The runner self-reports ob 0.0.1-m0 (…+dirty). A tool deploying production from a dirty build is a smell — consider warning (or refusing without --force).


Happy to send a PR for #1 (non-interactive ob approve --confirm) if that direction sounds right.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in cmd/ob/commands.go:177-188, 203, 609, and 629 to trace approval and deploy flags, then inspect internal/engine/gate.go:112-165, 171, and 202 for migration results. Confirm the intended scope with maintainers, then verify scriptable strong approval, accurate -y behavior, and safe no-op migration handling before considering the expiry, artifact, and dirty-build refinements.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
cli, devops, infrastructure
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.