Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add new option for appending a build suffix to prereleases #3195

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Usage:
.option("debug", { describe: "Output debugging information", type: "boolean", group: "Options" })
.option("d", { alias: "dry-run", describe: "Skip publishing", type: "boolean", group: "Options" })
.option("h", { alias: "help", group: "Options" })
.option("prerelease-build-format", {describe: "Prerelease build number format", type: "string", group: "Options"})
.strict(false)
.exitProcess(false);

Expand Down
19 changes: 19 additions & 0 deletions docs/usage/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ The [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) format used by

**Note**: The `tagFormat` must contain the `version` variable exactly once and compile to a [valid Git reference](https://git-scm.com/docs/git-check-ref-format#_description).

### prereleaseBuildFormat

Type: `String`<br>
Default: `undefined`<br>
CLI arguments: `--prerelease-build-format`

The format used by **semantic-release** when appending prerelease build information after the auto increment prerelease number. If left unspecified, no build information will be appended, otherwise the parsed value of this formatter will be appended after a `+` in the resulting version, so there is no need to add one yourself. Using this option is useful if you want extra insight into which version of the project has been released, or if you need to avoid tag conflicts caused by more complex git workflows, like ones that utilize history rewrites. The build number is generated with [Lodash template](https://lodash.com/docs#template) and will be compiled with the following variables.

- `commit` The current commit hash. Can use `commit.substr(0,7)` to use the short hash.
- `build` The current CI build number. This is useful when you need atomically increasing build numbers.

**Examples**:

| Previous Version | Prerelease Build Format | Branch | Commit Sha | Result |
| ---------------------- | ----------------------- | ------- | ---------- | ----------------------- |
| `1.1.3` | `${commit}` | `alpha` | `1a2b3c4` | `1.2.3-alpha.1+1a2b3c4` |
| `1.2.3-alpha.1+abcdef` | `${commit}` | `alpha` | `4d5e6f7` | `1.2.3-alpha.2+4d5e6f7` |
| `1.1.3` | | `alpha` | `1a2b3c4` | `1.2.3-alpha.1` |

### plugins

Type: `Array`<br>
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ async function run(context, plugins) {
}

context.nextRelease = nextRelease;
context.prereleaseBuildFormat = options.prereleaseBuildFormat;
nextRelease.version = getNextVersion(context);
nextRelease.gitTag = makeTag(options.tagFormat, nextRelease.version);
nextRelease.name = nextRelease.gitTag;
Expand Down
20 changes: 16 additions & 4 deletions lib/get-next-version.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import semver from "semver";
import { template } from "lodash-es";
import { FIRST_RELEASE, FIRSTPRERELEASE } from "./definitions/constants.js";
import { getLatestVersion, highest, isSameChannel, tagsToVersions } from "./utils.js";

export default ({ branch, nextRelease: { type, channel }, lastRelease, logger }) => {
export default ({
branch,
envCi: {commit, build},
nextRelease: {type, channel},
lastRelease,
logger,
prereleaseBuildFormat
}) => {
let version;
if (lastRelease.version) {
const { major, minor, patch } = semver.parse(lastRelease.version);
Expand All @@ -24,12 +32,16 @@ export default ({ branch, nextRelease: { type, channel }, lastRelease, logger })
} else {
version = semver.inc(lastRelease.version, type);
}

logger.log("The next release version is %s", version);
} else {
version = branch.type === "prerelease" ? `${FIRST_RELEASE}-${branch.prerelease}.${FIRSTPRERELEASE}` : FIRST_RELEASE;
logger.log(`There is no previous release, the next release version is ${version}`);
logger.log("There is no previous release");
}

if (branch.type === "prerelease" && prereleaseBuildFormat) {
version += `+${template(prereleaseBuildFormat)({build, commit})}`;
}

logger.log('The next release version is %s', version);

return version;
};
75 changes: 75 additions & 0 deletions test/get-next-version.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ test("Increase version for patch release", (t) => {
t.is(
getNextVersion({
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
envCi: {},
nextRelease: { type: "patch" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -24,6 +25,7 @@ test("Increase version for minor release", (t) => {
t.is(
getNextVersion({
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
envCi: {},
nextRelease: { type: "minor" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -36,6 +38,7 @@ test("Increase version for major release", (t) => {
t.is(
getNextVersion({
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
envCi: {},
nextRelease: { type: "major" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -48,6 +51,7 @@ test("Return 1.0.0 if there is no previous release", (t) => {
t.is(
getNextVersion({
branch: { name: "master", type: "release", tags: [] },
envCi: {},
nextRelease: { type: "minor" },
lastRelease: {},
logger: t.context.logger,
Expand All @@ -65,6 +69,7 @@ test("Increase version for patch release on prerelease branch", (t) => {
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
envCi: {},
nextRelease: { type: "patch", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -83,6 +88,7 @@ test("Increase version for patch release on prerelease branch", (t) => {
{ gitTag: "v1.0.1-beta.1", version: "1.0.1-beta.1", channels: ["beta"] },
],
},
envCi: {},
nextRelease: { type: "patch", channel: "beta" },
lastRelease: { version: "1.0.1-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -98,6 +104,7 @@ test("Increase version for patch release on prerelease branch", (t) => {
prerelease: "alpha",
tags: [{ gitTag: "v1.0.1-beta.1", version: "1.0.1-beta.1", channels: ["beta"] }],
},
envCi: {},
nextRelease: { type: "patch", channel: "alpha" },
lastRelease: { version: "1.0.1-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -115,6 +122,7 @@ test("Increase version for minor release on prerelease branch", (t) => {
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
envCi: {},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -133,6 +141,7 @@ test("Increase version for minor release on prerelease branch", (t) => {
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: ["beta"] },
],
},
envCi: {},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "1.1.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -148,6 +157,7 @@ test("Increase version for minor release on prerelease branch", (t) => {
prerelease: "alpha",
tags: [{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: ["beta"] }],
},
envCi: {},
nextRelease: { type: "minor", channel: "alpha" },
lastRelease: { version: "1.1.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -165,6 +175,7 @@ test("Increase version for major release on prerelease branch", (t) => {
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
envCi: {},
nextRelease: { type: "major", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -183,6 +194,7 @@ test("Increase version for major release on prerelease branch", (t) => {
{ gitTag: "v2.0.0-beta.1", version: "2.0.0-beta.1", channels: ["beta"] },
],
},
envCi: {},
nextRelease: { type: "major", channel: "beta" },
lastRelease: { version: "2.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -198,6 +210,7 @@ test("Increase version for major release on prerelease branch", (t) => {
prerelease: "alpha",
tags: [{ gitTag: "v2.0.0-beta.1", version: "2.0.0-beta.1", channels: ["beta"] }],
},
envCi: {},
nextRelease: { type: "major", channel: "alpha" },
lastRelease: { version: "2.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -210,6 +223,7 @@ test("Return 1.0.0 if there is no previous release on prerelease branch", (t) =>
t.is(
getNextVersion({
branch: { name: "beta", type: "prerelease", prerelease: "beta", tags: [] },
envCi: {},
nextRelease: { type: "minor" },
lastRelease: {},
logger: t.context.logger,
Expand All @@ -231,6 +245,7 @@ test("Increase version for release on prerelease branch after previous commits w
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: [null, "beta"] },
],
},
envCi: {},
nextRelease: { type: "minor" },
lastRelease: { version: "1.1.0", channels: [null] },
logger: t.context.logger,
Expand All @@ -251,6 +266,7 @@ test("Increase version for release on prerelease branch based on highest commit
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: [null, "beta"] },
],
},
envCi: {},
nextRelease: { type: "major" },
lastRelease: { version: "v1.1.0-beta.1", channels: [null] },
logger: t.context.logger,
Expand All @@ -268,6 +284,7 @@ test("Increase version for release on prerelease branch when there is no regular
prerelease: "beta",
tags: [{ gitTag: "v1.0.0-beta.1", version: "1.0.0-beta.1", channels: ["beta"] }],
},
envCi: {},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "v1.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
Expand All @@ -289,10 +306,68 @@ test("Increase patch when previous version shares HEAD with other releases", (t)
{ gitTag: "v1.0.0-alpha.1", version: "1.0.0-alpha.1", channels: ["alpha", "beta"] },
],
},
envCi: {},
nextRelease: { type: "patch", channel: "alpha" },
lastRelease: { version: "v1.0.0-alpha.1", channels: ["alpha", "beta"] },
logger: t.context.logger,
}),
"1.0.0-alpha.2"
);
});

test("Append commit build number to prerelease version", (t) => {
t.is(
getNextVersion({
branch: {
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{gitTag: "v1.0.0", version: "1.0.0", channels: [null]}],
},
envCi: {commit: "1a2b3c4", build: "1234"},
nextRelease: {type: "minor"},
lastRelease: {version: "1.0.0", channels: [null]},
logger: t.context.logger,
prereleaseBuildFormat: `\${commit}`,
}),
"1.1.0-beta.1+1a2b3c4"
);
});

test("Append CI build number to prerelease version", (t) => {
t.is(
getNextVersion({
branch: {
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{gitTag: "v1.0.0", version: "1.0.0", channels: [null]}],
},
envCi: {commit: "1a2b3c4", build: "1234"},
nextRelease: {type: "minor"},
lastRelease: {version: "1.0.0", channels: [null]},
logger: t.context.logger,
prereleaseBuildFormat: `\${build}`,
}),
"1.1.0-beta.1+1234"
);
});

test("Append new commit build number to next prerelease version", (t) => {
t.is(
getNextVersion({
branch: {
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{gitTag: "v1.1.0-beta.1+1a2b3c4", version: "1.1.0-beta.1+1a2b3c4", channels: ["beta"]}],
},
envCi: {commit: "4d5e6f7", build: "1234"},
nextRelease: {type: "minor", channel: "beta"},
lastRelease: {version: "v1.1.0-beta.1+1a2b3c4", channels: ["beta"]},
logger: t.context.logger,
prereleaseBuildFormat: `\${commit}`,
}),
"1.1.0-beta.2+4d5e6f7"
);
});
3 changes: 2 additions & 1 deletion test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ test("Dry-run", async (t) => {
await gitCommits(["feat: Initial commit"], { cwd });
t.log("$ semantic-release -d");
const { stdout, exitCode } = await execa(cli, ["-d"], { env, cwd, extendEnv: false });
t.regex(stdout, new RegExp(`There is no previous release, the next release version is ${version}`));
t.regex(stdout, /There is no previous release/);
t.regex(stdout, new RegExp(`The next release version is ${version}`));
t.regex(stdout, new RegExp(`Release note for version ${version}`));
t.regex(stdout, /Initial commit/);
t.is(exitCode, 0);
Expand Down