Skip to content

Commit

Permalink
feat(run): Add --no-bail option
Browse files Browse the repository at this point in the history
Fixes #1351
  • Loading branch information
evocateur committed Mar 29, 2018
1 parent 6e4c6fd commit 893fcc8
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "package-1",
"version": "1.0.0",
"scripts": {
"fail": "exit 1",
"my-script": "echo package-1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "package-2",
"version": "1.0.0",
"dependencies": {
"fail": "exit 1",
"package-1": "^1.0.0"
}
}
63 changes: 0 additions & 63 deletions commands/run/__tests__/__snapshots__/run-command.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`RunCommand in a basic repo always runs env script 1`] = `
Array [
"packages/package-1 npm run env",
"packages/package-4 npm run env",
"packages/package-2 npm run env",
"packages/package-3 npm run env",
]
`;

exports[`RunCommand in a basic repo does not run a script in ignored packages 1`] = `
Array [
"packages/package-1 npm run my-script",
]
`;

exports[`RunCommand in a basic repo runs a script in all packages with --parallel 1`] = `
Array [
"packages/package-1 npm run env",
Expand All @@ -24,57 +9,9 @@ Array [
]
`;

exports[`RunCommand in a basic repo runs a script in packages 1`] = `
Array [
"packages/package-1 npm run my-script",
"packages/package-3 npm run my-script",
]
`;

exports[`RunCommand in a basic repo runs a script in packages with --stream 1`] = `
Array [
"packages/package-1 npm run my-script",
"packages/package-3 npm run my-script",
]
`;

exports[`RunCommand in a basic repo runs a script only in scoped packages 1`] = `
Array [
"packages/package-1 npm run my-script",
]
`;

exports[`RunCommand in a basic repo should filter packages that are not updated with --since 1`] = `
Array [
"packages/package-3 npm run my-script",
]
`;

exports[`RunCommand in a basic repo supports alternate npmClient configuration 1`] = `
Array [
"packages/package-1 yarn run env",
"packages/package-4 yarn run env",
"packages/package-2 yarn run env",
"packages/package-3 yarn run env",
]
`;

exports[`RunCommand in a cyclical repo warns when cycles are encountered 1`] = `
Array [
"packages/package-dag-1 npm run env",
"packages/package-standalone npm run env",
"packages/package-dag-2a npm run env",
"packages/package-dag-2b npm run env",
"packages/package-dag-3 npm run env",
"packages/package-cycle-1 npm run env",
"packages/package-cycle-2 npm run env",
"packages/package-cycle-extraneous npm run env",
]
`;

exports[`RunCommand with --include-filtered-dependencies runs scoped command including filtered deps 1`] = `
Array [
"packages/package-1 npm run my-script",
"packages/package-2 npm run my-script",
]
`;
66 changes: 45 additions & 21 deletions commands/run/__tests__/run-command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ const normalizeRelativeDir = require("@lerna-test/normalize-relative-dir");
const lernaRun = require("@lerna-test/command-runner")(require("../command"));

// assertion helpers
const ranInPackages = testDir =>
npmRunScript.mock.calls.reduce((arr, [script, { args, npmClient, pkg }]) => {
const dir = normalizeRelativeDir(testDir, pkg.location);
const record = [dir, npmClient, "run", script].concat(args);
arr.push(record.join(" "));
return arr;
}, []);

const ranInPackagesStreaming = testDir =>
npmRunScript.stream.mock.calls.reduce((arr, [script, { args, npmClient, pkg }]) => {
const dir = normalizeRelativeDir(testDir, pkg.location);
Expand All @@ -38,17 +30,18 @@ const ranInPackagesStreaming = testDir =>
}, []);

