Skip to content

Commit

Permalink
feat(conventional-commits): Add conventional prerelease/graduation (#…
Browse files Browse the repository at this point in the history
…1991)

Fixes #1433
Fixes #1675
  • Loading branch information
Shawn Erquhart authored and evocateur committed May 11, 2019
1 parent e32da08 commit 5d84b61
Show file tree
Hide file tree
Showing 46 changed files with 1,797 additions and 156 deletions.
3 changes: 3 additions & 0 deletions __fixtures__/prerelease-independent/lerna.json
@@ -0,0 +1,3 @@
{
"version": "independent"
}
3 changes: 3 additions & 0 deletions __fixtures__/prerelease-independent/package.json
@@ -0,0 +1,3 @@
{
"name": "independent"
}
@@ -0,0 +1,4 @@
{
"name": "package-1",
"version": "1.0.0-alpha.0"
}
@@ -0,0 +1,7 @@
{
"name": "package-2",
"version": "2.0.0-alpha.0",
"dependencies": {
"package-1": "^1.0.0-alpha.0"
}
}
@@ -0,0 +1,7 @@
{
"name": "package-3",
"version": "3.0.0-beta.3",
"devDependencies": {
"package-2": "^2.0.0-alpha.0"
}
}
@@ -0,0 +1,7 @@
{
"name": "package-4",
"version": "4.0.0",
"dependencies": {
"package-1": "^0.0.0"
}
}
@@ -0,0 +1,8 @@
{
"name": "package-5",
"dependencies": {
"package-3": "^3.0.0-beta.3"
},
"private": true,
"version": "5.0.0-alpha.0"
}
3 changes: 3 additions & 0 deletions __fixtures__/prerelease/lerna.json
@@ -0,0 +1,3 @@
{
"version": "1.0.0-alpha.0"
}
3 changes: 3 additions & 0 deletions __fixtures__/prerelease/package.json
@@ -0,0 +1,3 @@
{
"name": "normal"
}
4 changes: 4 additions & 0 deletions __fixtures__/prerelease/packages/package-1/package.json
@@ -0,0 +1,4 @@
{
"name": "package-1",
"version": "1.0.0-alpha.0"
}
7 changes: 7 additions & 0 deletions __fixtures__/prerelease/packages/package-2/package.json
@@ -0,0 +1,7 @@
{
"name": "package-2",
"version": "1.0.0-alpha.0",
"dependencies": {
"package-1": "^1.0.0-alpha.0"
}
}
10 changes: 10 additions & 0 deletions __fixtures__/prerelease/packages/package-3/package.json
@@ -0,0 +1,10 @@
{
"name": "package-3",
"version": "1.0.0-alpha.0",
"peerDependencies": {
"package-2": "^1.0.0-alpha.0"
},
"devDependencies": {
"package-2": "^1.0.0-alpha.0"
}
}
7 changes: 7 additions & 0 deletions __fixtures__/prerelease/packages/package-4/package.json
@@ -0,0 +1,7 @@
{
"name": "package-4",
"version": "1.0.0-alpha.0",
"dependencies": {
"package-1": "^0.0.0"
}
}
11 changes: 11 additions & 0 deletions __fixtures__/prerelease/packages/package-5/package.json
@@ -0,0 +1,11 @@
{
"name": "package-5",
"dependencies": {
"package-1": "^1.0.0-alpha.0"
},
"optionalDependencies": {
"package-3": "^1.0.0-alpha.0"
},
"private": true,
"version": "1.0.0-alpha.0"
}
4 changes: 4 additions & 0 deletions commands/__mocks__/@lerna/collect-updates.js
@@ -1,5 +1,7 @@
"use strict";

const { collectPackages, getPackagesForOption } = jest.requireActual("@lerna/collect-updates");

