fix(e2e): make hotfix-conflict scenario anchor deterministic - #309
Conversation
executeHotfixApply anchored env/<env> at the recorded state SHA and silently fell back to trunk HEAD when that SHA was momentarily empty under a gitea state-sync race. The fallback seeded the env branch at the just-patched tip, turning the scenario's engineered cherry-pick conflict into an empty clean apply and flipping the resulting PR label run-to-run. resolveEnvAnchor now resolves an explicit base_ref then the recorded SHA, and errors loudly instead of guessing; the conflict scenario pins base_ref and asserts the conflict label it actually produces. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
gitea's branches API resolves old_ref_name as a branch or tag name, not a raw commit SHA, so seeding env/<env> from an anchor SHA silently branched from HEAD instead. At the conflict scenario's apply step HEAD already carried the patched content, so the cherry-pick applied cleanly and never produced the engineered conflict. Seed the env branch with a git push of the anchor SHA from inside the act container, which resolves the object by hash precisely, so the anchor content is exactly what the SHA guarantees. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
|
Holding this as a draft. The two commits are sound, safe improvements to the hotfix e2e harness: env-branch anchor resolution no longer silently falls back to trunk HEAD, and env branches are seeded with What remains: Not blocking anything: this is e2e test scaffolding for the hotfix conflict path; it does not affect generated output or the product. Parking until it can be iterated locally. |
…rses execInRepo read the container exec output with a plain io.Copy, but Docker's exec stream is multiplexed with 8-byte per-frame headers. Those binary header bytes landed between newlines, so parseSentinel split lines that began with a frame header instead of CONFLICT_FILES=, the match never hit, and conflict was always parsed as false (wrong cascade-hotfix label on a genuine conflict). Read through the existing readDemuxedStream (stdcopy.StdCopy) helper instead. The cherry-pick was always conflicting correctly; the sentinel is now parseable. Verified locally: the conflict scenario passes deterministically with conflict=true across repeated runs, and the clean-apply path is unaffected. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Problem
TestMultiStepScenarios/Hotfix_Conflict_Resolutionflipped pass/fail run-to-run on the same commit (green on PR #277, red on the rc.4 orchestrate run).executeHotfixApplyanchoredenv/<env>at the recorded state SHA and silently fell back to trunk HEAD when that SHA came back empty under a gitea state-propagation race. The fallback seeded the env branch at the just-patched tip, turning the scenario's engineered cherry-pick conflict into an empty clean apply, so the harness applied thecascade-hotfixlabel instead ofcascade-hotfix-conflictand step 10's assertion matched nothing.Fix
resolveEnvAnchor(env, baseRef): explicitbase_ref(context-resolved, literal fallback) then the recorded state SHA, then a loud error - the silent trunk-HEAD fallback is removed, so an unresolvable anchor surfaces the race instead of fabricating the wrong outcome.base_ref: commit1so the cherry-pick deterministically conflicts every run; the assertion + labels now match the genuine engineered conflict (the scenario's name and description always intended a conflict).TestResolveEnvAnchor(precedence + loud-error path) andTestParseHotfixApplyBaseRef.Verification
cd e2e && go build ./...passes;go test ./harness/ -run TestResolveEnvAnchor|TestParseHotfixApplyBaseRefpasses;golangci-lint run ./harness/clean. Host-side git repro confirms anchor=commit1 conflicts 5/5 across every merge strategy. The full containerized scenario needs Docker (act+gitea) and runs in CI.