Repository: intuit/auto
Pull request #2035 (2021-07-22 00:32:12)

feat(plugins/npm): exclude prelease versions when calculating monorepo project version
# What Changed

- Modified `getMonorepoPackage` to exclude all pre-release versions if there's at least 1 non pre-release version in the monorepo. 

## Why

- Including these releases can lead `canary` or `next` releases to increment the project `base` version for a whole project, since the newly created packages will have `canary` / `next` assigned to the `@latest` tag on NPM.

Todo:

- [x] Add tests
- [ ] Add docs

## Change Type

Indicate the type of change your pull request is:

- [ ] `documentation`
- [ ] `patch`
- [x] `minor`
- [ ] `major`

<!-- GITHUB_RELEASE PR BODY: canary-assets -->
:baby_chick: Download canary assets:

[auto-linux--canary.2035.24576.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-linux--canary.2035.24576.gz)  
[auto-macos--canary.2035.24576.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-macos--canary.2035.24576.gz)  
[auto-win.exe--canary.2035.24576.gz](https://github.com/intuit/auto/releases/download/v0.0.0-canary/auto-win.exe--canary.2035.24576.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.30.0--canary.2035.24576.0</code></summary>
  <br />
  
  :sparkles: Test out this PR locally via:
  
  ```bash
  npm install @auto-canary/bot-list@10.30.0--canary.2035.24576.0
  npm install @auto-canary/auto@10.30.0--canary.2035.24576.0
  npm install @auto-canary/core@10.30.0--canary.2035.24576.0
  npm install @auto-canary/package-json-utils@10.30.0--canary.2035.24576.0
  npm install @auto-canary/all-contributors@10.30.0--canary.2035.24576.0
  npm install @auto-canary/brew@10.30.0--canary.2035.24576.0
  npm install @auto-canary/chrome@10.30.0--canary.2035.24576.0
  npm install @auto-canary/cocoapods@10.30.0--canary.2035.24576.0
  npm install @auto-canary/conventional-commits@10.30.0--canary.2035.24576.0
  npm install @auto-canary/crates@10.30.0--canary.2035.24576.0
  npm install @auto-canary/docker@10.30.0--canary.2035.24576.0
  npm install @auto-canary/exec@10.30.0--canary.2035.24576.0
  npm install @auto-canary/first-time-contributor@10.30.0--canary.2035.24576.0
  npm install @auto-canary/gem@10.30.0--canary.2035.24576.0
  npm install @auto-canary/gh-pages@10.30.0--canary.2035.24576.0
  npm install @auto-canary/git-tag@10.30.0--canary.2035.24576.0
  npm install @auto-canary/gradle@10.30.0--canary.2035.24576.0
  npm install @auto-canary/jira@10.30.0--canary.2035.24576.0
  npm install @auto-canary/magic-zero@10.30.0--canary.2035.24576.0
  npm install @auto-canary/maven@10.30.0--canary.2035.24576.0
  npm install @auto-canary/microsoft-teams@10.30.0--canary.2035.24576.0
  npm install @auto-canary/npm@10.30.0--canary.2035.24576.0
  npm install @auto-canary/omit-commits@10.30.0--canary.2035.24576.0
  npm install @auto-canary/omit-release-notes@10.30.0--canary.2035.24576.0
  npm install @auto-canary/pr-body-labels@10.30.0--canary.2035.24576.0
  npm install @auto-canary/released@10.30.0--canary.2035.24576.0
  npm install @auto-canary/s3@10.30.0--canary.2035.24576.0
  npm install @auto-canary/sbt@10.30.0--canary.2035.24576.0
  npm install @auto-canary/slack@10.30.0--canary.2035.24576.0
  npm install @auto-canary/twitter@10.30.0--canary.2035.24576.0
  npm install @auto-canary/upload-assets@10.30.0--canary.2035.24576.0
  npm install @auto-canary/vscode@10.30.0--canary.2035.24576.0
  # or 
  yarn add @auto-canary/bot-list@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/auto@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/core@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/package-json-utils@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/all-contributors@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/brew@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/chrome@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/cocoapods@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/conventional-commits@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/crates@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/docker@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/exec@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/first-time-contributor@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/gem@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/gh-pages@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/git-tag@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/gradle@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/jira@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/magic-zero@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/maven@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/microsoft-teams@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/npm@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/omit-commits@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/omit-release-notes@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/pr-body-labels@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/released@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/s3@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/sbt@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/slack@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/twitter@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/upload-assets@10.30.0--canary.2035.24576.0
  yarn add @auto-canary/vscode@10.30.0--canary.2035.24576.0
  ```
</details>
<!-- GITHUB_RELEASE PR BODY: canary-version -->



Patch:
diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts
index 28385701..0cfa8cb5 100644
--- a/plugins/npm/src/index.ts
+++ b/plugins/npm/src/index.ts
@@ -25,7 +25,7 @@ import {
   DEFAULT_PRERELEASE_BRANCHES,
 } from "@auto-it/core";
 import getPackages from "get-monorepo-packages";
-import { gt, gte, inc, ReleaseType } from "semver";
+import { gt, gte, inc, prerelease, ReleaseType } from "semver";
 import {
   loadPackageJson,
   getRepo,
@@ -146,6 +146,7 @@ export async function getChangedPackages({
   return [...changed];
 }
 
+
 /** Get the package with the greatest version in a monorepo */
 export function getMonorepoPackage() {
   const packages = getPackages(process.cwd());
@@ -154,7 +155,15 @@ export function getMonorepoPackage() {
     return {} as IPackageJSON;
   }
 
-  const monorepoPackage = packages.reduce((greatest, subPackage) => {
+  // Remove pre-releases so that released package versions take precedence
+  let releasedPackages = packages.filter(subPackage => prerelease(subPackage.package?.version || '') === null);
+  // If doing this would remove all packages, this means were not any @latest releases yet
+  // In that case, restore the original list of packages.
+  if (releasedPackages.length === 0) {
+    releasedPackages = packages;
+  }
+
+  const monorepoPackage = releasedPackages.reduce((greatest, subPackage) => {
     if (subPackage.package.version) {
       if (!greatest.package.version) {
         return subPackage;


Test patch:
diff --git a/plugins/npm/__tests__/npm.test.ts b/plugins/npm/__tests__/npm.test.ts
index 57686859..453b1cf7 100644
--- a/plugins/npm/__tests__/npm.test.ts
+++ b/plugins/npm/__tests__/npm.test.ts
@@ -44,6 +44,16 @@ const monorepoPackagesResult = [
   { path: "packages/d", name: "@packages/d", package: { version: "0.1.1" } },
 ];
 
+const monorepoPackagesWithPrereleaseResult = [
+  { path: "packages/a", name: "@packages/a", package: { version: "0.1.1" } },
+  { path: "packages/b", name: "@packages/b", package: {} },
+  { path: "packages/c", name: "@packages/c", package: { version: "0.1.2" } },
+  { path: "packages/d", name: "@packages/d", package: { version: "0.1.1" } },
+  // This can happen if a new module is published with a breaking version
+  { path: "packages/e", name: "@packages/e", package: { version: "1.0.0-next.0" } },
+  { path: "packages/f", name: "@packages/f", package: { version: "1.0.0-next.0" } },
+];
+
 const packageTemplate = ({
   path,
   name,
@@ -143,6 +153,11 @@ describe("getMonorepoPackage", () => {
     monorepoPackages.mockReturnValueOnce(monorepoPackagesResult);
     expect(getMonorepoPackage()).toStrictEqual({ version: "0.1.2" });
   });
+
+  test("should ignore versions from preleases", () => {
+    monorepoPackages.mockReturnValueOnce(monorepoPackagesWithPrereleaseResult);
+    expect(getMonorepoPackage()).toStrictEqual({ version: "0.1.2" });
+  });
 });
 
 const prefixRelease = (str: string) => str;