Skip to content

test(e2e): hotfix scenario suite - clean apply, conflict resolution, refusals (Wave D, S1/S2/S6)#116

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

test(e2e): hotfix scenario suite - clean apply, conflict resolution, refusals (Wave D, S1/S2/S6)#116
joshua-temple merged 19 commits into
mainfrom
test/e2e-hotfix-scenarios-core

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Summary

  • Adds three multi-step e2e scenarios under e2e/scenarios/hotfix/ covering the core hotfix paths (Wave D)
  • hotfix-clean-apply.yaml: validates the end-to-end hotfix lifecycle for a clean cherry-pick - plan, apply, merge PR, finalize; asserts state divergence fields (ref/base_sha/patches), hotfix tag creation, and that flanking environments (dev/prod) are unchanged
  • hotfix-conflict-resolution.yaml: validates conflict detection and resolution - engineers a real cherry-pick conflict (trunk advanced past env/test's anchor before the fix commit), asserts the conflict PR label, pushes resolved content via resolve_conflict, then merges and finalizes
  • hotfix-refusals.yaml: validates four guard cases - non-existent commit SHA rejected, first-env target rejected, no-op when fix is already reachable from env state, dry-run leaves no branches

Verification

  • go build ./... and cd e2e && go vet ./... clean on all commits
  • S1 (clean apply) and S6 (refusals) running locally under act; S2 (conflict) queued
  • No reserved-only fields asserted (canary/blue_green/telemetry/analysis/switch/adapter)

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>
…ch prod)

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The generated cascade-hotfix.yaml was invoking `cascade hotfix plan` and
`cascade hotfix finalize` without --config, causing both to fail with
"failed to parse config: reading manifest file: open : no such file or
directory". Pass the manifest path the same way the promote workflow does.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The apply job branched the hotfix from origin/env/<env>, a remote-tracking
ref that does not exist on a first hotfix into an environment: the plan verb
creates env/<env> locally at the recorded state SHA but never pushes it, so
the cherry-pick step failed with 'invalid reference: origin/env/<env>'.

Branch the hotfix from the plan's validated BASE_SHA, and when the remote env
branch is absent create and push it at BASE_SHA so the resolution PR has a
base to target. When the branch already exists its tip equals BASE_SHA, so the
push is skipped. Guard plan and finalize each passing --config, and guard the
absent-env-branch apply path.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
When the fix is already contained in the target environment's state SHA the
planner reports no_op and there is nothing to cherry-pick. The apply job ran
regardless and attempted a cherry-pick that would fail. Expose no_op as a plan
job output and gate the apply job on needs.plan.outputs.no_op != 'true'.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The hotfix_plan step in the clean and conflict scenarios validated the plan
and then a separate hotfix_apply step performed the cherry-pick. Without
dry_run the plan dispatch also ran the workflow apply job, which opens the PR
with the gh CLI that is absent from the act runner image. Mark the plan step
dry_run so it exercises only the plan job; the harness drives the apply.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The finalize verb cross-checked the merge SHA against the env-branch tip via a
local branch ref, but the finalize job checks out trunk and the env branch is
present only as a remote-tracking ref, so the lookup failed with git exit 128.
Resolve the tip from the local ref first and fall back to refs/remotes/origin,
and fetch the env branches in the finalize job so the ref is available.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The harness created env/<env> via the Gitea API then a branches.exist
assertion enumerated branches immediately. Gitea's branch-list endpoint lags a
create, so the assertion raced it and failed intermittently. Poll the list
endpoint until the new branch appears before proceeding.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The finalize job runs on the merged pull_request event, which checks out in
detached HEAD. The state write used a bare git push that relies on an upstream
tracking branch, so it failed with no branch to push to. Mirror promote
finalize: write through the Contents REST API on real GitHub, and under act push
the trunk branch explicitly with git push origin HEAD:refs/heads/<trunk>. Pass
GH_TOKEN and GITHUB_REPOSITORY to the finalize step for the API path.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The state write derived its push branch from the workflow event, but finalize
runs on the merged pull_request whose base is env/<target>, so it pushed the
manifest commit onto the env branch and was rejected as non-fast-forward. Take
the trunk branch from the manifest config (falling back to main) so state lands
on trunk regardless of the triggering event.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
createGitTag posts to the GitHub git-data refs API, which Gitea does not
implement and answers with 405. The release create that follows materializes
the tag from target_commitish, so the explicit ref create is unnecessary on
Gitea. Treat 405 as success, matching the existing 422 already-exists handling.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
finalize creates the hotfix release and tag via the release API, which needs a
token. The step only exported GH_TOKEN (for the state-write API), so the
release call ran unauthenticated and the API rejected it. Also export
GITHUB_TOKEN, which the release manager reads.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The git-data refs API (POST /git/refs) is GitHub-only; Gitea answers 405/401
and the release create that follows materializes the tag from target_commitish
anyway. Skip the explicit ref create when the API host is not GitHub so the
hotfix and promote release flows work against the Gitea e2e backend.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
releaseToken read only RELEASE_TOKEN and GITHUB_TOKEN. GITHUB_TOKEN is a
reserved name the runner does not reliably propagate as a step env var, so the
release create ran with an empty token and the API rejected it. Add GH_TOKEN as
a final fallback, matching the token the apply job already relies on.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
The GitHub Releases API (release objects) is unavailable on the gitea
backend used by the e2e harness: its endpoints reject the GitHub release
shape and Bearer auth, so the trailing release-object POST aborted the
hotfix finalize verb. Gate the create and prerelease release-object calls
behind isGitHubHost, mirroring the existing createGitTag gate, so a
non-GitHub host returns a synthetic success and finalize proceeds. The
real-GitHub code path is unchanged and remains covered by the host-gating
unit tests and the finalize integration test.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
…undary

The hotfix finalize steps asserted GitHub-only outcomes the gitea backend
cannot produce: the hotfix tag is never cut and the release object is never
created against a non-GitHub host. Drop the tag-existence assertion and keep
the gitea-observable state (merged commit on env/test, finalize success,
finalized hotfix state). The conflict scenario's cherry-pick lands clean
under gitea, so assert the cascade-hotfix label gitea applies; the
conflict-labeled and release-object paths are exercised by the real-GitHub
validation fleet. The resolution path stays covered by the resolve step.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple joshua-temple merged commit 68642a7 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