Using Exclamation Mark for Breaking Change Confuses Parser
shellscape opened this issue · 10 comments
It appears that the conventional-commits-parser
package doesn't directly support the exclamation mark demarcation for noting a breaking change in a commit. Parsing the following commit measage:
chore!: drop node 8 support
Will yield a node with the following structure:
{
type: null,
scope: null,
subject: null,
merge: null,
header: 'chore!: drop node 8 support',
body: null,
footer: null,
notes: [],
references: [],
mentions: [],
revert: null,
hash: 'd0059c44727bd0562db42aedeed60713b698c264',
breaking: false
}
A notable number of properties are left null
in addition to not recognizing the !
indicating a breaking change. Support for !
is noted in the first item in the Specification https://www.conventionalcommits.org/en/v1.0.0/#specification.
Ran into the same issue. Nothing ends up in changelog when using exclamation mark.
+1. We are having to use BREAKING CHANGE:
in the footer of the commit message for now. But this should be supported as it is part of the conventional commits specification as mentioned above
I solved this by supplying the parser function with the second options
parameter.
The options argument includes the fields
headerPattern: /^(\w*)(?:\((.*)\))?!?: (.*)$/
and
breakingHeaderPattern: /^(\w*)(?:\((.*)\))?!: (.*)$/
which seemingly solved the issue.
I got these options from the "conventional-changelog-conventionalcommits" package, i.e.
const parser = require("conventional-commits-parser");
const spec = require("conventional-changelog-conventionalcommits");
...
const options = await spec();
const parsed = parser.sync(COMMIT, options.parserOpts);
resulting with COMMIT as chore!: drop node 8 support
in this:
{
type: 'chore',
scope: null,
subject: 'drop node 8 support',
merge: null,
header: 'chore!: drop node 8 support',
body: null,
footer: null,
notes: [ { title: 'BREAKING CHANGE', text: 'drop node 8 support' } ],
references: [],
mentions: [],
revert: null
}
Any update to have the fix merged?
Got caught with this today and made a botched release because of it :(
In our case we solved by overwriting conventional-changelog-conventionalcommits
config
in the following way:
note the *!
type
'use strict'
const config = require('conventional-changelog-conventionalcommits');
module.exports = config({
"types": [
{ type: 'feat', section: 'New Features' },
{ type: 'fix', section: 'Bugs' },
{ type: '*!', section: 'BREAKING CHANGES' }
]
})
I tried both @tfn220189 's suggestion AND @fhenz's suggestion. Still no luck. Oddly, the changelog writer is getting the 'BREAKING CHANGE' note, but the commit analyzer still thinks feat!: something
is a minor change, not a major one. Here's my entire release.config.js
file:
const typeTransforms = [
['feat', 'Features'],
['fix', 'Bug Fixes'],
['perf', 'Performance'],
['revert', 'Reverts'],
['docs', 'Documentation'],
['style', 'Code Style'],
['refactor', 'Code Refactoring'],
['chore', 'Chores'],
['test', 'Tests'],
['build', 'Build'],
['ci', 'Continuous Integration'],
['*!', 'BREAKING CHANGES'],
];
const parserOpts = {
"noteKeywords": ["BREAKING-CHANGE", "BREAKING CHANGE", "BREAKING CHANGES"],
"headerPattern": /^(\w*)(?:\(([\w\$\.\-\* ]*)\))?!?: (.*)$/,
"breakingHeaderPattern": /^(\w*)(?:\((.*)\))?!: (.*)$/,
}
// the following is copied and modified from https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-angular/writer-opts.js
// eslint-disable-next-line max-lines-per-function
function transform(commit, context) {
const issues = [];
commit.notes.forEach((note) => {
note.title = 'BREAKING CHANGES';
});
typeTransforms.forEach((type) => {
if (commit.type === type[0]) {
commit.type = type[1];
}
});
if (commit.scope === '*') {
commit.scope = '';
}
if (typeof commit.hash === 'string') {
commit.shortHash = commit.hash.substring(0, 7);
}
if (typeof commit.subject === 'string') {
let url = context.repository
? `${context.host}/${context.owner}/${context.repository}`
: context.repoUrl;
if (url) {
url = `${url}/issues/`;
// Issue URLs.
commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => {
issues.push(issue);
return `[#${issue}](${url}${issue})`;
});
}
if (context.host) {
// User URLs.
commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => {
if (username.includes('/')) {
return `@${username}`;
}
return `[@${username}](${context.host}/${username})`;
});
}
}
// remove references that already appear in the subject
commit.references = commit.references.filter((reference) => issues.indexOf(reference.issue) === -1);
return commit;
}
module.exports = {
plugins: [
['@semantic-release/commit-analyzer', {
releaseRules: [
{type: 'docs', release: 'patch'},
{type: 'feat', release: 'minor'},
{type: 'test', release: 'patch'},
{type: 'chore', release: 'patch'},
{type: 'perf', release: 'patch'},
{type: 'style', release: 'patch'},
{type: 'ci', release: 'patch'},
{type: 'refactor', release: 'patch'},
{type: 'build', release: 'patch'},
{type: 'fix', release: 'patch'},
{type: 'revert', release: 'patch'},
],
parserOpts,
}],
['@semantic-release/release-notes-generator', {
writerOpts: {transform},
parserOpts,
}],
'@semantic-release/npm',
'@semantic-release/github',
],
};
We ended up giving up on this package and are using the parser directly. Over a year and no one from the team has addressed this, so I wouldn't hold out any hope for it being fixed. Here's the script that we use in place of conventional-changelog
which does our changelog generation for packages in the Rollup plugins repo: https://github.com/rollup/plugins/blob/master/scripts/release.ts
Hi guys, I just made a commitizen cli. You can try running the command npx czg break
in any of your projects.
demo:
guide | website:
https://cz-git.qbb.sh/recipes/breakingchange.html
hope it can help u
Exclamation works perfectly with conventionalcommits
preset:
npx conventional-recommended-bump --preset conventionalcommits
@carloschneider that's not the context of this issue