feat(release): two-stage release - gate-green main promotes to a queued release branch #475

Closed
coilysiren wants to merge 0 commits from feat/two-stage-release into main
Owner

Implements ward#1117 / aos#469 for aos.

  • promote.yml (stage 1) - every main push re-runs the full repo gate; only green gates fast-forward release to that sha, pushed with CI_RELEASE_TOKEN so the push reliably enqueues workflows (aos#240 class). Fails loud if the secret is missing.
  • release.yml (stage 2) - now triggers on release pushes only, under concurrency: release-pipeline / cancel-in-progress: false (Forgejo v14+ queue semantics): promoted shas release in sequence, never overlap-and-cancel. Stale aosbuilder buildx instances get removed before create (crashed-run name-collision fix). Alerts follow the branch.
  • ci.yml also runs on release, so promotion re-runs the full gate per spec.
  • scripts/sync-actions-secrets.py + ward exec sync-actions-secrets - the aos repo had NO TELEGRAM_* secrets (every alert step failed silently-loud) and no CI_RELEASE_TOKEN. One verb re-syncs them from SSM.

Post-merge sequencing: releases pause until CI_RELEASE_TOKEN + Telegram secrets are set - run ward exec sync-actions-secrets once (needs AWS + the admin PAT; an agent permission classifier blocked me from writing decrypted SSM values to the secrets API myself). First green promote then creates the release branch and stage 2 takes over.

Refs #452, #469, ward#1117.

Implements ward#1117 / aos#469 for aos. * **promote.yml (stage 1)** - every main push re-runs the full repo gate; only green gates fast-forward `release` to that sha, pushed with `CI_RELEASE_TOKEN` so the push reliably enqueues workflows (aos#240 class). Fails loud if the secret is missing. * **release.yml (stage 2)** - now triggers on `release` pushes only, under `concurrency: release-pipeline / cancel-in-progress: false` (Forgejo v14+ queue semantics): promoted shas release **in sequence**, never overlap-and-cancel. Stale `aosbuilder` buildx instances get removed before create (crashed-run name-collision fix). Alerts follow the branch. * **ci.yml** also runs on `release`, so promotion re-runs the full gate per spec. * **scripts/sync-actions-secrets.py** + `ward exec sync-actions-secrets` - the aos repo had NO TELEGRAM_* secrets (every alert step failed silently-loud) and no CI_RELEASE_TOKEN. One verb re-syncs them from SSM. **Post-merge sequencing:** releases pause until `CI_RELEASE_TOKEN` + Telegram secrets are set - run `ward exec sync-actions-secrets` once (needs AWS + the admin PAT; an agent permission classifier blocked me from writing decrypted SSM values to the secrets API myself). First green promote then creates the `release` branch and stage 2 takes over. Refs #452, #469, ward#1117.
feat(release): two-stage release - gate-green main promotes to a queued release branch
All checks were successful
ci / gate (pull_request) Successful in 13s
9df95f4aa5
Implements the ward#1117 / aos#469 spec for aos:

* promote.yml (stage 1): every main push re-runs the full repo gate and,
  only when green, fast-forwards `release` to that sha. The push uses
  CI_RELEASE_TOKEN (real-user PAT) so it reliably enqueues workflows
  (the aos#240 job-token suppression). Fails loud when the secret is
  missing. Bursts collapse to the newest sha (cancel-in-progress: true).
* release.yml (stage 2): triggers on `release` pushes only, under a
  concurrency queue with cancel-in-progress: false, so promoted shas
  release in sequence - no more overlap-and-cancel taking down in-flight
  image builds. Alert conditions follow the branch move. Stale
  `aosbuilder` buildx instances are removed before create, closing the
  crashed-run name-collision failure mode on the shared daemon.
* ci.yml runs on `release` pushes too, so the promoted sha gets the full
  gate a second time, per spec.
* scripts/sync-actions-secrets.py + `ward exec sync-actions-secrets`:
  one-verb sync of the Telegram alert creds + CI_RELEASE_TOKEN from
  their SSM sources of truth - the aos repo never had TELEGRAM_* set,
  which is why every main-failure alert step itself failed.

Refs coilyco-flight-deck/ward#1117
Refs #469

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Cym37PsLtA61parAQyeAw
fix(promote): keep the server scheme - github.server_url is in-cluster http here
All checks were successful
ci / gate (pull_request) Successful in 15s
9c735c5c64
Ward's first live promote (ward run 1828) proved server_url resolves to
the in-cluster http URL on this runner; assuming https produced
"https://http://...". Keep the URL's own scheme.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Cym37PsLtA61parAQyeAw
merge: refresh feat/two-stage-release against main (comment-cap hotfix + landed sync script)
All checks were successful
ci / gate (pull_request) Successful in 58s
b1a82f9632
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Cym37PsLtA61parAQyeAw
coilysiren closed this pull request 2026-07-13 02:57:07 +00:00
All checks were successful
ci / gate (pull_request) Successful in 58s

Pull request closed

Sign in to join this conversation.
No description provided.