Skip to content

fix(generate-changelog): do not fail on release commits or empty changelogs - #78

Merged
marc0olo merged 3 commits into
mainfrom
fix/generate-changelog-release-commits
Sep 17, 2026
Merged

marc0olo merged 3 commits into
mainfrom
fix/generate-changelog-release-commits

Conversation

@marc0olo

@marc0olo marc0olo commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes #75.

generate_changelog runs on every push to main, release-PR merges included. Commitizen has nothing to add on those and exits non-zero, so the job fails.

Behaviour changes

  • A head commit whose subject matches the new release_commit_pattern input skips changelog generation entirely. Default ^chore:[[:space:]]release([[:space:]]|$); an empty string disables the check.
  • Commitizen exit code 3, No commits found, no longer fails the job.
  • An invalid release_commit_pattern now fails the step. Bash returns 2 for a malformed expression, which previously read as "not a release commit" and silently disabled the check.
  • Commitizen is pinned to 4.18.1, rather than pip install -U upgrading it on every run.

For the reviewer

Exit 16 stays fatal. It also fires when tags are genuinely unavailable, so swallowing it would let changelog generation stop silently. The subject check covers the release case instead, which means a retitled release PR can still fail.

Inert until #87 lands. The exit-code handling and the Commitizen pin live in actions this workflow still pins at afeee4f.

🤖 Generated with Claude Code

marc0olo and others added 2 commits September 17, 2026 10:01
…gelogs

The generate_changelog workflow fires on every push to main, including when a
release PR is merged. Commitizen then has nothing to add to the changelog and
exits non-zero, failing the job. Two variants have been observed in
dfinity/icp-js-core:

- exit 3 ("No commits found") when the tag already exists
- exit 16 ("No tag found to do an incremental changelog") when the tag has not
  been pushed yet, which is the common case since the release tag is pushed
  manually a couple of minutes after the release PR merges

Both are no-ops in intent, not errors. Two complementary changes:

- Skip the changelog steps entirely when the head commit subject looks like a
  release commit, via a new release_commit_pattern input. This covers the exit
  16 case, whose cause is the tag not existing yet.
- Treat commitizen exit 3 as success in actions/generate-changelog, so a
  release commit that slips past the subject check (retitled release PR, or a
  repo that permits merge commits) still does not fail the job.

Exit 16 deliberately remains fatal. Unlike exit 3 it is ambiguous: it also
fires when tags are genuinely unavailable, for example a shallow clone or a
regression in tag fetching. Swallowing it would turn a loud failure into a
silent no-op where the changelog quietly stops being generated.

Closes #75

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The changelog workflow now treats exit code 3 as a no-op, so the tool
defining that code should not upgrade itself on every run. Verified
against the pinned version that 3 is NO_COMMITS_FOUND.

Also documents release_commit_pattern, which the workflow README was
missing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Update the immutable internal action pins and correct the documented release-pattern escaping before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR prevents changelog generation from failing on release commits or empty changelogs.

Changes:

  • Detects release commits and skips unnecessary workflow steps.
  • Treats Commitizen exit code 3 as successful.
  • Pins Commitizen to 4.18.1 and documents the new behavior.
File summaries
File Reviewed changes and findings
workflows/generate-changelog/README.md Documents the new input. Nit (1 vote): correct the escaped pipe in the default pattern.
actions/setup-commitizen/README.md Documents Commitizen pinning.
actions/setup-commitizen/action.yaml Pins Commitizen. Moderate (1 vote): update workflow callers to use a commit containing this change.
actions/generate-changelog/action.yaml Handles exit code 3. Moderate (1 vote): update the workflow’s immutable action reference.
.github/workflows/generate-changelog.yaml Adds release-commit detection and conditional steps. Moderate (2 votes): update the internal action pins from the pre-change commit.
Review details

Suppressed comments (3)

actions/generate-changelog/action.yaml:19

  • This new exit-code handling is not used by the reusable workflow: .github/workflows/generate-changelog.yaml still invokes dfinity/ci-tools/actions/generate-changelog@afeee4fbdc0683a88ec5a74ed7f59a2ce0e833ad, an immutable SHA from before this change. After merge, an empty changelog will still run the old one-line command and fail with exit 3. Update the pinned action reference to a commit containing this change.
        cz changelog --incremental --merge-prerelease --file-name="$FILE_NAME" --version-scheme semver2

actions/setup-commitizen/action.yaml:11

  • This pin is likewise not used by the repository's workflow callers: check-commit-messages, check-pr-title, and generate-changelog all pin setup-commitizen to afeee4fbdc0683a88ec5a74ed7f59a2ce0e833ad. Because that ref is immutable, those workflows will continue installing the unpinned Commitizen action after this change, so the exit-code contract is still not reproducible. Update their pinned refs to a commit containing this action change.
      run: pip install 'commitizen==4.18.1'

