Repository navigation
[Review] CI/changelog fragments: the no-changelog waiver is only read at PR open or push, so a label added later leaves the required check red #1447
Description
Context
#1297 added a CI step that requires a changelog fragment on any PR touching addons/hammerforge/ or hammerforge_mcp/src/. The no-changelog label waives it. The waiver is only read from the payload of the event that started the run. CI never runs on a label change, so the label only works if it is already on the PR when that event fires.
.github/workflows/ci.ymlL6-10.pull_requesthas notypes:, so only the defaults (opened,synchronize,reopened) trigger it:hammerforge/.github/workflows/ci.yml
Lines 6 to 10 in 6b9a632
on: push: branches: [main] pull_request: branches: [main] .github/workflows/ci.ymlL152-162, the fragment step. It sits inside thestatic-checksjob ("GDScript Lint & Format"):hammerforge/.github/workflows/ci.yml
Lines 155 to 162 in 6b9a632
# A pull request that changed the addon and forgot its fragment passed, # and the change was missing from the changelog until someone noticed; # the template's checkbox was the only reminder (#1297). HEAD is the # pull request's merge commit, so its first parent is the base. The # no-changelog label waives it for a refactor or a test-only change. - name: Check a changed addon brings a changelog fragment if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'no-changelog') run: python3 tools/changelog_fragments.py --require HEAD^1 CONTRIBUTING.mdL82. It tells contributors the label waives the check, but says nothing about when the label has to go on:Line 82 in 6b9a632
`python tools/changelog_fragments.py --check` checks every fragment, and CI runs it. `--preview` prints `[Unreleased]` with your line in place, dated today and linked to `PR #?` until it merges. CI also asks for a fragment on a pull request that changes `addons/hammerforge/` or `hammerforge_mcp/src/`; the `no-changelog` label waives that for a refactor or a test-only change, and docs, tests and tooling are never asked. `python tools/changelog_fragments.py --require origin/main` runs the same check on a branch.
Why it matters for long-term health
"GDScript Lint & Format" is one of the three required status checks in the main ruleset. Here is what happens when a refactor or test-only PR touches the addon and the label goes on after CI starts (the usual sequence: open the PR, see it fail, add the waiver):
- The fragment step fails.
- Adding the label doesn't start a run, so the required check stays red and the merge is blocked.
- The only ways out are an empty push, closing and reopening the PR, or adding a fragment the change doesn't need. The first two re-run the whole CI, including the four GUT shards.
GitHub's docs say re-running a workflow uses the original event's GITHUB_SHA and GITHUB_REF. I wouldn't count on a "Re-run failed jobs" seeing a label added afterwards either.
The reverse is a silent hole. Remove the label after the first green run, and nothing re-checks the PR until its next push.
Until now this has only worked because of how I open PRs. #1382 and #1391 both had the label added within a second of gh pr create, before the run started. On #1391 (run 39539880603) the step shows as skipped. A contributor following CONTRIBUTING.md won't know about that ordering.
Evidence
on:
push:
branches: [main]
pull_request:
branches: [main]
...
- name: Check a changed addon brings a changelog fragment
if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'no-changelog')
run: python3 tools/changelog_fragments.py --require HEAD^1From the official docs (https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request): "By default, a workflow only runs when a pull_request event's activity type is opened, synchronize, or reopened. To trigger workflows by different activity types, use the types keyword."
Proposed direction
- Move the
--requirecheck out ofstatic-checksinto a small workflow of its own. It should run onpull_request: types: [opened, synchronize, reopened, labeled, unlabeled], need only checkout (depth 2) and Python, and finish in seconds. - Make that workflow's job a required check alongside the other three.
- Don't add
labeledtoci.ymlitself. Every label change, including the area labels people add by hand, would then re-run the GUT shards, andcancel-in-progresswould cancel a run already in flight.labeler.ymlusesGITHUB_TOKEN, so its labels wouldn't start runs either way. - Add one line to CONTRIBUTING.md: adding the label re-checks the PR, and no push is needed.
Activity
saworbit commentedon Oct 21, 2026
#1487 is the other half of the same check:
--requirecounts a deleted fragment as bringing one. If the check moves into its own workflow as proposed here, the--diff-filter=Achange can go in with it, along with an explicit exemption for the compile/release PR.saworbit commentedon Oct 21, 2026
Fixed in bd50211 on #1503. The fragment check is now its own workflow,
changelog-fragment.yml, jobChangelog Fragment, and it runs on labeled and unlabeled too. CI's lint job no longer runs it. It needs adding to themainruleset's required checks before #1503 merges, so auto-merge is off on that one. CONTRIBUTING says the label rechecks the PR with no push. Fragment added in changelog.d/changelog-check.behind.md.