From 098ed9a09c75944ff8c065aaecb3bd727afb5a21 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 3 Jun 2020 08:06:28 +0200
Subject: [PATCH] feat(lerna): dynamic npm and yarn versioning

Closes #6369
---
 lib/manager/npm/post-update/lerna.spec.ts | 12 ++++++++++--
 lib/manager/npm/post-update/lerna.ts      | 15 +++++++++++++--
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/manager/npm/post-update/lerna.spec.ts b/lib/manager/npm/post-update/lerna.spec.ts
index 9438d7ae4a..49cc2015a2 100644
--- a/lib/manager/npm/post-update/lerna.spec.ts
+++ b/lib/manager/npm/post-update/lerna.spec.ts
@@ -70,7 +70,12 @@ describe('generateLockFiles()', () => {
       JSON.stringify({ devDependencies: { lerna: '2.0.0' } })
     );
     const execSnapshots = mockExecAll(exec);
-    const res = await lernaHelper.generateLockFiles('yarn', 'some-dir', {}, {});
+    const res = await lernaHelper.generateLockFiles(
+      'yarn',
+      'some-dir',
+      { compatibility: { yarn: '^1.10.0' } },
+      {}
+    );
     expect(execSnapshots).toMatchSnapshot();
     expect(res.error).toBe(false);
   });
@@ -87,7 +92,10 @@ describe('generateLockFiles()', () => {
     const res = await lernaHelper.generateLockFiles(
       'npm',
       'some-dir',
-      { dockerMapDotfiles: true },
+      {
+        dockerMapDotfiles: true,
+        compatibility: { npm: '^6.0.0' },
+      },
       {}
     );
     expect(res.error).toBe(false);
diff --git a/lib/manager/npm/post-update/lerna.ts b/lib/manager/npm/post-update/lerna.ts
index 1cc1951fcd..214765c5bb 100644
--- a/lib/manager/npm/post-update/lerna.ts
+++ b/lib/manager/npm/post-update/lerna.ts
@@ -1,4 +1,4 @@
-import semver from 'semver';
+import semver, { validRange } from 'semver';
 import { quote } from 'shlex';
 import { join } from 'upath';
 import { logger } from '../../../logger';
@@ -30,12 +30,23 @@ export async function generateLockFiles(
   let cmdOptions = '';
   try {
     if (lernaClient === 'yarn') {
-      preCommands.push('npm i -g yarn');
+      let installYarn = 'npm i -g yarn';
+      const yarnCompatibility = config.compatibility?.yarn;
+      if (validRange(yarnCompatibility)) {
+        installYarn += `@${quote(yarnCompatibility)}`;
+      }
+      preCommands.push(installYarn);
       if (skipInstalls !== false) {
         preCommands.push(optimizeCommand);
       }
       cmdOptions = '--ignore-scripts --ignore-engines --ignore-platform';
     } else if (lernaClient === 'npm') {
+      let installNpm = 'npm i -g npm';
+      const npmCompatibility = config.compatibility?.npm;
+      if (validRange(npmCompatibility)) {
+        installNpm += `@${quote(npmCompatibility)}`;
+        preCommands.push(installNpm);
+      }
       cmdOptions = '--ignore-scripts  --no-audit';
       if (skipInstalls !== false) {
         cmdOptions += ' --package-lock-only';
-- 
GitLab