From 6eac92fe5a899895a530360724723f307cf349f3 Mon Sep 17 00:00:00 2001 From: Michael Iwersen Date: Fri, 23 Dec 2022 14:15:14 +0100 Subject: [PATCH] feat(version): support custom command for git tag (#2760) --- commands/version/README.md | 21 +++++++++++++++++++++ commands/version/__tests__/git-tag.test.js | 9 +++++++++ commands/version/command.js | 5 +++++ commands/version/index.js | 6 ++++-- commands/version/lib/git-tag.js | 16 +++++++++------- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/commands/version/README.md b/commands/version/README.md index 9800481996..2325e3b109 100644 --- a/commands/version/README.md +++ b/commands/version/README.md @@ -59,6 +59,7 @@ Running `lerna version --conventional-commits` without the above flags will rele - [`--create-release `](#--create-release-type) - [`--exact`](#--exact) - [`--force-publish`](#--force-publish) + - [`--git-tag-command `](#--git-tag-command-cmd) - [`--git-remote `](#--git-remote-name) - [`--ignore-changes`](#--ignore-changes) - [`--ignore-scripts`](#--ignore-scripts) @@ -264,6 +265,26 @@ When run with this flag, `lerna version` will force publish the specified packag > This will skip the `lerna changed` check for changed packages and forces a package that didn't have a `git diff` change to be updated. +### `--git-tag-command ` + +Allows users to specify a custom command to be used when applying git tags. For example, this may be useful for providing a wrapper command in CI/CD pipelines that have no direct write access. + +```sh +lerna version --git-tag-command "git gh-tag %s -m %s" +``` + +This can also be configured in `lerna.json`. + +```json +{ + "command": { + "version": { + "gitTagCommand": "git gh-tag %s -m %s" + } + } +} +``` + ### `--git-remote ` ```sh diff --git a/commands/version/__tests__/git-tag.test.js b/commands/version/__tests__/git-tag.test.js index ea1474fe92..94a43f8fd2 100644 --- a/commands/version/__tests__/git-tag.test.js +++ b/commands/version/__tests__/git-tag.test.js @@ -34,4 +34,13 @@ describe("gitTag", () => { expect(childProcess.exec).toHaveBeenLastCalledWith("git", ["tag", tag, "-m", tag, "--force"], opts); }); + + it("creates an annotated git tag using the wrapper arguments", async () => { + const tag = "v1.2.4"; + const opts = { cwd: "default" }; + + await gitTag(tag, {}, opts, "git-wrapper gh-tag %s -m %s"); + + expect(childProcess.exec).toHaveBeenLastCalledWith("git-wrapper", ["gh-tag", tag, "-m", tag], opts); + }); }); diff --git a/commands/version/command.js b/commands/version/command.js index f840931b93..fc171d68fc 100644 --- a/commands/version/command.js +++ b/commands/version/command.js @@ -168,6 +168,11 @@ exports.builder = (yargs, composed) => { requiresArg: true, defaultDescription: "v", }, + "git-tag-command": { + describe: + "Allows users to specify a custom command to be used when applying git tags. For example, this may be useful for providing a wrapper command in CI/CD pipelines that have no direct write access.", + type: "string", + }, "npm-client-args": { describe: "Additional arguments to pass to the npm client when performing 'npm install'.", type: "array", diff --git a/commands/version/index.js b/commands/version/index.js index b9abcbc1cd..6ae6295020 100644 --- a/commands/version/index.js +++ b/commands/version/index.js @@ -694,7 +694,9 @@ class VersionCommand extends Command { return Promise.resolve() .then(() => gitCommit(message, this.gitOpts, this.execOpts)) - .then(() => Promise.all(tags.map((tag) => gitTag(tag, this.gitOpts, this.execOpts)))) + .then(() => + Promise.all(tags.map((tag) => gitTag(tag, this.gitOpts, this.execOpts, this.options.gitTagCommand))) + ) .then(() => tags); } @@ -707,7 +709,7 @@ class VersionCommand extends Command { return Promise.resolve() .then(() => gitCommit(message, this.gitOpts, this.execOpts)) - .then(() => gitTag(tag, this.gitOpts, this.execOpts)) + .then(() => gitTag(tag, this.gitOpts, this.execOpts, this.options.gitTagCommand)) .then(() => [tag]); } diff --git a/commands/version/lib/git-tag.js b/commands/version/lib/git-tag.js index 6686c686b8..e84d7ba692 100644 --- a/commands/version/lib/git-tag.js +++ b/commands/version/lib/git-tag.js @@ -10,19 +10,21 @@ module.exports.gitTag = gitTag; * @param {{ forceGitTag: boolean; signGitTag: boolean; }} gitOpts * @param {import("@lerna/child-process").ExecOpts} opts */ -function gitTag(tag, { forceGitTag, signGitTag }, opts) { - log.silly("gitTag", tag); +function gitTag(tag, { forceGitTag, signGitTag }, opts, command = "git tag %s -m %s") { + log.silly("gitTag", tag, command); - const args = ["tag", tag, "-m", tag]; + const [cmd, ...args] = command.split(" "); + + const interpolatedArgs = args.map((arg) => arg.replace(/%s/, tag)); if (forceGitTag) { - args.push("--force"); + interpolatedArgs.push("--force"); } if (signGitTag) { - args.push("--sign"); + interpolatedArgs.push("--sign"); } - log.verbose("git", args); - return childProcess.exec("git", args, opts); + log.verbose(cmd, interpolatedArgs); + return childProcess.exec(cmd, interpolatedArgs, opts); }