fix(rollback): guard the first environment against rollback - #418
Merged
Merged
Conversation
The first environment tracks trunk and is never promoted into, so its deploy-history ring is structurally always empty. A no-target rollback there resolved its target from an empty or stale ring, producing a silent wrong target. Refuse a rollback aimed at the first environment in the preflight and apply paths with an actionable error that points at the trunk revert path. Exclude the first environment from the generated rollback workflow's choice dropdown and gate emission on at least two environments, mirroring the hotfix generator, so the manual path never offers an environment the guard refuses. Add unit coverage for the guard on the preflight, apply, no-target, and deployable-scoped paths, and an e2e scenario proving a first-environment rollback fails fast while a promoted environment still rolls back. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
joshua-temple
enabled auto-merge (squash)
June 30, 2026 13:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Closes #385 (reframed).
cascade rollbackon the trunk-tracking first environment now fails fast with an actionable error instead of silently resolving a wrong target from its structurally-empty deploy-history ring.Why
The first env (IsFirstEnvironment, the build/deploy-on-merge target) tracks trunk and is never promoted into, so its ring (advanced only by promote/hotfix/rollback finalize) is always empty. A no-target rollback there silently mis-resolves. The trunk-native undo for the first env is a revert merge, not a ring rollback. (The original 'advance the ring on deploy-on-merge' framing was wrong: it would bolt ring-rollback onto the one env that should not use it.)
Changes
Rollbacker.firstEnvErrcalled fromPlan(covers preflight, finalize, and repository_dispatch, which all route through Plan) andApply(defense in depth). Inert when no config is parsed.rollback.Enabled()now requires >= 2 environments and the dispatch dropdown enumeratesEnvironments[1:], mirroring the HotfixGenerator precedent. A single-env project (its only env tracks trunk) now generates no rollback workflow. The runtime guard stays authoritative because repository_dispatch carries a free-string environment the choice list cannot constrain.Tests
rollback/rollback-first-env-guard.yaml): first-env rollback fails fast asserting the guard message (new ExpectLog field); promoted-env rollback succeeds back to the prior version. Docker-green (43.8s).Verification
go build/vet/test (2079 pass), golangci-lint, actionlint (incl. the rollback dispatch generator test) all clean.