feat(release): enable ! notation for breaking changes in semantic-release - #1658
feat(release): enable ! notation for breaking changes in semantic-release#1658brtbrt wants to merge 21 commits into
Conversation
…eaking change support The ! notation for breaking changes (e.g., feat(scope)!:) requires conventional-commits-parser@3.3.0+. Commit-analyzer v10 includes this. Fixes #1657
Adds a validate job that runs semantic-release --dry-run to show what version will be bumped. The release job now depends on validate and requires manual approval (via production environment), allowing reviewers to check the dry-run output before proceeding. Relates to #1657
|
Size stats
|
There was a problem hiding this comment.
Pull request overview
This PR updates the repo’s semantic-release setup so that Conventional Commits breaking changes using the ! notation (e.g. feat(scope)!:) are recognized correctly, and introduces a pre-release validation step that runs semantic-release --dry-run before the actual release proceeds.
Changes:
- Upgraded
@semantic-release/commit-analyzerto^10.0.0(and updatedyarn.lock) to support!breaking-change parsing. - Added a new
validatejob in the release workflow to runsemantic-release --dry-runand gate thereleasejob behind it. - Wired
releaseto depend onvalidate, keeping theenvironment: productionapproval gate for the actual publish.
Reviewed changes
Copilot reviewed 2 out of 12 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
package.json |
Adds @semantic-release/commit-analyzer@^10.0.0 to address breaking-change ! parsing. |
yarn.lock |
Locks the new analyzer version and its updated conventional-commits parser dependency chain. |
.github/workflows/release.yml |
Adds a validate dry-run job and makes release depend on it. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "@semantic-release/changelog": "^6.0.1", | ||
| "@semantic-release/commit-analyzer": "^10.0.0", | ||
| "@semantic-release/git": "^10.0.1", |
|
Deploy preview for mistica-web ready!
Deployed with vercel-action |
|
I would not add a forced dry run validation. I'd just add a checkbox into the release job to perform a dry run. |
|
Accessibility report ℹ️ You can run this locally by executing |
Adds custom releaseRules to @semantic-release/commit-analyzer to ensure commits marked as breaking (via ! notation or BREAKING CHANGE footer) trigger major releases. This explicitly handles the breaking flag that may not be recognized by default with the angular preset. See #1657
Update: Custom releaseRules ConfigurationAdded explicit to the plugin to ensure breaking changes are properly recognized. Why this is neededThe angular preset alone does not reliably recognize the What was added"releaseRules": [
{ "breaking": true, "release": "major" },
{ "revert": true, "release": "patch" },
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "scope": "no-release", "release": false }
]The key rule is the first one: when a commit's |
bfe6119 to
70e8060
Compare
Add explicit note that the ! notation is not supported by semantic-release in the current configuration. Breaking changes must use the BREAKING CHANGE: footer in the commit body instead. See #1657
70e8060 to
f5f7d01
Compare
Add a validation step that rejects any PR title containing the ! character, since the ! notation for breaking changes is not supported by semantic-release.
… jobs Move CLI argument validation from the release job to the validate job. Both jobs now use the same sanitized args, ensuring the dry-run shows the exact version that will be released. Output safe_args from validate job and pass to release job via needs.
Link to issue #1660 which tracks upstream semantic-release issues blocking ! notation support. When those are resolved, these TODOs should be addressed to re-enable the shorter breaking change syntax.
… ! notation support Fixes breaking change detection for ! notation in commit subjects. Version 13.0.1 includes conventional-commits-parser 6.4.0 which properly parses the ! prefix as a breaking change indicator per the Angular convention.
Disable the ! notation guard to test if semantic-release properly detects breaking changes with the new configuration.
5e2f331 to
4b0cc14
Compare
5a093b4 to
4b0cc14
Compare
…mantic-release supports ! notation
|
…antic-release supports ! notation
…llow caret updates
| feat | ||
| chore | ||
| revert | ||
| requireScope: false |
There was a problem hiding this comment.
Makes the scope optional (feat: … and feat(button): … both pass). It is the action's default.
I set it explicitly to document the intent and stay consistent with semantic-release, which does not require a scope either.
| description: 'CLI args' | ||
| required: false | ||
| default: '' | ||
| skipValidation: |
There was a problem hiding this comment.
I would change this the other way around (checkbox to enable dryrun). You can even simplify and have just 1 parametrizable job (the user can run it with dry run enabled or not, it doesn't have 2 steps)
There was a problem hiding this comment.
Happy to collapse it into a single parametrizable job, but not to invert the flag. Validation stays default-on. An opt-in safety check is one that gets forgotten exactly when it matters. skipValidation is a deliberate opt-out, not the other way around.
better safe than sorry.
There was a problem hiding this comment.
The only case when this really matters is when you publish a breaking change as part of a minor/patch version. Don't make everyone go through 2 steps for something that happened once in the last 2 years.
| "preset": "angular", | ||
| "_comment": "TODO #1660: Remove breakingHeaderPattern once semantic-release angular preset supports ! notation natively", | ||
| "parserOpts": { | ||
| "breakingHeaderPattern": "^(\\w*)(?:\\((.*)\\))?!: (.*)$" | ||
| } |
There was a problem hiding this comment.
You resolved my previous comment but didn't change the preset to conventional-commits
There was a problem hiding this comment.
Good catch — the analyzer alone was not enough. release-notes-generator parses commits independently, so without the same override a feat!: … bumps the major version but still renders as a plain feature in the CHANGELOG. I have applied breakingHeaderPattern to both plugins, so ! is now handled consistently.
We are staying on the angular preset to keep our existing changelog format. breakingHeaderPattern is the only gap for ! support, and it is now covered in both places. TODO #1660 tracks removing the overrides once angular supports ! natively. Resolving this.
There was a problem hiding this comment.
Why do you resolve the conversation?
That's probably because in the config we are setting preset to angular in the release notes generator config and you forgot to change it too:

You can set it top level according to the doc:
https://semantic-release.gitbook.io/semantic-release/usage/plugins#plugin-options-configuration

Summary
Fix the
!notation for breaking changes in commit subjects (feat(scope)!: description), which used to be validated on PRs, but ignored as a major when releasing.The whys
ciworkflow is usingcommit-analyzer13.0.1 (the action is using it) .uses: amannn/action-semantic-pull-request@v5releasewas using another one: (10.0.0?) which was buggy about thisthe two workflows used to work with different seantics, risky.
Changes
Core Fix
@semantic-release/commit-analyzerfrom 10.0.0 to 13.0.1 (includes conventional-commits-parser 6.4.0)parserOpts.breakingHeaderPatternconfiguration to enable!notation parsingTesting & Verification!
!notation correctly triggers major version bumps (e.g., 17.1.0 → 18.0.0 forfeat(ci)!:)https://github.com/Telefonica/mistica-web/actions/runs/29528124907/job/87721546071
https://github.com/Telefonica/mistica-web/actions/runs/29513716048/job/87673343062
Related Issues
Fixes #1657
Tracks #1660 (upstream issue - TODO to remove breakingHeaderPattern when fixed)
Migration
Breaking changes can now use the shorter syntax:
Instead of:
Both syntaxes still work. The
!notation is now the preferred approach.Testing
feat(ci)!: ...correctly detected as major version bumpcloses #1657