workflows/generate-changelog/README.md:24

  • The documented default contains \| inside an inline code span, so it renders as a backslash plus pipe rather than the | alternation in the workflow default. A user copying this value will not match normal subjects such as chore: release 1.2.3; use a table-safe representation that renders a literal | without the backslash.
| `release_commit_pattern` | Skip changelog generation when the head commit subject matches this extended regular expression. Set to an empty string to disable the check. | `'^chore:[[:space:]]release([[:space:]]\|$)'`                         |
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/generate-changelog.yaml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Invalid release-pattern expressions can silently disable the release guard and should fail explicitly.

Review details

Suppressed comments (1)

.github/workflows/generate-changelog.yaml:119

  • [[ ... =~ ... ]] returns status 2 for an invalid ERE, but because it is used directly as an if condition, set -e does not abort and the else branch records skip=false. A typo in this configurable pattern therefore silently disables the release guard and can let a release commit run through changelog generation; capture the match status and fail explicitly when it is 2.
          if [ -n "$RELEASE_COMMIT_PATTERN" ] && [[ "$subject" =~ $RELEASE_COMMIT_PATTERN ]]; then
            echo 'skip=true' >> "$GITHUB_OUTPUT"
            echo "::notice::Head commit is a release commit ('$subject'); skipping changelog generation."
          else
            echo 'skip=false' >> "$GITHUB_OUTPUT"
          fi
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Bash returns 2 rather than 1 for a malformed regular expression, and as
an if condition that fell through to the else branch and recorded
skip=false. A typo in the pattern therefore disabled the release check
while the job stayed green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@marc0olo

Copy link
Copy Markdown
Member Author

Valid, including the suppressed one, and fixed in 20889b4.

Confirmed the behaviour first — bash returns 2 for a malformed ERE and the if sent that to the else branch:

status=0  MATCH (skip=true)                                  ^chore:[[:space:]]release([[:space:]]|$)
status=2  no match -> else branch sets skip=false            ^chore:[[:space:]]release([[:space:]]|$
status=2  no match -> else branch sets skip=false            [[:invalid:]]

So a typo in a configurable input silently disabled the guard while the job stayed green — the same quiet-failure shape this PR is trying to remove, which makes it worth fixing rather than suppressing.

The match status is now captured and 2 fails the step with ::error::. Verified against all three cases:

pattern=^chore:[[:space:]]release([[:space:]]|$)   exit=0  skip=true
pattern=^chore:[[:space:]]release([[:space:]]|$    exit=1  ::error::release_commit_pattern is not a valid...
pattern=<empty>                                    exit=0  skip=false

Empty still disables the check deliberately, as documented.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved review issues were identified.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@marc0olo
marc0olo merged commit 059c186 into main Sep 17, 2026
16 checks passed
@marc0olo
marc0olo deleted the fix/generate-changelog-release-commits branch September 17, 2026 12:52
marc0olo added a commit that referenced this pull request Sep 17, 2026
#78 changed the generate-changelog and setup-commitizen actions, which
the workflows still pinned from before, so they would have kept running
the previous copies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
marc0olo added a commit that referenced this pull request Sep 17, 2026
* ci: fail when a workflow pins a stale copy of an action

Workflows reference this repository's own actions by commit SHA, and
those pins do not move when an action changes, so a workflow keeps
running the previous copy of it. Passing a newly added input to such an
action is reported as a warning rather than an error, so the run stays
green while the new behaviour does nothing.

actions/create-pr was already a commit behind, which meant the bundle
rebuilt in #79 was not the one the changelog workflow ran.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: note the bump constraints on the self reference check

A bump has to be its own pull request, because --fix can only pin to a
commit that already exists. And the check cannot be a required status
check, since it only reports after a merge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: fail clearly on a shallow clone in the self reference check

Pins are resolved against local history, so a shallow checkout made every
one of them report as an unknown commit, which reads as a problem with the
references rather than with the checkout.

The documented example now shows the checkout it needs, and says that the
script covers this repository only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: pin self references at the default branch, not HEAD

--fix resolved HEAD, so running it from a branch wrote a SHA that squash
and rebase merges discard, leaving a reference to a commit that never
lands. It now pins at the default branch tip and says so when that
differs from HEAD.

Also corrects the usage text, which claimed --fix repoints every
reference unconditionally when it only does so once one has fallen
behind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore: repoint workflow self references at the current commit

#78 changed the generate-changelog and setup-commitizen actions, which
the workflows still pinned from before, so they would have kept running
the previous copies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

generate-changelog: exit code 3 (no commits) causes false failure after release merge

3 participants