Skip to content

Commit ae87669

Browse files
padraig-meaneyevocateur
authored andcommitted
fix(publish): Add --graph-type option to control packages included in topological sort (#2152)
Allow for configuration of a specific `graphType` so that users can opt-in to using `devDependencies` when building a package graph to determine a topological sort. Closes #1437
1 parent b335763 commit ae87669

File tree

4 files changed

+62
-4
lines changed

4 files changed

+62
-4
lines changed

commands/publish/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ This is useful when a previous `lerna publish` failed to publish all packages to
4949
- [`--contents <dir>`](#--contents-dir)
5050
- [`--dist-tag <tag>`](#--dist-tag-tag)
5151
- [`--git-head <sha>`](#--git-head-sha)
52+
- [`--graph-type <all|dependencies>`](#--graph-type-alldependencies)
5253
- [`--no-git-reset`](#--no-git-reset)
5354
- [`--no-verify-access`](#--no-verify-access)
5455
- [`--otp`](#--otp)
@@ -127,6 +128,28 @@ lerna publish from-package --git-head ${CODEBUILD_RESOLVED_SOURCE_VERSION}
127128

128129
Under all other circumstances, this value is derived from a local `git` command.
129130

131+
### `--graph-type <all|dependencies>`
132+
133+
Set which kind of dependencies to use when building a package graph. The default value is `dependencies`, whereby only packages listed in the `dependencies` section of a package's `package.json` are included. Pass `all` to include both `dependencies` _and_ `devDependencies` when constructing the package graph and determining topological order.
134+
135+
When using traditional peer + dev dependency pairs, this option should be configured to `all` so the peers are always published before their dependents.
136+
137+
```sh
138+
lerna publish --graph-type all
139+
```
140+
141+
Configured via `lerna.json`:
142+
143+
```json
144+
{
145+
"command": {
146+
"publish": {
147+
"graphType": "all"
148+
}
149+
}
150+
}
151+
```
152+
130153
### `--no-git-reset`
131154

132155
By default, `lerna publish` ensures any changes to the working tree have been reset.

commands/publish/__tests__/publish-command.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,35 @@ Map {
178178
});
179179
});
180180

181+
describe("--graph-type", () => {
182+
it("produces a topological ordering that _includes_ devDependencies when value is 'all'", async () => {
183+
const cwd = await initFixture("normal");
184+
185+
await lernaPublish(cwd)("--graph-type", "all");
186+
187+
expect(npmPublish.order()).toEqual([
188+
"package-1",
189+
"package-4",
190+
"package-2",
191+
// package-3 has a peer/devDependency on package-2
192+
"package-3",
193+
// package-5 is private
194+
]);
195+
});
196+
197+
it("throws an error when value is _not_ 'all' or 'dependencies'", async () => {
198+
const testDir = await initFixture("normal");
199+
200+
try {
201+
await lernaPublish(testDir)("--graph-type", "poopy-pants");
202+
} catch (err) {
203+
expect(err.message).toMatch("poopy-pants");
204+
}
205+
206+
expect.hasAssertions();
207+
});
208+
});
209+
181210
describe("--otp", () => {
182211
otplease.getOneTimePassword.mockImplementation(() => Promise.resolve("654321"));
183212

commands/publish/command.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ exports.builder = yargs => {
4141
type: "string",
4242
requiresArg: true,
4343
},
44+
"graph-type": {
45+
describe: "Type of dependency to use when determining package hierarchy.",
46+
choices: ["all", "dependencies"],
47+
defaultDescription: "dependencies",
48+
},
4449
otp: {
4550
describe: "Supply a one-time password for publishing with two-factor authentication.",
4651
type: "string",

commands/publish/index.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -589,10 +589,11 @@ class PublishCommand extends Command {
589589
return runTopologically(this.packagesToPublish, mapper, {
590590
concurrency: this.concurrency,
591591
rejectCycles: this.options.rejectCycles,
592-
// Don't sort based on devDependencies because that
593-
// would increase the chance of dependency cycles
594-
// causing less-than-ideal a publishing order.
595-
graphType: "dependencies",
592+
// By default, do not include devDependencies in the graph because it would
593+
// increase the chance of dependency cycles, causing less-than-ideal order.
594+
// If the user has opted-in to --graph-type=all (or "graphType": "all" in lerna.json),
595+
// devDependencies _will_ be included in the graph construction.
596+
graphType: this.options.graphType === "all" ? "allDependencies" : "dependencies",
596597
});
597598
}
598599

0 commit comments

Comments
 (0)