Skip to content

feat(ship): environment-level promote with SHA-ordering release resolution - #213

Merged
prellr merged 1 commit into
mainfrom
feat/ship-env-promote
Jun 27, 2026
Merged

prellr merged 1 commit into
mainfrom
feat/ship-env-promote

Conversation

@prellr

@prellr prellr commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Item 4 of the Ship-model discussion. Production = "main at SHA X", so a prod deploy ships everything merged — not one release's PRs. This makes the model honest.

Phases

  • A — "Deploy to production" action. Env-level dispatch (dispatchEnvDeployWorkflow extracted from the per-release auto-dispatch) + PromoteEnvironment + POST /deploy_environments/{id}/promote (member auth + GitHub token; 400 if no deploy workflow configured). Per-release PromoteRelease stays as the "ship up to release X" wrapper.
  • B — ancestry/ordering resolver (core). On a prod deploy landing, resolve the project (deploy→env), pick a cutoff (exact-SHA anchor's merged_at, else deploy time), and advance every non-terminal release merged at-or-before it (ListNonTerminalReleasesForProjectMergedAtOrBefore → ResolveReleasesForProdSHA). One deploy resolves all the releases it shipped. Falls back to the legacy single-release link when the project can't be resolved. SHA-ordering heuristic (your pick); GitHub-compare is a noted future refinement.
  • C — reconcile. POST /deploy_environments/{id}/reconcile runs the same resolver off the env's current_sha/current_deployed_at — heals releases stranded by the old exact-SHA linkage (e.g. your verified-but-"in-staging" ones).
  • D — UI. "Deploy to production" button on the Production env card + confirm dialog + mutation + API method + i18n.

Test plan

  • go build/vet/sqlc clean; 2 new resolver tests (ResolvesAllReleasesMergedBefore, SkipsReleasesMergedAfterDeploy) + full Go suite pass; core+views typecheck; 204 ship + 8 schema tests green. Resolver reviewed by hand (cutoff + boundary correctness).
  • Live: "Deploy to production" dispatches deploy-prod.yml; on land, all in-staging releases ≤ the deploy advance to in_production/done; "reconcile" heals the currently-stuck releases.

Built with help from a background implementer (whose process died mid-run — its file output was complete and I verified + reviewed everything before this PR).

🤖 Generated with Claude Code

…ution

Reworks prod promotion to match reality: production = "main at SHA X", so a
prod deploy ships everything merged to main — not one release's PRs. Item 4
of the Ship-model discussion.

Phase A — env-level "Deploy to production". Extracts the workflow dispatch out
of maybeAutoDispatchProductionDeploy into a reusable dispatchEnvDeployWorkflow,
and adds Service.PromoteEnvironment + POST /api/deploy_environments/{id}/promote
(member auth + GitHub token; 400 when the env has no deploy_workflow_filename).
Per-release PromoteRelease stays as the "ship up to release X" wrapper.

Phase B — ancestry/ordering resolver (the core). When a prod deploy lands,
linkProductionDeployForRelease now resolves the deploy's project (deploy→env),
picks a cutoff (the exact-SHA anchor's merged_at when present, else the deploy's
completed/triggered time), and advances EVERY non-terminal release for the
project merged at-or-before that cutoff — via the new
ListNonTerminalReleasesForProjectMergedAtOrBefore query + the shared
Service.ResolveReleasesForProdSHA. One deploy resolves all the releases it
shipped, instead of only the exact-SHA match. Falls back to the legacy
single-release link when the project can't be resolved (no regression). Ordering
heuristic per the design call; GitHub-compare ancestry is a future refinement
for out-of-order merges. Tests: ResolvesAllReleasesMergedBefore (3 releases all
advance) + SkipsReleasesMergedAfterDeploy (later-merged stays put).

Phase C — reconcile. POST /api/deploy_environments/{id}/reconcile runs the same
resolver off the env's current_sha + current_deployed_at, healing releases
stranded by the old exact-SHA-only linkage (e.g. verified-but-still-in-staging).

Phase D — UI. "Deploy to production" button on the Production env card with a
confirm dialog ("ships everything on main, not one release"),
usePromoteDeployEnvironment mutation + promoteDeployEnvironment API method +
schema, new i18n (en + zh-Hans).

go build + vet + sqlc current; new resolver tests + full Go suite pass;
core + views typecheck; 204 ship + 8 schema tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@prellr
prellr merged commit dd273d7 into main Jun 27, 2026
2 checks passed
@prellr
prellr deleted the feat/ship-env-promote branch June 27, 2026 17:46
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.

1 participant