Skip to content

feat(ci): auto-promote-on-e2e — retag :latest on green E2E Staging SaaS - #2206

Merged
hongmingwang-moleculeai merged 1 commit into
stagingfrom
feat/auto-promote-on-e2e-green
Apr 28, 2026
Merged

feat(ci): auto-promote-on-e2e — retag :latest on green E2E Staging SaaS#2206
hongmingwang-moleculeai merged 1 commit into
stagingfrom
feat/auto-promote-on-e2e-green

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

Final piece of the SaaS pipeline self-healing loop. Adds `auto-promote-on-e2e.yml` which retags `platform:staging-` + `platform-tenant:staging-` → `:latest` whenever `E2E Staging SaaS (full lifecycle)` passes for a `main` push.

After this lands, the chain is end-to-end automatic:

```
staging push → CI + E2E Canvas + E2E API Smoke + CodeQL all green
→ auto-promote-staging fast-forwards main
→ publish-workspace-server-image builds :staging-
→ E2E Staging SaaS runs on the main commit
→ THIS WORKFLOW retags :latest on green
→ tenants auto-pull within 5 min (or redeploy-tenants-on-main fans out faster)
```

Why trigger only on `main`

`:latest` is what prod tenants pull. We only advance `:latest` for SHAs that have reached `main` (via auto-promote-staging). Triggering on staging would let a staging-only revert advance `:latest` to a SHA that never reaches main, breaking the "production runs what's on main" invariant.

Why a separate workflow

  • Test concerns and release concerns separate
  • Disabling promote during an incident is one workflow toggle, not an edit to the long E2E file
  • When Phase 2 canary work eventually lands, the canary path can replace this trigger without touching the E2E workflow

Doc-aligned

Per `molecule-controlplane/docs/canary-tenants.md` section "Do we actually need canary right now?", the recommendation for current scale (≤20 paying tenants) is "fix staging E2E + use it as the promote gate" — exactly what this PR ships. Phase 2 canary fleet stays deferred until blast radius grows.

Safety

  • `if:` skips the job when E2E failed (`:latest` stays on the prior known-good digest)
  • Verifies both `platform:staging-` and `platform-tenant:staging-` exist before retagging either — half-published state is impossible
  • `workflow_dispatch` provided as manual escape hatch (with optional `sha` override)

Test plan

  • yaml syntax valid
  • After merge: this PR's own merge to main triggers E2E Staging SaaS (path filter touches `.github/workflows/**` so the SaaS suite includes the workflow file in its watched paths — verify it runs)
  • On green E2E for main commit: this workflow fires, retags both images
  • Verify with `gh api repos/Molecule-AI/molecule-core/pulls//check-runs` and `docker manifest inspect ghcr.io/molecule-ai/platform-tenant:latest` that `:latest` digest matches `:staging-`

🤖 Generated with Claude Code

Closes the final gap in the SaaS pipeline. After auto-promote-staging
fast-forwards main, publish-workspace-server-image builds new
`:staging-<sha>` images, but `:latest` (what prod tenants pull) only
moves on either a manual `promote-latest.yml` dispatch or a canary-
verify retag (gated on Phase 2 fleet that doesn't exist).

This workflow closes that gap by retagging
`platform:staging-<sha>` + `platform-tenant:staging-<sha>` → `:latest`
whenever E2E Staging SaaS passes for a `main` push. Uses crane
(no Docker daemon needed). Verifies both images exist before retagging
either, so a half-published state is impossible.

Why trigger only on `main` (not staging):
  - `:latest` is what prod tenants pull. Only SHAs that have reached
    `main` (via auto-promote-staging) should advance `:latest`.
  - Triggering on staging would let a staging-only revert advance
    `:latest` to a SHA that never reaches `main`, breaking the
    invariant "production runs what's on `main`".

Why a separate workflow rather than folding into e2e-staging-saas.yml:
  - Test concerns and release concerns separate.
  - Disabling promote during an incident is one workflow toggle, not
    an edit to the long E2E file.
  - When Phase 2 canary work eventually lands, the canary path can
    replace this trigger without touching the E2E workflow.

Doc-aligned: per molecule-controlplane/docs/canary-tenants.md,
"green staging E2E → :latest" is the recommended approach for the
current scale (≤20 paying tenants); canary fleet is deferred until
blast radius grows.

Pipeline after this lands is fully self-healing:
  staging push → 4 gates green → auto-promote fast-forwards main
   → publish-workspace-server-image → E2E Staging SaaS
   → THIS WORKFLOW retags :latest → tenant fleet auto-pulls in 5 min
                                    (or redeploy-tenants-on-main fans out faster)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged via the queue into staging with commit 693135e Apr 28, 2026
21 checks passed
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
…-chain-proof budget (#2205)' (#2206) from fix/e2e-api-health-wait-migration-chain into main
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