Skip to content

[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

Open

Description

@saworbit

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.yml L6-10. pull_request has no types:, so only the defaults (opened, synchronize, reopened) trigger it:
    on:
    push:
    branches: [main]
    pull_request:
    branches: [main]
  • .github/workflows/ci.yml L152-162, the fragment step. It sits inside the static-checks job ("GDScript Lint & Format"):
    # 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.md L82. It tells contributors the label waives the check, but says nothing about when the label has to go on:
    `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):

  1. The fragment step fails.
  2. Adding the label doesn't start a run, so the required check stays red and the merge is blocked.
  3. 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^1

From 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 --require check out of static-checks into a small workflow of its own. It should run on pull_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 labeled to ci.yml itself. Every label change, including the area labels people add by hand, would then re-run the GUT shards, and cancel-in-progress would cancel a run already in flight. labeler.yml uses GITHUB_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

  1. saworbit commented on Oct 21, 2026

    @saworbit
    OwnerAuthor

    #1487 is the other half of the same check: --require counts a deleted fragment as bringing one. If the check moves into its own workflow as proposed here, the --diff-filter=A change can go in with it, along with an explicit exemption for the compile/release PR.

  2. added
    enhancementNew feature or request
    area: ciWorkflows, contributor tooling, dependency pins
    P2Medium. Real bug or gap with a workaround. May ship with a one-line accept note.
    on Oct 21, 2026
  3. saworbit commented on Oct 21, 2026

    @saworbit
    OwnerAuthor

    Fixed in bd50211 on #1503. The fragment check is now its own workflow, changelog-fragment.yml, job Changelog Fragment, and it runs on labeled and unlabeled too. CI's lint job no longer runs it. It needs adding to the main ruleset'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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium. Real bug or gap with a workaround. May ship with a one-line accept note.area: ciWorkflows, contributor tooling, dependency pinsenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions