Skip to content

Commit

Permalink
feat(publish): Add option --no-git-reset to leave unstaged changes …
Browse files Browse the repository at this point in the history
…in working tree (#1791)
  • Loading branch information
yoitsro authored and evocateur committed Nov 23, 2018
1 parent b69a728 commit eae5619
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 35 deletions.
13 changes: 13 additions & 0 deletions commands/publish/README.md
Expand Up @@ -42,6 +42,7 @@ but have the package contents themselves consistently published by an automated

* [`--canary`](#--canary)
* [`--npm-client <client>`](#--npm-client-client)
* [`--git-reset`](#--git-reset)
* [`--npm-tag <dist-tag>`](#--npm-tag-dist-tag)
* [`--no-verify-access`](#--no-verify-access)
* [`--registry <url>`](#--registry-url)
Expand All @@ -68,6 +69,18 @@ When run with this flag, `lerna publish` publishes packages in a more granular w

> The intended use case for this flag is a per commit level release or nightly release.
### `--git-reset`

Ensures the working tree is reset by any changes the `publish` command makes.

To not reset the working tree, specify `--no-git-reset`. This is especially useful when used as part of a CI pipeline in conjunction with the `--canary` flag. For instance, the `package.json` version numbers which have been bumped may need to be used in subsequent CI pipeline steps (such as Docker builds).

The default `--git-reset` is `true`.

```sh
lerna publish --git-reset
```

### `--npm-client <client>`

Must be an executable that knows how to publish packages to an npm registry.
Expand Down
96 changes: 96 additions & 0 deletions commands/publish/__tests__/publish-canary-no-git-reset.test.js
@@ -0,0 +1,96 @@
"use strict";

// we're actually testing integration with git
jest.unmock("@lerna/collect-updates");

// local modules _must_ be explicitly mocked
jest.mock("../lib/get-packages-without-license");
jest.mock("../lib/verify-npm-package-access");
jest.mock("../lib/get-npm-username");
jest.mock("../lib/git-checkout");

const fs = require("fs-extra");
const path = require("path");

// mocked modules
const writePkg = require("write-pkg");
const npmPublish = require("@lerna/npm-publish");
const PromptUtilities = require("@lerna/prompt");
const gitCheckout = require("../lib/git-checkout");

// helpers
const initFixture = require("@lerna-test/init-fixture")(__dirname);
const gitAdd = require("@lerna-test/git-add");
const gitTag = require("@lerna-test/git-tag");
const gitCommit = require("@lerna-test/git-commit");

// test command
const lernaPublish = require("@lerna-test/command-runner")(require("../command"));

// stabilize commit SHA
expect.addSnapshotSerializer(require("@lerna-test/serialize-git-sha"));

async function initTaggedFixture(fixtureName) {
const cwd = await initFixture(fixtureName);

if (fixtureName.indexOf("independent") > -1) {
await Promise.all([
gitTag(cwd, "package-1@1.0.0"),
gitTag(cwd, "package-2@2.0.0"),
gitTag(cwd, "package-3@3.0.0"),
gitTag(cwd, "package-4@4.0.0"),
gitTag(cwd, "package-5@5.0.0"),
]);
} else {
await gitTag(cwd, "v1.0.0");
}

return cwd;
}

/**
* ALL canary tests _require_ an actual commit _past_ the original tag,
* as a canary release on the same commit as a tagged release is non-sensical.
*
* @param {String} cwd Current working directory
* @param {Array[String]..} tuples Any number of [filePath, fileContent] configs
*/
async function setupChanges(cwd, ...tuples) {
await Promise.all(
tuples.map(([filePath, content]) => fs.outputFile(path.join(cwd, filePath), content, "utf8"))
);
await gitAdd(cwd, ".");
await gitCommit(cwd, "setup");
}

test("publish --canary --no-git-reset", async () => {
const cwd = await initTaggedFixture("normal");

await setupChanges(
cwd,
["packages/package-1/all-your-base.js", "belong to us"],
["packages/package-4/non-matching-semver.js", "senpai noticed me"]
);
await lernaPublish(cwd)("--canary", "--no-git-reset");

expect(PromptUtilities.confirm).toHaveBeenLastCalledWith(
"Are you sure you want to publish these packages?"
);
expect(npmPublish.registry).toMatchInlineSnapshot(`
Map {
"package-1" => "canary",
"package-3" => "canary",
"package-4" => "canary",
"package-2" => "canary",
}
`);
expect(writePkg.updatedVersions()).toMatchInlineSnapshot(`
Object {
"package-1": 1.0.1-alpha.0+SHA,
"package-2": 1.0.1-alpha.0+SHA,
"package-3": 1.0.1-alpha.0+SHA,
"package-4": 1.0.1-alpha.0+SHA,
}
`);
expect(gitCheckout).toHaveBeenCalledTimes(0);
});
5 changes: 5 additions & 0 deletions commands/publish/command.js
Expand Up @@ -57,6 +57,11 @@ exports.builder = yargs => {
alias: "yes",
type: "boolean",
},
"git-reset": {
describe: "Reset the git working tree.\nPass --no-git-reset to disable.",
type: "boolean",
default: true,
},
};

return composeVersionOptions(yargs)
Expand Down
5 changes: 4 additions & 1 deletion commands/publish/index.js
Expand Up @@ -159,7 +159,10 @@ class PublishCommand extends Command {
chain = chain.then(() => this.annotateGitHead());
chain = chain.then(() => this.packUpdated());
chain = chain.then(() => this.publishPacked());
chain = chain.then(() => this.resetChanges());

if (this.options.gitReset) {
chain = chain.then(() => this.resetChanges());
}

if (this.options.tempTag) {
chain = chain.then(() => this.npmUpdateAsLatest());
Expand Down
9 changes: 9 additions & 0 deletions helpers/git-status/index.js
@@ -0,0 +1,9 @@
"use strict";

const execa = require("execa");

module.exports = gitStatus;

function gitStatus(cwd) {
return execa("git", ["status"], { cwd });
}
11 changes: 11 additions & 0 deletions helpers/git-status/package.json
@@ -0,0 +1,11 @@
{
"name": "@lerna-test/git-status",
"version": "0.0.0-test-only",
"description": "A local test helper",
"main": "index.js",
"private": true,
"license": "MIT",
"dependencies": {
"execa": "^1.0.0"
}
}
40 changes: 40 additions & 0 deletions integration/lerna-publish-canary.test.js
Expand Up @@ -5,6 +5,7 @@ const path = require("path");
const cliRunner = require("@lerna-test/cli-runner");
const commitChangeToPackage = require("@lerna-test/commit-change-to-package");
const gitTag = require("@lerna-test/git-tag");
const gitStatus = require("@lerna-test/git-status");
const cloneFixture = require("@lerna-test/clone-fixture")(
path.resolve(__dirname, "../commands/publish/__tests__")
);
Expand Down Expand Up @@ -40,3 +41,42 @@ Successfully published:
- package-3@1.0.1-alpha.0+SHA
`);
});

test("lerna publish --canary --no-git-reset leaves the working tree dirty", async () => {
const { cwd } = await cloneFixture("normal");
const args = ["publish", "--canary", "--yes", "--no-git-reset"];

await gitTag(cwd, "v1.0.0");
await commitChangeToPackage(cwd, "package-1", "change", { change: true });

const { stdout } = await cliRunner(cwd, env)(...args);
expect(stdout).toMatchInlineSnapshot(`
Found 3 packages to publish:
- package-1 => 1.0.1-alpha.0+SHA
- package-2 => 1.0.1-alpha.0+SHA
- package-3 => 1.0.1-alpha.0+SHA
Successfully published:
- package-1@1.0.1-alpha.0+SHA
- package-2@1.0.1-alpha.0+SHA
- package-3@1.0.1-alpha.0+SHA
`);

const { stdout: statusStdOut } = await gitStatus();
expect(statusStdOut).toMatchInlineSnapshot(`
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: packages/package-1/package.json
modified: packages/package-2/package.json
modified: packages/package-3/package.json
no changes added to commit (use "git add" and/or "git commit -a")
`);
});
70 changes: 36 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -35,6 +35,7 @@
"@lerna-test/git-add": "file:helpers/git-add",
"@lerna-test/git-commit": "file:helpers/git-commit",
"@lerna-test/git-init": "file:helpers/git-init",
"@lerna-test/git-status": "file:helpers/git-status",
"@lerna-test/git-tag": "file:helpers/git-tag",
"@lerna-test/init-fixture": "file:helpers/init-fixture",
"@lerna-test/load-manifests": "file:helpers/load-manifests",
Expand Down

0 comments on commit eae5619

Please sign in to comment.