diff --git a/packages/shipjs-lib/src/lib/const.js b/packages/shipjs-lib/src/lib/const.js index a8191219..cbdf9641 100644 --- a/packages/shipjs-lib/src/lib/const.js +++ b/packages/shipjs-lib/src/lib/const.js @@ -11,6 +11,6 @@ export const GIT_COMMIT_PREFIX_PATCH = new Set([ export const GIT_COMMIT_PREFIX_MINOR = new Set(['feat']); -export const GIT_COMMIT_BREAKING_CHANGE = 'BREAKING CHANGE'; +export const GIT_COMMIT_BREAKING_CHANGE = /^BREAKING[ -]CHANGE\s*:/; export const RELEASE_BRANCH = 'releases'; diff --git a/packages/shipjs-lib/src/lib/util/__tests__/getNextVersion.spec.js b/packages/shipjs-lib/src/lib/util/__tests__/getNextVersion.spec.js index 05a9232e..20d408c4 100644 --- a/packages/shipjs-lib/src/lib/util/__tests__/getNextVersion.spec.js +++ b/packages/shipjs-lib/src/lib/util/__tests__/getNextVersion.spec.js @@ -97,6 +97,55 @@ describe('getNextVersionFromCommitMessages', () => { expect(actual).toBe('1.0.0'); }); + it('detects major from BREAKING-CHANGE with hyphen', () => { + const version = '1.2.3'; + const titles = 'feat: abc'; + const bodies = 'BREAKING-CHANGE: this also breaks things.'; + const { version: actual } = getNextVersionFromCommitMessages( + version, + titles, + bodies + ); + expect(actual).toBe('2.0.0'); + }); + + it('does not trigger major from prose mentioning breaking changes', () => { + const version = '1.2.3'; + const titles = 'feat: upgrade storybook'; + const bodies = + 'This PR includes breaking changes around package consolidation.'; + const { version: actual } = getNextVersionFromCommitMessages( + version, + titles, + bodies + ); + expect(actual).toBe('1.3.0'); + }); + + it('detects major from ! suffix in title', () => { + const version = '1.2.3'; + const titles = 'feat!: remove deprecated API'; + const bodies = ''; + const { version: actual } = getNextVersionFromCommitMessages( + version, + titles, + bodies + ); + expect(actual).toBe('2.0.0'); + }); + + it('detects major from scoped ! suffix in title', () => { + const version = '1.2.3'; + const titles = 'fix(auth)!: change token format'; + const bodies = ''; + const { version: actual } = getNextVersionFromCommitMessages( + version, + titles, + bodies + ); + expect(actual).toBe('2.0.0'); + }); + it('gets a null with no commit messages', () => { const version = '0.0.1'; const titles = ''; diff --git a/packages/shipjs-lib/src/lib/util/getCommitNumbersPerType.js b/packages/shipjs-lib/src/lib/util/getCommitNumbersPerType.js index b35a5de0..a52221eb 100644 --- a/packages/shipjs-lib/src/lib/util/getCommitNumbersPerType.js +++ b/packages/shipjs-lib/src/lib/util/getCommitNumbersPerType.js @@ -16,7 +16,7 @@ export default function getCommitNumbersPerType(commitTitles) { ignoredMessages.push(title); return; } - const prefix = match[1].toLowerCase(); + const prefix = match[1].replace(/!$/, '').toLowerCase(); if ( GIT_COMMIT_PREFIX_PATCH.has(prefix) || GIT_COMMIT_PREFIX_MINOR.has(prefix) diff --git a/packages/shipjs-lib/src/lib/util/getNextVersion.js b/packages/shipjs-lib/src/lib/util/getNextVersion.js index 47bfd83a..20607079 100644 --- a/packages/shipjs-lib/src/lib/util/getNextVersion.js +++ b/packages/shipjs-lib/src/lib/util/getNextVersion.js @@ -18,10 +18,13 @@ export function getNextVersionFromCommitMessages(version, titles, bodies) { bodies .toUpperCase() .split('\n') - .some((line) => line.startsWith(GIT_COMMIT_BREAKING_CHANGE)) + .some((line) => GIT_COMMIT_BREAKING_CHANGE.test(line.trim())) ) { return { version: inc(version, 'major') }; } + if (titles.split('\n').some((line) => /^\w+(\(.*?\))?!:/.test(line.trim()))) { + return { version: inc(version, 'major') }; + } const { numbers, ignoredMessages } = getCommitNumbersPerType(titles); const minor = Array.from(GIT_COMMIT_PREFIX_MINOR).some( (prefix) => numbers[prefix] > 0