From a9b9f97457e4e4b0cac7f4ce562458d921a1f9be Mon Sep 17 00:00:00 2001 From: Daniel Stockman <5605+evocateur@users.noreply.github.com> Date: Tue, 12 May 2020 14:58:43 -0700 Subject: [PATCH] feat(version): Ignore private packages completely with `--no-private` - No more spurious tags for unpublished packages - No more mutation of private manifest versions - No more redundant checking for previous releases of private packages Configure this option in lerna.json for greatest consistency: ``` { "command": { "version": { "private": false } }, "version": "1.2.3" } ``` (version can be whatever it is already, included for illustrative purposes) --- .../publish/__tests__/publish-canary.test.js | 27 ++++++++++ commands/version/README.md | 8 +++ .../__tests__/version-bump-prerelease.test.js | 53 +++++++++++++++++++ .../version/__tests__/version-bump.test.js | 12 +++++ .../version/__tests__/version-command.test.js | 51 ++++++++++++++++++ .../version-conventional-commits.test.js | 18 +++++++ commands/version/command.js | 10 ++++ commands/version/index.js | 13 +++++ 8 files changed, 192 insertions(+) diff --git a/commands/publish/__tests__/publish-canary.test.js b/commands/publish/__tests__/publish-canary.test.js index e8858e177d..ffa107f671 100644 --- a/commands/publish/__tests__/publish-canary.test.js +++ b/commands/publish/__tests__/publish-canary.test.js @@ -401,3 +401,30 @@ test("publish --canary without _any_ tags (independent)", async () => { } `); }); + +test("publish --canary --no-private", async () => { + // mostly to say, "yay you didn't explode!" + // publish always skips private packages already + const cwd = await initTaggedFixture("independent"); + await setupChanges( + cwd, + ["packages/package-1/all-your-base.js", "belong to us"], + [ + "packages/package-3/package.json", + JSON.stringify({ + name: "package-3", + version: "3.0.0", + private: true, + }), + ] + ); + + await lernaPublish(cwd)("--canary", "--no-private"); + + expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` + Object { + "package-1": 1.0.1-alpha.0+SHA, + "package-2": 2.0.1-alpha.0+SHA, + } + `); +}); diff --git a/commands/version/README.md b/commands/version/README.md index 5cdaa3bc3f..544eed8ef4 100644 --- a/commands/version/README.md +++ b/commands/version/README.md @@ -60,6 +60,7 @@ Running `lerna version --conventional-commits` without the above flags will rele - [`--no-changelog`](#--no-changelog) - [`--no-commit-hooks`](#--no-commit-hooks) - [`--no-git-tag-version`](#--no-git-tag-version) +- [`--no-private`](#--no-private) - [`--no-push`](#--no-push) - [`--preid`](#--preid) - [`--sign-git-commit`](#--sign-git-commit) @@ -317,6 +318,13 @@ Pass `--no-git-tag-version` to disable the behavior. This option is analogous to the `npm version` option [`--git-tag-version`](https://docs.npmjs.com/misc/config#git-tag-version), just inverted. +### `--no-private` + +By default, `lerna version` will include private packages when choosing versions, making commits, and tagging releases. +Pass `--no-private` to disable this behavior. + +Note that this option does _not_ exclude [private scoped packages](https://docs.npmjs.com/about-private-packages), only those with a [`"private": true` field](https://docs.npmjs.com/configuring-npm/package-json.html#private) in their package.json file. + ### `--no-push` By default, `lerna version` will push the committed and tagged changes to the configured [git remote](#--git-remote-name). diff --git a/commands/version/__tests__/version-bump-prerelease.test.js b/commands/version/__tests__/version-bump-prerelease.test.js index 15acbfe874..3d1526136e 100644 --- a/commands/version/__tests__/version-bump-prerelease.test.js +++ b/commands/version/__tests__/version-bump-prerelease.test.js @@ -137,6 +137,8 @@ test("independent version prerelease does not bump on every unrelated change", a "package.json": File({ name: "pkg-b", version: "1.0.0-bumps.1", + // TODO: (major) make --no-private the default + private: true, }), }), }), @@ -180,3 +182,54 @@ Publish - pkg-a@1.0.2 `); }); + +test("independent version prerelease respects --no-private", async () => { + const cwd = tempy.directory(); + const fixture = new Tacks( + Dir({ + "lerna.json": File({ + version: "independent", + }), + "package.json": File({ + name: "no-private-versioning", + }), + packages: Dir({ + "pkg-1": Dir({ + "package.json": File({ + name: "pkg-1", + version: "1.0.0", + devDependencies: { + "pkg-2": "^2.0.0", + }, + }), + }), + "pkg-2": Dir({ + "package.json": File({ + name: "pkg-2", + version: "2.0.0", + private: true, + }), + }), + }), + }) + ); + fixture.create(cwd); + + await gitInit(cwd, "."); + await gitAdd(cwd, "-A"); + await gitCommit(cwd, "init"); + + // TODO: (major) make --no-private the default + await lernaVersion(cwd)("prerelease", "--no-private"); + + const changedFiles = await showCommit(cwd, "--name-only"); + expect(changedFiles).toMatchInlineSnapshot(` + Publish + + - pkg-1@1.0.1-alpha.0 + + HEAD -> master, tag: pkg-1@1.0.1-alpha.0 + + packages/pkg-1/package.json + `); +}); diff --git a/commands/version/__tests__/version-bump.test.js b/commands/version/__tests__/version-bump.test.js index 0b3d7ab6b9..6dd17ecb46 100644 --- a/commands/version/__tests__/version-bump.test.js +++ b/commands/version/__tests__/version-bump.test.js @@ -94,6 +94,8 @@ describe("version bump", () => { const message = await getCommitMessage(testDir); expect(message).toContain("package-1@1.0.1-alpha.0"); + // TODO: (major) make --no-private the default + expect(message).toContain("package-5@5.0.1-alpha.0"); }); test("prerelease increments version with custom --preid", async () => { @@ -104,4 +106,14 @@ describe("version bump", () => { const message = await getCommitMessage(testDir); expect(message).toContain("package-1@1.0.1-foo.0"); }); + + it("ignores private packages with --no-private", async () => { + const testDir = await initFixture("independent"); + + await lernaVersion(testDir)("patch", "--no-private"); + + const message = await getCommitMessage(testDir); + // TODO: (major) make --no-private the default + expect(message).not.toContain("package-5"); + }); }); diff --git a/commands/version/__tests__/version-command.test.js b/commands/version/__tests__/version-command.test.js index 68edd7226d..2ccabb2830 100644 --- a/commands/version/__tests__/version-command.test.js +++ b/commands/version/__tests__/version-command.test.js @@ -156,6 +156,21 @@ describe("VersionCommand", () => { const patch = await showCommit(testDir); expect(patch).toMatchSnapshot(); }); + + it("does not bump major of private packages with --no-private", async () => { + const testDir = await initFixture("normal"); + + // despite being a pendant leaf... + collectUpdates.setUpdated(testDir, "package-4"); + PromptUtilities.mockChoices("major"); + + await lernaVersion(testDir)("--no-private"); + + const patch = await showCommit(testDir, "--name-only"); + expect(patch).not.toContain("package-5"); + // ...all packages are still majored + expect(patch).toContain("package-1"); + }); }); describe("independent mode", () => { @@ -281,6 +296,42 @@ describe("VersionCommand", () => { }); }); + // TODO: (major) make --no-private the default + describe("--no-private", () => { + it("does not universally version private packages", async () => { + const testDir = await initFixture("normal"); + await lernaVersion(testDir)("--no-private"); + + const patch = await showCommit(testDir, "--name-only"); + expect(patch).not.toContain("package-5"); + }); + + it("does not independently version private packages", async () => { + const testDir = await initFixture("independent"); + await lernaVersion(testDir)("--no-private"); + + const patch = await showCommit(testDir, "--name-only"); + expect(patch).not.toContain("package-5"); + }); + + it("consumes configuration from lerna.json", async () => { + const testDir = await initFixture("normal"); + + await fs.outputJSON(path.join(testDir, "lerna.json"), { + version: "1.0.0", + command: { + version: { + private: false, + }, + }, + }); + await lernaVersion(testDir)(); + + const patch = await showCommit(testDir, "--name-only"); + expect(patch).not.toContain("package-5"); + }); + }); + describe("--no-push", () => { it("versions changed packages without git push", async () => { const testDir = await initFixture("normal"); diff --git a/commands/version/__tests__/version-conventional-commits.test.js b/commands/version/__tests__/version-conventional-commits.test.js index 86df000613..7488a135d8 100644 --- a/commands/version/__tests__/version-conventional-commits.test.js +++ b/commands/version/__tests__/version-conventional-commits.test.js @@ -141,6 +141,15 @@ describe("--conventional-commits", () => { expect(ConventionalCommitUtilities.updateChangelog).not.toHaveBeenCalled(); }); + + it("should respect --no-private", async () => { + const cwd = await initFixture("independent"); + // TODO: (major) make --no-private the default + await lernaVersion(cwd)("--conventional-commits", "--no-private"); + + const changedFiles = await showCommit(cwd, "--name-only"); + expect(changedFiles).not.toContain("package-5"); + }); }); describe("fixed mode", () => { @@ -273,6 +282,15 @@ describe("--conventional-commits", () => { expect(ConventionalCommitUtilities.updateChangelog).not.toHaveBeenCalled(); }); + + it("should respect --no-private", async () => { + const cwd = await initFixture("normal"); + // TODO: (major) make --no-private the default + await lernaVersion(cwd)("--conventional-commits", "--no-private"); + + const changedFiles = await showCommit(cwd, "--name-only"); + expect(changedFiles).not.toContain("package-5"); + }); }); it("avoids duplicating previously-released version", async () => { diff --git a/commands/version/command.js b/commands/version/command.js index 4109ff1db7..cf288ad72a 100644 --- a/commands/version/command.js +++ b/commands/version/command.js @@ -105,6 +105,16 @@ exports.builder = (yargs, composed) => { hidden: true, type: "boolean", }, + // TODO: (major) make --no-private the default + "no-private": { + describe: "Do not version private packages.", + type: "boolean", + }, + private: { + // proxy for --no-private + hidden: true, + type: "boolean", + }, "no-push": { describe: "Do not push tagged commit to git remote.", type: "boolean", diff --git a/commands/version/index.js b/commands/version/index.js index 80bd8db148..ca89292098 100644 --- a/commands/version/index.js +++ b/commands/version/index.js @@ -191,6 +191,12 @@ class VersionCommand extends Command { this.execOpts, this.options ).filter(node => { + // --no-private completely removes private packages from consideration + if (node.pkg.private && this.options.private === false) { + // TODO: (major) make --no-private the default + return false; + } + if (!node.version) { // a package may be unversioned only if it is private if (node.pkg.private) { @@ -439,6 +445,13 @@ class VersionCommand extends Command { if (hasBreakingChange) { // _all_ packages need a major version bump whenever _any_ package does this.updates = Array.from(this.packageGraph.values()); + + // --no-private completely removes private packages from consideration + if (this.options.private === false) { + // TODO: (major) make --no-private the default + this.updates = this.updates.filter(node => !node.pkg.private); + } + this.updatesVersions = new Map(this.updates.map(({ name }) => [name, this.globalVersion])); } else { this.updatesVersions = versions;