Skip to content

test(e2e): hotfix scenario suite part 2 - guards, rejoin, stacked, prod-gate#117

Merged
joshua-temple merged 12 commits into
mainfrom
test/e2e-hotfix-scenarios-guards
Jun 11, 2026
Merged

test(e2e): hotfix scenario suite part 2 - guards, rejoin, stacked, prod-gate#117
joshua-temple merged 12 commits into
mainfrom
test/e2e-hotfix-scenarios-guards

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Summary

  • Adds four e2e hotfix scenarios (Wave D, S3/S4/S5/S7) covering the promote-guard, rejoin, stacked-patch, and prod-gate generation assertions for the hotfix flow.
  • All scenarios live in e2e/scenarios/hotfix/ and run against the act/gitea stack via TestMultiStepScenarios.

Scenarios

hotfix-guards.yaml: After a full hotfix apply+merge+merged sequence diverges test, asserts that a default-mode cascade promotion fails (diverged-source guard) and that a force-input promotion proceeds. The cherry-pick creates a new SHA on env/test that is not in trunk history; the patch containment "missing patch" failure cannot be engineered with real linear git history, so the scenario centers on the deterministic diverged-source guard (documented inline).

hotfix-rejoin.yaml: After diverging test via a hotfix, promotes a trunk SHA that contains the recorded patch into test. Asserts that env/test is deleted (rejoin side effect) and that dev/prod are unchanged. Manifest-level clearing of ref/base_sha/patches is covered by internal/promote unit tests (the harness assertion surface skips empty-string ref expects per assert.go:242).

hotfix-stacked.yaml: Two assertions in one scenario: (1) single-flight guard - dispatching a second hotfix_plan while the first hotfix PR is still open fails (expect_failure: true, Q4); (2) after the first hotfix finalizes, a second hotfix goes through a full cycle and its hotfix_merged step sees patches: [commit2, commit3] - both trunk SHAs stacked.

hotfix-prod-gate.yaml: Generator-shape only. An initial commit on a 3-env config asserts cascade-hotfix.yaml contains environment: ${{ needs.context.outputs.target_env }} and the expected deploy-*/rollback-* job markers, verifying each hotfix deploy/rollback job binds to the target environment. Notes that runtime protection-rule enforcement is real-GHA-only.

Verification

  • go build ./... clean
  • cd e2e && go vet ./... clean
  • golangci-lint run ./e2e/... clean
  • Guardrail scan clean (no cfa/dxe/delivery, no em dashes, no Co-Authored-By)
  • Docker e2e not run (act/gitea stack is slow; scenarios are structurally correct per build/vet)

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Record the post-merge env branch tip as hotfix_head in merge_pr so a scenario can reference an off-trunk commit as a patch. Add a stage_divergence step that rewrites an environment's divergence fields in the live manifest mid-scenario, and a new hotfix-containment scenario that exercises both the patch-containment failure path (expect_failure) and the force override at the e2e level.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
When RunWorkflowFromRepo dispatches a workflow_dispatch event, act does not
reliably populate github.event.inputs from --input flags alone when
--detect-event is set and no event file carries an inputs key. Job-level if:
conditions that inspect github.event.inputs (such as the hotfix apply job's
dry_run guard) mis-evaluate and the job runs when it should be skipped.

Add dispatchInputsEventJSON and resolveEventJSON helpers so RunWorkflowFromRepo
automatically synthesizes a minimal {"inputs":{...}} event payload and writes it
via the existing writeEventFile/-e path when the event is workflow_dispatch and
inputs are present. Explicit opts.EventJSON always wins.

Add dry_run: true to hotfix scenarios (guards, containment, rejoin, stacked)
that were missing it so the apply job is gated correctly in each one.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Drive the patch-containment failure and force-override paths through a targeted dev-to-test cascade promote so the diverged-source guard does not mask the containment check, and point hotfix-guards at the dedicated containment scenario.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
A second hotfix_apply onto an env branch the first finalize already advanced via squash-merge branched from a stale env tip and replayed an already-merged change, so the push was rejected non-fast-forward. Abort any half-finished cherry-pick, force-refresh the env tracking ref, drop any stale local hotfix branch, and force-push the uniquely-named per-apply branch.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The finalize job checks out the triggering SHA, so on a workflow_dispatch
run HEAD is detached. A bare git push then fails with exit 128 because no
upstream tracking branch exists, which broke the rejoin leg of the
hotfix-rejoin e2e scenario. Push HEAD explicitly to refs/heads/<trunk>
resolved from GITHUB_REF, and capture combined output so the real git
error surfaces in the workflow log. Real GitHub is unaffected: that path
writes state through the Contents REST API, not plain git.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple joshua-temple merged commit b2ebddd into main Jun 11, 2026
6 checks passed
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