diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/lerna.json b/core/conventional-commits/__tests__/__fixtures__/major-zero/lerna.json new file mode 100644 index 0000000000..84e537a34e --- /dev/null +++ b/core/conventional-commits/__tests__/__fixtures__/major-zero/lerna.json @@ -0,0 +1,8 @@ +{ + "command": { + "publish": { + "conventionalCommits": true + } + }, + "version": "independent" +} diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/package.json b/core/conventional-commits/__tests__/__fixtures__/major-zero/package.json new file mode 100644 index 0000000000..5c1c951592 --- /dev/null +++ b/core/conventional-commits/__tests__/__fixtures__/major-zero/package.json @@ -0,0 +1,5 @@ +{ + "name": "conventional-commits-major-zero", + "repository": "lerna/conventional-commits-major-zero", + "version": "0.0.0-root" +} diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-0/CHANGELOG.md b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-0/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-0/package.json b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-0/package.json new file mode 100644 index 0000000000..4415541841 --- /dev/null +++ b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-0/package.json @@ -0,0 +1,5 @@ +{ + "name": "package-0", + "repository": "lerna/conventional-commits-major-zero", + "version": "0.1.0" +} diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-1/CHANGELOG.md b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-1/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-1/package.json b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-1/package.json new file mode 100644 index 0000000000..fdfbc2b635 --- /dev/null +++ b/core/conventional-commits/__tests__/__fixtures__/major-zero/packages/package-1/package.json @@ -0,0 +1,5 @@ +{ + "name": "package-1", + "repository": "lerna/conventional-commits-major-zero", + "version": "1.0.0" +} diff --git a/core/conventional-commits/__tests__/conventional-commits.test.js b/core/conventional-commits/__tests__/conventional-commits.test.js index 7b535e8d21..a23b2ddd55 100644 --- a/core/conventional-commits/__tests__/conventional-commits.test.js +++ b/core/conventional-commits/__tests__/conventional-commits.test.js @@ -217,6 +217,21 @@ describe("conventional-commits", () => { ).rejects.toThrow("Unable to load conventional-changelog preset 'conventional-changelog-garbage/pail'"); }); + describe("bump for major version zero", () => { + it("treats breaking changes as semver-minor", async () => { + const cwd = await initFixture("major-zero"); + const [pkg0] = await getPackages(cwd); + + // make a change in package-0 + await pkg0.set("changed", 1).serialize(); + await gitAdd(cwd, pkg0.manifestLocation); + await gitCommit(cwd, "feat: changed\n\nBREAKING CHANGE: changed"); + + const bump = await recommendVersion(pkg0, "independent", {}); + expect(bump).toBe("0.2.0"); + }); + }); + describe("prerelease bumps", () => { let cwd; let pkg; diff --git a/core/conventional-commits/lib/recommend-version.js b/core/conventional-commits/lib/recommend-version.js index f13ae56df9..f524f9d048 100644 --- a/core/conventional-commits/lib/recommend-version.js +++ b/core/conventional-commits/lib/recommend-version.js @@ -51,7 +51,7 @@ function recommendVersion(pkg, type, { changelogPreset, rootPath, tagPrefix, pre // result might be undefined because some presets are not consistent with angular // we still need to bump _something_ because lerna saw a change here - const releaseType = data.releaseType || "patch"; + let releaseType = data.releaseType || "patch"; if (prereleaseId) { const shouldBump = shouldBumpPrerelease(releaseType, pkg.version); @@ -59,6 +59,26 @@ function recommendVersion(pkg, type, { changelogPreset, rootPath, tagPrefix, pre log.verbose(type, "increment %s by %s", pkg.version, prereleaseType); resolve(semver.inc(pkg.version, prereleaseType, prereleaseId)); } else { + if (semver.major(pkg.version) === 0) { + // According to semver, major version zero (0.y.z) is for initial + // development. Anything MAY change at any time. The public API + // SHOULD NOT be considered stable. The version 1.0.0 defines + // the (initial stable) public API. + // + // To allow monorepos to use major version zero meaningfully, + // the transition from 0.x to 1.x must be explicitly requested + // by the user. Breaking changes MUST NOT automatically bump + // the major version from 0.x to 1.x. + // + // The usual convention is to use semver-patch bumps for bugfix + // releases and semver-minor for everything else, including + // breaking changes. This matches the behavior of `^` operator + // as implemented by `npm`. + // + if (releaseType === "major") { + releaseType = "minor"; + } + } log.verbose(type, "increment %s by %s", pkg.version, releaseType); resolve(semver.inc(pkg.version, releaseType)); }