describe("RunCommand", () => {
npmRunScript.mockResolvedValue({ stdout: "stdout" });
npmRunScript.stream.mockResolvedValue();
npmRunScript.mockImplementation((script, { pkg }) => Promise.resolve({ stdout: pkg.name }));
npmRunScript.stream.mockImplementation(() => Promise.resolve());

describe("in a basic repo", () => {
it("runs a script in packages", async () => {
const testDir = await initFixture("basic");

await lernaRun(testDir)("my-script");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput()).toMatch("stdout\nstdout");
const output = consoleOutput().split("\n");
expect(output).toContain("package-1");
expect(output).toContain("package-3");
});

it("runs a script in packages with --stream", async () => {
Expand All @@ -64,23 +57,23 @@ describe("RunCommand", () => {

await lernaRun(testDir)("env");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput().split("\n")).toEqual(["package-1", "package-4", "package-2", "package-3"]);
});

it("runs a script only in scoped packages", async () => {
const testDir = await initFixture("basic");

await lernaRun(testDir)("my-script", "--scope", "package-1");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput()).toBe("package-1");
});

it("does not run a script in ignored packages", async () => {
const testDir = await initFixture("basic");

await lernaRun(testDir)("my-script", "--ignore", "package-@(2|3|4)");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput()).toBe("package-1");
});

it("should filter packages that are not updated with --since", async () => {
Expand All @@ -103,7 +96,7 @@ describe("RunCommand", () => {

await lernaRun(testDir)("my-script", "--since", "master");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput()).toBe("package-3");
});

it("requires a git repo when using --since", async () => {
Expand All @@ -125,7 +118,6 @@ describe("RunCommand", () => {

await lernaRun(testDir)("missing-script");

expect(npmRunScript).not.toBeCalled();
expect(consoleOutput()).toBe("");
});

Expand All @@ -142,16 +134,39 @@ describe("RunCommand", () => {

await lernaRun(testDir)("env", "--npm-client", "yarn");

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput().split("\n")).toEqual(["package-1", "package-4", "package-2", "package-3"]);
});

it("reports script errors with early exit", async () => {
expect.assertions(2);
npmRunScript.mockImplementationOnce((script, { pkg }) => Promise.reject(new Error(pkg.name)));

const testDir = await initFixture("basic");

try {
await lernaRun(testDir)("fail");
} catch (err) {
expect(err.message).toMatch("package-1");
expect(err.message).not.toMatch("package-2");
}
});
});

describe("with --include-filtered-dependencies", () => {
it("runs scoped command including filtered deps", async () => {
const testDir = await initFixture("include-filtered-dependencies");
await lernaRun(testDir)("my-script", "--scope", "@test/package-2", "--include-filtered-dependencies");
await lernaRun(testDir)(
"my-script",
"--scope",
"@test/package-2",
"--include-filtered-dependencies",
"--",
"--silent"
);

expect(ranInPackages(testDir)).toMatchSnapshot();
const output = consoleOutput().split("\n");
expect(output).toContain("@test/package-1");
expect(output).toContain("@test/package-2");
});
});

Expand All @@ -169,7 +184,16 @@ describe("RunCommand", () => {
"package-cycle-extraneous -> package-cycle-1 -> package-cycle-2 -> package-cycle-1"
);

expect(ranInPackages(testDir)).toMatchSnapshot();
expect(consoleOutput().split("\n")).toEqual([
"package-dag-1",
"package-standalone",
"package-dag-2a",
"package-dag-2b",
"package-dag-3",
"package-cycle-1",
"package-cycle-2",
"package-cycle-extraneous",
]);
});

it("should throw an error with --reject-cycles", async () => {
Expand Down
7 changes: 7 additions & 0 deletions commands/run/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ exports.builder = yargs => {
type: "string",
})
.options({
bail: {
group: "Command Options:",
describe: "Stop when the script fails in a package.\nPass --no-bail to continue despite failure.",
defaultDescription: "true",
type: "boolean",
default: undefined,
},
stream: {
group: "Command Options:",
describe: "Stream output with lines prefixed by package.",
Expand Down
22 changes: 12 additions & 10 deletions commands/run/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class RunCommand extends Command {

get defaultOptions() {
return Object.assign({}, super.defaultOptions, {
bail: true,
parallel: false,
stream: false,
});
Expand Down Expand Up @@ -77,6 +78,15 @@ class RunCommand extends Command {
});
}

getOpts(pkg) {
return {
args: this.args,
npmClient: this.npmClient,
reject: this.options.bail,
pkg,
};
}

runScriptInPackagesBatched() {
const runner = this.options.stream
? pkg => this.runScriptInPackageStreaming(pkg)
Expand All @@ -97,19 +107,11 @@ class RunCommand extends Command {
}

runScriptInPackageStreaming(pkg) {
return npmRunScript.stream(this.script, {
args: this.args,
npmClient: this.npmClient,
pkg,
});
return npmRunScript.stream(this.script, this.getOpts(pkg));
}

runScriptInPackageCapturing(pkg) {
return npmRunScript(this.script, {
args: this.args,
npmClient: this.npmClient,
pkg,
})
return npmRunScript(this.script, this.getOpts(pkg))
.then(result => {
output(result.stdout);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"package-3": "^1.0.0"
},
"scripts": {
"prefail": "echo package-1",
"fail": "exit 1",
"my-script": "echo package-1",
"test": "echo package-1"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"name": "package-3",
"version": "1.0.0",
"scripts": {
"prefail": "echo package-3",
"fail": "exit 1",
"my-script": "echo package-3",
"test": "echo package-3"
}
Expand Down
22 changes: 0 additions & 22 deletions integration/__snapshots__/lerna-run.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,27 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`lerna run my-script --parallel: stderr 1`] = `
lerna info version __TEST_VERSION__
lerna info run in 2 package(s): npm run my-script --silent
lerna success run Ran npm script 'my-script' in packages:
lerna success - package-1
lerna success - package-3
`;

exports[`lerna run my-script --scope: stderr 1`] = `
lerna info version __TEST_VERSION__
lerna info filter [ 'package-1' ]
lerna success run Ran npm script 'my-script' in packages:
lerna success - package-1
`;

exports[`lerna run test --ignore: stderr 1`] = `
lerna info version __TEST_VERSION__
lerna info filter [ '!package-@(1|2|3)' ]
lerna success run Ran npm script 'test' in packages:
lerna success - package-4
`;

exports[`lerna run test --parallel: stderr 1`] = `
lerna info version __TEST_VERSION__
lerna info run in 4 package(s): npm run test --silent
Expand Down

0 comments on commit 893fcc8

Please sign in to comment.