// collectUpdates.setUpdated(cwd, packageNames...)
// otherwise, enables everything
const updated = new Map();
Expand All @@ -20,3 +22,5 @@ afterEach(() => {

module.exports = mockCollectUpdates;
module.exports.setUpdated = setUpdated;
module.exports.collectPackages = collectPackages;
module.exports.getPackagesForOption = getPackagesForOption;
9 changes: 9 additions & 0 deletions commands/publish/README.md
Expand Up @@ -52,6 +52,7 @@ This is useful when a previous `lerna publish` failed to publish all packages to
- [`--no-git-reset`](#--no-git-reset)
- [`--no-verify-access`](#--no-verify-access)
- [`--preid`](#--preid)
- [`--pre-dist-tag <tag>`](#--pre-dist-tag-tag)
- [`--registry <url>`](#--registry-url)
- [`--temp-tag`](#--temp-tag)
- [`--ignore-scripts`](#--ignore-scripts)
Expand Down Expand Up @@ -157,6 +158,14 @@ lerna publish --canary --preid next
When run with this flag, `lerna publish --canary` will increment `premajor`, `preminor`, `prepatch`, or `prerelease` semver
bumps using the specified [prerelease identifier](http://semver.org/#spec-item-9).

### `--pre-dist-tag <tag>`

```sh
lerna publish --pre-dist-tag next
```

Works the same as [`--dist-tag`](#--dist-tag-tag), except only applies to packages being released with a prerelease version.

### `--registry <url>`

When run with this flag, forwarded npm commands will use the specified registry for your package(s).
Expand Down
62 changes: 62 additions & 0 deletions commands/publish/__tests__/publish-tagging.test.js
Expand Up @@ -96,3 +96,65 @@ Map {
expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-1@1.0.1", "beta", conf); // <--
expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-2@1.0.1", "beta", conf);
});

test("publish prerelease --pre-dist-tag beta", async () => {
const cwd = await initFixture("normal");

collectUpdates.setUpdated(cwd, "package-1");

await lernaPublish(cwd)("prerelease", "--pre-dist-tag", "beta");

expect(npmPublish.registry.get("package-1")).toBe("beta");
expect(npmDistTag.remove).not.toHaveBeenCalled();
});

test("publish non-prerelease --pre-dist-tag beta", async () => {
const cwd = await initFixture("normal");

collectUpdates.setUpdated(cwd, "package-1");

await lernaPublish(cwd)("--pre-dist-tag", "beta");

expect(npmPublish.registry.get("package-1")).toBe("latest");
expect(npmDistTag.remove).not.toHaveBeenCalled();
});

test("publish non-prerelease --dist-tag next --pre-dist-tag beta", async () => {
const cwd = await initFixture("normal");

collectUpdates.setUpdated(cwd, "package-1");

await lernaPublish(cwd)("--dist-tag", "next", "--pre-dist-tag", "beta");

expect(npmPublish.registry.get("package-1")).toBe("next");
expect(npmDistTag.remove).not.toHaveBeenCalled();
});

test("publish --pre-dist-tag beta --temp-tag", async () => {
const cwd = await initFixture("integration");

await lernaPublish(cwd)(
"prerelease",
"--dist-tag",
"next",
"--preid",
"beta",
"--pre-dist-tag",
"beta",
"--temp-tag"
);

expect(npmPublish.registry).toMatchInlineSnapshot(`
Map {
"@integration/package-1" => "lerna-temp",
"@integration/package-2" => "lerna-temp",
}
`);

const conf = expect.objectContaining({
tag: "next",
});

expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-1@1.0.1-beta.0", "beta", conf);
expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-2@1.0.1-beta.0", "beta", conf);
});
24 changes: 20 additions & 4 deletions commands/publish/index.js
Expand Up @@ -26,6 +26,7 @@ const batchPackages = require("@lerna/batch-packages");
const runParallelBatches = require("@lerna/run-parallel-batches");
const pulseTillDone = require("@lerna/pulse-till-done");
const versionCommand = require("@lerna/version");
const prereleaseIdFromVersion = require("@lerna/prerelease-id-from-version");

const createTempLicenses = require("./lib/create-temp-licenses");
const getCurrentSHA = require("./lib/get-current-sha");
Expand Down Expand Up @@ -642,15 +643,19 @@ class PublishCommand extends Command {

const mapper = pPipe(
[
pkg =>
pulseTillDone(npmPublish(pkg, pkg.packed.tarFilePath, opts)).then(() => {
pkg => {
const preDistTag = this.getPreDistTag(pkg);
const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag;
const pkgOpts = Object.assign({}, opts, { tag });
return pulseTillDone(npmPublish(pkg, pkg.packed.tarFilePath, pkgOpts)).then(() => {
tracker.success("published", pkg.name, pkg.version);
tracker.completeWork(1);

logPacked(pkg.packed);

return pkg;
}),
});
},

this.options.requireScripts && (pkg => this.execScript(pkg, "postpublish")),
].filter(Boolean)
Expand Down Expand Up @@ -685,7 +690,8 @@ class PublishCommand extends Command {
};
const mapper = pkg => {
const spec = `${pkg.name}@${pkg.version}`;
const distTag = getDistTag(pkg.get("publishConfig"));
const preDistTag = this.getPreDistTag(pkg);
const distTag = preDistTag || getDistTag(pkg.get("publishConfig"));

return Promise.resolve()
.then(() => pulseTillDone(npmDistTag.remove(spec, "lerna-temp", opts)))
Expand Down Expand Up @@ -714,6 +720,16 @@ class PublishCommand extends Command {

// undefined defaults to "latest" OR whatever is in pkg.publishConfig.tag
}

getPreDistTag(pkg) {
if (!this.options.preDistTag) {
return;
}
const isPrerelease = prereleaseIdFromVersion(pkg.version);
if (isPrerelease) {
return this.options.preDistTag;
}
}
}

module.exports.PublishCommand = PublishCommand;
1 change: 1 addition & 0 deletions commands/publish/package.json
Expand Up @@ -46,6 +46,7 @@
"@lerna/npm-publish": "file:../../utils/npm-publish",
"@lerna/output": "file:../../utils/output",
"@lerna/pack-directory": "file:../../utils/pack-directory",
"@lerna/prerelease-id-from-version": "file:../../utils/prerelease-id-from-version",
"@lerna/prompt": "file:../../core/prompt",
"@lerna/pulse-till-done": "file:../../utils/pulse-till-done",
"@lerna/run-lifecycle": "file:../../utils/run-lifecycle",
Expand Down
35 changes: 34 additions & 1 deletion commands/version/README.md
Expand Up @@ -30,15 +30,23 @@ lerna version [major | minor | patch | premajor | preminor | prepatch | prerelea
When this positional parameter is passed, `lerna version` will skip the version selection prompt and [increment](https://github.com/npm/node-semver#functions) the version by that keyword.
You must still use the `--yes` flag to avoid all prompts.

#### "Graduating" prereleases
## Prerelease

If you have any packages with a prerelease version number (e.g. `2.0.0-beta.3`) and you run `lerna version` with and a non-prerelease bump (`major`, `minor`, or `patch`), it will publish those previously pre-released packages _as well as_ the packages that have changed since the last release.

For projects using conventional commits, use the following flags for prerelease management:
**[`--conventional-prerelease`](#--conventional-prerelease):** release current changes as prerelease versions.
**[`--conventional-graduate`](#--conventional-graduate):** graduate prerelease versioned packages to stable versions.

Running `lerna version --conventional-commits` without the above flags will release current changes as prerelease only if the version is already in prerelease.

## Options

- [`--allow-branch`](#--allow-branch-glob)
- [`--amend`](#--amend)
- [`--conventional-commits`](#--conventional-commits)
- [`--conventional-graduate`](#--conventional-graduate)
- [`--conventional-prerelease`](#--conventional-prerelease)
- [`--changelog-preset`](#--changelog-preset)
- [`--exact`](#--exact)
- [`--force-publish`](#--force-publish)
Expand Down Expand Up @@ -117,6 +125,31 @@ When run with this flag, `lerna version` will use the [Conventional Commits Spec

Passing [`--no-changelog`](#--no-changelog) will disable the generation (or updating) of `CHANGELOG.md` files.

### `--conventional-graduate`

```sh
lerna version --conventional-commits --conventional-graduate=package-2,package-4

# force all prerelease packages to be graduated
lerna version --conventional-commits --conventional-graduate
```
When run with this flag, `lerna version` will graduate the specified packages (comma-separated) or all packages using `*`. This command works regardless of whether the current HEAD has been released, similar to `--force-publish`, except that any non-prerelease packages are ignored. If changes are present for packages that are not specified (if specifying packages), or for packages that are not in prerelease, those packages will be versioned as they normally would using `--conventional-commits`.

"Graduating" a package means bumping to the non-prerelease variant of a prerelease version, eg. `package-1@1.0.0-alpha.0 => package-1@1.0.0`.

> NOTE: when specifying packages, dependents of specified packages will be released, but will not be graduated.
### `--conventional-prerelease`

```sh
lerna version --conventional-commits --conventional-prerelease=package-2,package-4

# force all prerelease packages to be graduated
lerna version --conventional-commits --conventional-graduate
```

When run with this flag, `lerna version` will release with prerelease versions the specified packages (comma-separated) or all packages using `*`. Releases all unreleased changes as pre(patch/minor/major/release) by prefixing the version recommendation from `conventional-commits` with `pre`, eg. if present changes include a feature commit, the recommended bump will be `minor`, so this flag will result in a `preminor` release. If changes are present for packages that are not specified (if specifying packages), or for packages that are already in prerelease, those packages will be versioned as they normally would using `--conventional-commits`.

### `--changelog-preset`

```sh
Expand Down

0 comments on commit 5d84b61

Please sign in to comment.