Skip to content

🧪 test(ci): assert the changelog-sync guard verdict mapping - #324

Merged
konih merged 1 commit into
mainfrom
lane/rel-changelog-01
Aug 23, 2026
Merged

🧪 test(ci): assert the changelog-sync guard verdict mapping#324
konih merged 1 commit into
mainfrom
lane/rel-changelog-01

Conversation

@konih

@konih konih commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

What

Adds hack/test/changelog_sync_release_guard_test.sh assertions that pin the verdict mapping of the changelog-sync release guard. Test-only: 1 file, +196 lines, zero Go, zero production change. .github/workflows/changelog-sync.yaml is byte-identical to main.

Why the original story was stale

The REL-CHANGELOG-01 story asked for a demotion guard on the changelog-sync push step. That guard already landed at a5fdd3dc8 on 2026-08-07 — sixteen days before the story was filed. Implementing the story as written would have been a no-op re-implementation.

What was actually broken: the gate's test suite was vacuous

The landed guard was covered by tests, but those tests never asserted which verdict each guard exit code maps to. Concretely: flipping the workflow's 2) verdict=hold arm to verdict=push — i.e. making the guard push a CHANGELOG that demotes a release section while its tag is in flight, the exact scenario the guard exists to prevent — previously left all 22 checks green.

So the guard was landed but unpinned: any future refactor of the case arms could silently invert its behaviour with a fully green suite.

This lane closes that vacuity. The suite now asserts, per exit code, the verdict emitted, whether the push step runs, whether the job stays green or fails, and the annotation surfaced:

  • exit 0 → verdict=push, push runs, job green (self-healing preserved)
  • exit 2 → verdict=hold, push skipped, job green, ::warning naming the pending tag (no alarm fatigue on every release)
  • exit 1 → job fails, push never runs, ::error annotation
  • exit 3 → usage errors (missing args, unreadable inputs) never silently pass as 0

It also asserts the structural invariants the mapping depends on: the guard step runs before the push step, and the push step gates on a single verdict literal.

Verification

An independent reviewer (not the author of this code) ran 12 of its own production mutations against the workflow and reproduced 7 mutants that main's suite missed and this branch now catches. Verdict: APPROVE, no P0, no P1.

Local gates on the rebased head:

  • bash hack/test/changelog_sync_release_guard_test.sh — rc=0, 31 ok -, 0 failures
  • bash hack/lint-shell.sh — rc=0
  • go test ./test/ci/ — ok
  • task changelog:verify — ok

Risk

None to production behaviour: no workflow, chart, manifest, or Go file is touched. The only effect is that a future regression in the guard's verdict mapping now turns CI red instead of green.

The release guard added in a5fdd3d is correct, but nothing tested the
inline `run:` body that turns its exit code into a job outcome. Flipping
`2) verdict=hold` to `2) verdict=push` -- which would push the exact
fbb5196 demotion of `## [0.17.0]` to main -- left the whole suite green,
as did replacing the fatal `*) exit 1` arm with a push verdict. Section 6
only proved the guard runs before the push and that the push reads its
output, never which verdict each exit code produces.

Extract the guard step's script from changelog-sync.yaml and execute it
against fixture repositories whose HEAD is untagged and whose CHANGELOG.md
is dirty, exactly as `task changelog:write` leaves it. Assert the job-level
outcome in both directions: a release-in-flight demotion emits a verdict
that is not the one the push step gates on (green, warned, not pushed), a
demotion whose tag is visible and a dropped middle section fail the step,
and a legitimate [Unreleased] append or body re-render still pushes.

The push condition must be a single `== '<literal>'` comparison against the
guard step's own id, so the verdict comparison is an evaluation rather than
a hard-coded guess.
@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@konih
konih merged commit a98621a into main Aug 23, 2026
31 checks passed
@konih
konih deleted the lane/rel-changelog-01 branch August 23, 2026 15:23
@sonarqubecloud

Copy link
Copy Markdown

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