Repository: intuit/auto (ts)

Issue:
Use lerna version commit message from lerna config if specified
I would like to specify a custom commit message for `lerna version` in my `lerna.json` file as described [here](https://github.com/lerna/lerna/tree/main/commands/version#--message-msg) and have auto use that instead of always using its own.

The `npm` plugin could either expose a config option for this, which would have the added benefit of also enabling this functionality for non-lerna repos, or auto could just read the custom message from `lerna.json` and use it if there is one.

This is useful when using conventional commits, as it's somewhat jarring to see "Bump independent versions" while every other commit conforms to a convention.

Pull request:
feat(npm): use version commit message from lerna.json
# What Changed

Use the user defined `lerna version` commit message from `lerna.json` in a monorepo where possible.

Fixes #2276

## Why

As described in #2276 - lerna allows the `version` command's message to be customised, but `auto` does not currently respect that customisation.

Todo:

- [x] Add tests
- [ ] Add docs

Unsure if a docs change is warranted as this is functionality present in `lerna` that `auto` is using.

## Change Type

- [ ] `documentation`
- [ ] `patch`
- [x] `minor`
- [ ] `major`

This could possibly be considered a patch change instead of a minor, since not respecting lerna's config for this could be considered a bug.
<!-- GITHUB_RELEASE PR BODY: canary-assets -->
:baby_chick: Download canary assets:

[auto-linux--canary.2277.26629.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-linux--canary.2277.26629.gz)  
[auto-macos--canary.2277.26629.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-macos--canary.2277.26629.gz)  
[auto-win.exe--canary.2277.26629.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-win.exe--canary.2277.26629.gz)
<!-- GITHUB_RELEASE PR BODY: canary-assets -->

<!-- GITHUB_RELEASE PR BODY: canary-version -->
<details>
  <summary>📦 Published PR as canary version: <code>under canary scope @auto-canary@10.38.0--canary.2277.26629.0</code></summary>
  <br />

  :sparkles: Test out this PR locally via:
  
  ```bash
  npm install @auto-canary/bot-list@10.38.0--canary.2277.26629.0
  npm install @auto-canary/auto@10.38.0--canary.2277.26629.0
  npm install @auto-canary/core@10.38.0--canary.2277.26629.0
  npm install @auto-canary/package-json-utils@10.38.0--canary.2277.26629.0
  npm install @auto-canary/all-contributors@10.38.0--canary.2277.26629.0
  npm install @auto-canary/brew@10.38.0--canary.2277.26629.0
  npm install @auto-canary/chrome@10.38.0--canary.2277.26629.0
  npm install @auto-canary/cocoapods@10.38.0--canary.2277.26629.0
  npm install @auto-canary/conventional-commits@10.38.0--canary.2277.26629.0
  npm install @auto-canary/crates@10.38.0--canary.2277.26629.0
  npm install @auto-canary/docker@10.38.0--canary.2277.26629.0
  npm install @auto-canary/exec@10.38.0--canary.2277.26629.0
  npm install @auto-canary/first-time-contributor@10.38.0--canary.2277.26629.0
  npm install @auto-canary/gem@10.38.0--canary.2277.26629.0
  npm install @auto-canary/gh-pages@10.38.0--canary.2277.26629.0
  npm install @auto-canary/git-tag@10.38.0--canary.2277.26629.0
  npm install @auto-canary/gradle@10.38.0--canary.2277.26629.0
  npm install @auto-canary/jira@10.38.0--canary.2277.26629.0
  npm install @auto-canary/magic-zero@10.38.0--canary.2277.26629.0
  npm install @auto-canary/maven@10.38.0--canary.2277.26629.0
  npm install @auto-canary/microsoft-teams@10.38.0--canary.2277.26629.0
  npm install @auto-canary/npm@10.38.0--canary.2277.26629.0
  npm install @auto-canary/omit-commits@10.38.0--canary.2277.26629.0
  npm install @auto-canary/omit-release-notes@10.38.0--canary.2277.26629.0
  npm install @auto-canary/pr-body-labels@10.38.0--canary.2277.26629.0
  npm install @auto-canary/released@10.38.0--canary.2277.26629.0
  npm install @auto-canary/s3@10.38.0--canary.2277.26629.0
  npm install @auto-canary/sbt@10.38.0--canary.2277.26629.0
  npm install @auto-canary/slack@10.38.0--canary.2277.26629.0
  npm install @auto-canary/twitter@10.38.0--canary.2277.26629.0
  npm install @auto-canary/upload-assets@10.38.0--canary.2277.26629.0
  npm install @auto-canary/version-file@10.38.0--canary.2277.26629.0
  npm install @auto-canary/vscode@10.38.0--canary.2277.26629.0
  # or 
  yarn add @auto-canary/bot-list@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/auto@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/core@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/package-json-utils@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/all-contributors@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/brew@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/chrome@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/cocoapods@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/conventional-commits@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/crates@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/docker@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/exec@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/first-time-contributor@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/gem@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/gh-pages@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/git-tag@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/gradle@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/jira@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/magic-zero@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/maven@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/microsoft-teams@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/npm@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/omit-commits@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/omit-release-notes@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/pr-body-labels@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/released@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/s3@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/sbt@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/slack@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/twitter@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/upload-assets@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/version-file@10.38.0--canary.2277.26629.0
  yarn add @auto-canary/vscode@10.38.0--canary.2277.26629.0
  ```
</details>
<!-- GITHUB_RELEASE PR BODY: canary-version -->


Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5bfc48d5..c53d1583 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,10 +1,6 @@
 name: build
 
-on:
-  push:
-    branches: [main, next]
-  pull_request:
-    types: [opened, synchronize, reopened]
+on: [push]
 
 # Enabled permissions on GITHUB_TOKEN
 permissions:
@@ -16,8 +12,6 @@ permissions:
   statuses: write
   # Needed to create PR statuses/checks
   checks: write
-  # To post comments on PRs
-  issues: write
 
 jobs:
   # Run install in one step so deps can be cached for other steps
diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts
index 5373ef07..ae6cff33 100644
--- a/packages/core/src/auto.ts
+++ b/packages/core/src/auto.ts
@@ -512,11 +512,11 @@ export default class Auto {
           );
         } catch (error) {
           // If we are behind or there is no match, exit and skip the release
-          this.logger.log.error(
+          this.logger.log.warn(
             "Current commit is behind, skipping the release to avoid collisions."
           );
-          this.logger.verbose.error(error);
-          process.exit(1);
+          this.logger.verbose.warn(error);
+          process.exit(0);
         }
       }
     );
diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts
index af23b08a..2208405f 100644
--- a/plugins/npm/src/index.ts
+++ b/plugins/npm/src/index.ts
@@ -958,7 +958,8 @@ export default class NPMPlugin implements IPlugin {
 
         if (isMonorepo()) {
           auto.logger.verbose.info("Detected monorepo, using lerna");
-          const monorepoVersion = getLernaJson().version;
+          const lernaJson = getLernaJson();
+          const monorepoVersion = lernaJson.version;
           const isIndependent = monorepoVersion === "independent";
 
           if (dryRun) {
@@ -995,6 +996,20 @@ export default class NPMPlugin implements IPlugin {
               ? useVersion || bump
               : useVersion || (await bumpLatest(getMonorepoPackage(), bump)) || bump;
 
+          let commitMessage = isIndependent
+            ? "Bump independent versions [skip ci]"
+            : "Bump version to: %s [skip ci]";
+
+          const customCommitMessage = lernaJson.command?.version?.message;
+
+          if (typeof customCommitMessage === "string") {
+            commitMessage = customCommitMessage.trim();
+
+            if (customCommitMessage.indexOf("[skip ci]") === -1) {
+              commitMessage += " [skip ci]";
+            }
+          }
+
           await execPromise("npx", [
             "lerna",
             "version",
@@ -1004,9 +1019,7 @@ export default class NPMPlugin implements IPlugin {
             "--yes",
             "--no-push",
             "-m",
-            isIndependent
-              ? `'"Bump independent versions [skip ci]"'`
-              : `'"Bump version to: %s [skip ci]"'`,
+            `'"${commitMessage}"'`,
             this.exact && "--exact",
             ...verboseArgs,
           ]);


Test patch:
diff --git a/plugins/npm/__tests__/npm.test.ts b/plugins/npm/__tests__/npm.test.ts
index c8e58de5..266417a7 100644
--- a/plugins/npm/__tests__/npm.test.ts
+++ b/plugins/npm/__tests__/npm.test.ts
@@ -880,6 +880,92 @@ describe("publish", () => {
     ]);
   });
 
+  test("monorepo - should use commit message from lerna.json", async () => {
+    mockFs({
+      "lerna.json": `
+        {
+          "command": {
+            "version": {
+              "message": "[skip ci] Custom version commit message"
+            }
+          }
+        }
+      `,
+      ...monorepoPackagesOnFs,
+    });
+
+    const plugin = new NPMPlugin();
+    const hooks = makeHooks();
+
+    plugin.apply({
+      config: { prereleaseBranches: ["next"] },
+      hooks,
+      remote: "origin",
+      baseBranch: "main",
+      logger: dummyLog(),
+    } as Auto.Auto);
+
+    monorepoPackages.mockReturnValueOnce(monorepoPackagesResult);
+    execPromise.mockReturnValueOnce("1.0.0");
+
+    await hooks.version.promise({ bump: Auto.SEMVER.patch });
+    expect(execPromise).toHaveBeenNthCalledWith(2, "npx", [
+      "lerna",
+      "version",
+      "1.0.1",
+      "--force-publish",
+      "--no-commit-hooks",
+      "--yes",
+      "--no-push",
+      "-m",
+      "'\"[skip ci] Custom version commit message\"'",
+      false,
+    ]);
+  });
+
+  test("monorepo - should ensure commit message from lerna.json contains [skip ci]", async () => {
+    mockFs({
+      "lerna.json": `
+        {
+          "command": {
+            "version": {
+              "message": "Custom version commit message"
+            }
+          }
+        }
+      `,
+      ...monorepoPackagesOnFs,
+    });
+
+    const plugin = new NPMPlugin();
+    const hooks = makeHooks();
+
+    plugin.apply({
+      config: { prereleaseBranches: ["next"] },
+      hooks,
+      remote: "origin",
+      baseBranch: "main",
+      logger: dummyLog(),
+    } as Auto.Auto);
+
+    monorepoPackages.mockReturnValueOnce(monorepoPackagesResult);
+    execPromise.mockReturnValueOnce("1.0.0");
+
+    await hooks.version.promise({ bump: Auto.SEMVER.patch });
+    expect(execPromise).toHaveBeenNthCalledWith(2, "npx", [
+      "lerna",
+      "version",
+      "1.0.1",
+      "--force-publish",
+      "--no-commit-hooks",
+      "--yes",
+      "--no-push",
+      "-m",
+      "'\"Custom version commit message [skip ci]\"'",
+      false,
+    ]);
+  });
+
   test("should publish private scoped packages to private", async () => {
     const plugin = new NPMPlugin();
     const hooks = makeHooks();