From 2be0ff3873ca07fa4a9be96083af9e9a760753e8 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Sat, 29 Jul 2023 09:48:36 +0200
Subject: [PATCH] fix(lerna): skip bootstrap if using a v7 range (#23595)

---
 .../manager/npm/post-update/lerna.spec.ts     | 28 ++++++-------------
 lib/modules/manager/npm/post-update/lerna.ts  | 19 +++++++------
 2 files changed, 20 insertions(+), 27 deletions(-)

diff --git a/lib/modules/manager/npm/post-update/lerna.spec.ts b/lib/modules/manager/npm/post-update/lerna.spec.ts
index c56f39a345..8115050c2a 100644
--- a/lib/modules/manager/npm/post-update/lerna.spec.ts
+++ b/lib/modules/manager/npm/post-update/lerna.spec.ts
@@ -184,7 +184,10 @@ describe('modules/manager/npm/post-update/lerna', () => {
       const res = await lernaHelper.generateLockFiles(
         lernaPkgFile('npm'),
         'some-dir',
-        { ...config, constraints: { ...config.constraints, npm: '6.0.0' } },
+        {
+          ...config,
+          constraints: { ...config.constraints, lerna: '^7.1.4', npm: '6.0.0' },
+        },
         {}
       );
       expect(res.error).toBeFalse();
@@ -192,25 +195,12 @@ describe('modules/manager/npm/post-update/lerna', () => {
         { cmd: 'install-tool node 16.16.0' },
         { cmd: 'install-tool npm 6.0.0' },
         { cmd: 'hash -d npm 2>/dev/null || true' },
-        { cmd: 'install-tool lerna 2.0.0' },
-        {
-          cmd: 'lerna info || echo "Ignoring lerna info failure"',
-          options: {
-            cwd: 'some-dir',
-          },
-        },
         {
           cmd: 'npm install --ignore-scripts  --no-audit --package-lock-only',
           options: {
             cwd: 'some-dir',
           },
         },
-        {
-          cmd: 'lerna bootstrap --no-ci --ignore-scripts -- --ignore-scripts  --no-audit --package-lock-only',
-          options: {
-            cwd: 'some-dir',
-          },
-        },
       ]);
     });
   });
@@ -219,7 +209,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
     it('returns specified version', () => {
       const pkg = {};
       expect(
-        lernaHelper.getLernaVersion(pkg, {
+        lernaHelper.getLernaConstraint(pkg, {
           devDependencies: { lerna: '2.0.0' },
         })
       ).toBe('2.0.0');
@@ -228,7 +218,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
     it('returns specified range', () => {
       const pkg = {};
       expect(
-        lernaHelper.getLernaVersion(pkg, {
+        lernaHelper.getLernaConstraint(pkg, {
           dependencies: { lerna: '1.x || >=2.5.0 || 5.0.0 - 7.2.3' },
         })
       ).toBe('1.x || >=2.5.0 || 5.0.0 - 7.2.3');
@@ -236,18 +226,18 @@ describe('modules/manager/npm/post-update/lerna', () => {
 
     it('returns latest if no lerna dep is specified', () => {
       const pkg = {};
-      expect(lernaHelper.getLernaVersion(pkg, {})).toBeNull();
+      expect(lernaHelper.getLernaConstraint(pkg, {})).toBeNull();
     });
 
     it('returns latest if pkg has no deps at all', () => {
       const pkg = {};
-      expect(lernaHelper.getLernaVersion(pkg, {})).toBeNull();
+      expect(lernaHelper.getLernaConstraint(pkg, {})).toBeNull();
     });
 
     it('returns latest if specified lerna version is not a valid semVer range', () => {
       const pkg = {};
       expect(
-        lernaHelper.getLernaVersion(pkg, { engines: { lerna: '[a.b.c;' } })
+        lernaHelper.getLernaConstraint(pkg, { engines: { lerna: '[a.b.c;' } })
       ).toBeNull();
     });
   });
diff --git a/lib/modules/manager/npm/post-update/lerna.ts b/lib/modules/manager/npm/post-update/lerna.ts
index 0557889be0..4d07a60421 100644
--- a/lib/modules/manager/npm/post-update/lerna.ts
+++ b/lib/modules/manager/npm/post-update/lerna.ts
@@ -22,7 +22,7 @@ import type { GenerateLockFileResult } from './types';
 import { getPackageManagerVersion, lazyLoadPackageJson } from './utils';
 
 // Exported for testability
-export function getLernaVersion(
+export function getLernaConstraint(
   lernaPackageFile: Partial<PackageFile<NpmManagerData>>,
   lazyPkgJson: PackageJsonSchema
 ): string | null {
@@ -115,18 +115,21 @@ export async function generateLockFiles(
       extraEnv.NPM_AUTH = env.NPM_AUTH;
       extraEnv.NPM_EMAIL = env.NPM_EMAIL;
     }
-    const lernaVersion =
+    const lernaConstraint =
       config.constraints?.lerna ??
-      getLernaVersion(lernaPackageFile, await lazyPgkJson.getValue());
+      getLernaConstraint(lernaPackageFile, await lazyPgkJson.getValue());
     if (
-      !is.string(lernaVersion) ||
-      (semver.valid(lernaVersion) && semver.gte(lernaVersion, '7.0.0'))
+      !is.string(lernaConstraint) ||
+      (semver.valid(lernaConstraint) && semver.gte(lernaConstraint, '7.0.0')) ||
+      (semver.validRange(lernaConstraint) &&
+        (semver.satisfies('7.0.0', lernaConstraint) ||
+          semver.satisfies('7.999.999', lernaConstraint)))
     ) {
-      logger.debug('Skipping lerna bootstrap');
+      logger.debug('Skipping lerna bootstrap for lerna >= 7.0.0');
       cmd.push(`${lernaClient} install ${cmdOptions}`);
     } else {
-      logger.debug(`Using lerna version ${lernaVersion}`);
-      toolConstraints.push({ toolName: 'lerna', constraint: lernaVersion });
+      logger.debug(`Using lerna version ${lernaConstraint}`);
+      toolConstraints.push({ toolName: 'lerna', constraint: lernaConstraint });
       cmd.push('lerna info || echo "Ignoring lerna info failure"');
       cmd.push(`${lernaClient} install ${cmdOptions}`);
       cmd.push(lernaCommand);
-- 
GitLab