From eee428f9731de40b1245444a3e70fc4e752d22ab Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Tue, 23 Jul 2019 08:50:09 +0200
Subject: [PATCH] feat(pnpm): support binarySource=docker (#4151)

---
 lib/manager/npm/post-update/index.js        |  2 +-
 lib/manager/npm/post-update/pnpm.js         | 17 +++++++++--
 test/workers/branch/lock-files/pnpm.spec.js | 32 +++++++++++++++------
 3 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index 0932df833d..81e3d53c60 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -534,7 +534,7 @@ async function getAdditionalFiles(config, packageFiles) {
     const res = await pnpm.generateLockFile(
       upath.join(config.localDir, lockFileDir),
       env,
-      config.binarySource
+      config
     );
     if (res.error) {
       // istanbul ignore if
diff --git a/lib/manager/npm/post-update/pnpm.js b/lib/manager/npm/post-update/pnpm.js
index e5815ceba1..ba999d95c6 100644
--- a/lib/manager/npm/post-update/pnpm.js
+++ b/lib/manager/npm/post-update/pnpm.js
@@ -8,7 +8,7 @@ module.exports = {
   generateLockFile,
 };
 
-async function generateLockFile(cwd, env, binarySource) {
+async function generateLockFile(cwd, env, config) {
   logger.debug(`Spawning pnpm install to create ${cwd}/pnpm-lock.yaml`);
   let lockFile = null;
   let stdout;
@@ -53,9 +53,22 @@ async function generateLockFile(cwd, env, binarySource) {
         }
       }
     }
-    if (binarySource === 'global') {
+    if (config.binarySource === 'global') {
       cmd = 'pnpm';
     }
+    if (config.binarySource === 'docker') {
+      logger.info('Running pnpm via docker');
+      cmd = `docker run --rm `;
+      const volumes = [cwd];
+      if (config.cacheDir) {
+        volumes.push(config.cacheDir);
+      }
+      cmd += volumes.map(v => `-v ${v}:${v} `).join('');
+      const envVars = ['NPM_CONFIG_CACHE', 'npm_config_store'];
+      cmd += envVars.map(e => `-e ${e} `).join('');
+      cmd += `-w ${cwd} `;
+      cmd += `renovate/pnpm pnpm`;
+    }
     logger.debug(`Using pnpm: ${cmd}`);
     cmd += ' install';
     cmd += ' --lockfile-only';
diff --git a/test/workers/branch/lock-files/pnpm.spec.js b/test/workers/branch/lock-files/pnpm.spec.js
index 75d6f4a4bb..79b02dbdf8 100644
--- a/test/workers/branch/lock-files/pnpm.spec.js
+++ b/test/workers/branch/lock-files/pnpm.spec.js
@@ -12,6 +12,11 @@ const { exec } = require('child-process-promise');
 const pnpmHelper = require('../../../../lib/manager/npm/post-update/pnpm');
 
 describe('generateLockFile', () => {
+  let env;
+  let config;
+  beforeEach(() => {
+    config = { cacheDir: 'some-cache-dir' };
+  });
   it('generates lock files', async () => {
     getInstalledPath.mockReturnValueOnce('node_modules/pnpm');
     exec.mockReturnValueOnce({
@@ -19,7 +24,19 @@ describe('generateLockFile', () => {
       stderror: '',
     });
     fs.readFile = jest.fn(() => 'package-lock-contents');
-    const res = await pnpmHelper.generateLockFile('some-dir');
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
+    expect(fs.readFile).toHaveBeenCalledTimes(1);
+    expect(res.lockFile).toEqual('package-lock-contents');
+  });
+  it('uses docker pnpm', async () => {
+    getInstalledPath.mockReturnValueOnce('node_modules/pnpm');
+    exec.mockReturnValueOnce({
+      stdout: '',
+      stderror: '',
+    });
+    fs.readFile = jest.fn(() => 'package-lock-contents');
+    config.binarySource = 'docker';
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
     expect(fs.readFile).toHaveBeenCalledTimes(1);
     expect(res.lockFile).toEqual('package-lock-contents');
   });
@@ -32,7 +49,7 @@ describe('generateLockFile', () => {
     fs.readFile = jest.fn(() => {
       throw new Error('not found');
     });
-    const res = await pnpmHelper.generateLockFile('some-dir');
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
     expect(fs.readFile).toHaveBeenCalledTimes(1);
     expect(res.error).toBe(true);
     expect(res.lockFile).not.toBeDefined();
@@ -50,7 +67,7 @@ describe('generateLockFile', () => {
       stderror: '',
     });
     fs.readFile = jest.fn(() => 'package-lock-contents');
-    const res = await pnpmHelper.generateLockFile('some-dir');
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
     expect(fs.readFile).toHaveBeenCalledTimes(1);
     expect(res.lockFile).toEqual('package-lock-contents');
   });
@@ -68,7 +85,7 @@ describe('generateLockFile', () => {
       stderror: '',
     });
     fs.readFile = jest.fn(() => 'package-lock-contents');
-    const res = await pnpmHelper.generateLockFile('some-dir');
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
     expect(fs.readFile).toHaveBeenCalledTimes(1);
     expect(res.lockFile).toEqual('package-lock-contents');
   });
@@ -88,11 +105,8 @@ describe('generateLockFile', () => {
       stderror: '',
     });
     fs.readFile = jest.fn(() => 'package-lock-contents');
-    const res = await pnpmHelper.generateLockFile(
-      'some-dir',
-      undefined,
-      'global'
-    );
+    config.binarySource = 'global';
+    const res = await pnpmHelper.generateLockFile('some-dir', env, config);
     expect(fs.readFile).toHaveBeenCalledTimes(1);
     expect(res.lockFile).toEqual('package-lock-contents');
   });
-- 
GitLab