mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 06:26:26 +00:00
feat: pnpm shrinkwrap support (#1392)
This feature adds support for pnpm shrinkwrap.yaml files. Closes #1391
This commit is contained in:
parent
400ca57398
commit
23e217991c
10 changed files with 1844 additions and 62 deletions
|
@ -146,6 +146,17 @@ async function resolvePackageFiles(config) {
|
|||
);
|
||||
packageFile.packageLock = packageLockFileName;
|
||||
}
|
||||
const shrinkwrapFileName = upath.join(
|
||||
path.dirname(packageFile.packageFile),
|
||||
'shrinkwrap.yaml'
|
||||
);
|
||||
if (fileList.includes(shrinkwrapFileName)) {
|
||||
logger.debug(
|
||||
{ packageFile: packageFile.packageFile },
|
||||
'Found shrinkwrap.yaml'
|
||||
);
|
||||
packageFile.shrinkwrapYaml = shrinkwrapFileName;
|
||||
}
|
||||
return packageFile;
|
||||
} else if (packageFile.packageFile.endsWith('package.js')) {
|
||||
// meteor
|
||||
|
|
|
@ -3,10 +3,12 @@ const path = require('path');
|
|||
const upath = require('upath');
|
||||
const npm = require('./npm');
|
||||
const yarn = require('./yarn');
|
||||
const pnpm = require('./pnpm');
|
||||
|
||||
module.exports = {
|
||||
hasPackageLock,
|
||||
hasYarnLock,
|
||||
hasShrinkwrapYaml,
|
||||
determineLockFileDirs,
|
||||
writeExistingFiles,
|
||||
writeUpdatedPackageFiles,
|
||||
|
@ -45,9 +47,26 @@ function hasYarnLock(config, packageFile) {
|
|||
throw new Error(`hasYarnLock cannot find ${packageFile}`);
|
||||
}
|
||||
|
||||
function hasShrinkwrapYaml(config, packageFile) {
|
||||
logger.trace(
|
||||
{ packageFiles: config.packageFiles, packageFile },
|
||||
'hasShrinkwrapYaml'
|
||||
);
|
||||
for (const p of config.packageFiles) {
|
||||
if (p.packageFile === packageFile) {
|
||||
if (p.shrinkwrapYaml) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw new Error(`hasShrinkwrapYaml cannot find ${packageFile}`);
|
||||
}
|
||||
|
||||
function determineLockFileDirs(config) {
|
||||
const packageLockFileDirs = [];
|
||||
const yarnLockFileDirs = [];
|
||||
const shrinkwrapYamlDirs = [];
|
||||
|
||||
for (const upgrade of config.upgrades) {
|
||||
if (upgrade.type === 'lockFileMaintenance') {
|
||||
|
@ -60,8 +79,11 @@ function determineLockFileDirs(config) {
|
|||
if (packageFile.packageLock) {
|
||||
packageLockFileDirs.push(dirname);
|
||||
}
|
||||
if (packageFile.shrinkwrapYaml) {
|
||||
shrinkwrapYamlDirs.push(dirname);
|
||||
}
|
||||
}
|
||||
return { packageLockFileDirs, yarnLockFileDirs };
|
||||
return { packageLockFileDirs, yarnLockFileDirs, shrinkwrapYamlDirs };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +94,9 @@ function determineLockFileDirs(config) {
|
|||
if (module.exports.hasPackageLock(config, packageFile.name)) {
|
||||
packageLockFileDirs.push(path.dirname(packageFile.name));
|
||||
}
|
||||
if (module.exports.hasShrinkwrapYaml(config, packageFile.name)) {
|
||||
shrinkwrapYamlDirs.push(path.dirname(packageFile.name));
|
||||
}
|
||||
}
|
||||
|
||||
// If yarn workspaces are in use, then we need to generate yarn.lock from the workspaces dir
|
||||
|
@ -87,7 +112,7 @@ function determineLockFileDirs(config) {
|
|||
}
|
||||
}
|
||||
|
||||
return { yarnLockFileDirs, packageLockFileDirs };
|
||||
return { yarnLockFileDirs, packageLockFileDirs, shrinkwrapYamlDirs };
|
||||
}
|
||||
|
||||
async function writeExistingFiles(config) {
|
||||
|
@ -197,6 +222,20 @@ async function writeExistingFiles(config) {
|
|||
} else {
|
||||
await fs.remove(upath.join(basedir, 'yarn.lock'));
|
||||
}
|
||||
// TODO: Update the below with this once https://github.com/pnpm/pnpm/issues/992 is fixed
|
||||
const pnpmBug992 = true;
|
||||
// istanbul ignore next
|
||||
if (
|
||||
packageFile.shrinkwrapYaml &&
|
||||
config.type !== 'lockFileMaintenance' &&
|
||||
!pnpmBug992
|
||||
) {
|
||||
logger.debug(`Writing shrinkwrap.yaml to ${basedir}`);
|
||||
const shrinkwrap = await platform.getFile(packageFile.shrinkwrapYaml);
|
||||
await fs.outputFile(upath.join(basedir, 'shrinkwrap.yaml'), shrinkwrap);
|
||||
} else {
|
||||
await fs.remove(upath.join(basedir, 'shrinkwrap.yaml'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,5 +355,34 @@ async function getUpdatedLockFiles(config) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const lockFileDir of dirs.shrinkwrapYamlDirs) {
|
||||
logger.debug(`Generating shrinkwrap.yaml for ${lockFileDir}`);
|
||||
const lockFileName = upath.join(lockFileDir, 'shrinkwrap.yaml');
|
||||
const res = await pnpm.generateLockFile(
|
||||
upath.join(config.tmpDir.path, lockFileDir)
|
||||
);
|
||||
if (res.error) {
|
||||
lockFileErrors.push({
|
||||
lockFile: lockFileName,
|
||||
stderr: res.stderr,
|
||||
});
|
||||
} else {
|
||||
const existingContent = await platform.getFile(
|
||||
lockFileName,
|
||||
config.parentBranch
|
||||
);
|
||||
if (res.lockFile !== existingContent) {
|
||||
logger.debug('shrinkwrap.yaml needs updating');
|
||||
updatedLockFiles.push({
|
||||
name: lockFileName,
|
||||
contents: res.lockFile,
|
||||
});
|
||||
} else {
|
||||
logger.debug("shrinkwrap.yaml hasn't changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { lockFileErrors, updatedLockFiles };
|
||||
}
|
||||
|
|
85
lib/workers/branch/pnpm.js
Normal file
85
lib/workers/branch/pnpm.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
const fs = require('fs-extra');
|
||||
const upath = require('upath');
|
||||
const { getInstalledPath } = require('get-installed-path');
|
||||
const { exec } = require('child-process-promise');
|
||||
|
||||
module.exports = {
|
||||
generateLockFile,
|
||||
};
|
||||
|
||||
async function generateLockFile(tmpDir) {
|
||||
logger.debug(`Spawning pnpm install to create ${tmpDir}/shrinkwrap.yaml`);
|
||||
let lockFile = null;
|
||||
let stdout;
|
||||
let stderr;
|
||||
try {
|
||||
const startTime = process.hrtime();
|
||||
let cmd;
|
||||
try {
|
||||
// See if renovate is installed locally
|
||||
const installedPath = upath.join(
|
||||
await getInstalledPath('pnpm', {
|
||||
local: true,
|
||||
}),
|
||||
'lib/bin/pnpm.js'
|
||||
);
|
||||
cmd = `node ${installedPath}`;
|
||||
} catch (localerr) {
|
||||
logger.debug('No locally installed pnpm found');
|
||||
// Look inside globally installed renovate
|
||||
try {
|
||||
const renovateLocation = await getInstalledPath('renovate');
|
||||
const installedPath = upath.join(
|
||||
await getInstalledPath('pnpm', {
|
||||
local: true,
|
||||
cwd: renovateLocation,
|
||||
}),
|
||||
'lib/bin/pnpm.js'
|
||||
);
|
||||
cmd = `node ${installedPath}`;
|
||||
} catch (nestederr) {
|
||||
logger.debug('Could not find globally nested pnpm');
|
||||
// look for global pnpm
|
||||
try {
|
||||
const installedPath = upath.join(
|
||||
await getInstalledPath('pnpm'),
|
||||
'lib/bin/pnpm.js'
|
||||
);
|
||||
cmd = `node ${installedPath}`;
|
||||
} catch (globalerr) {
|
||||
logger.warn('Could not find globally installed pnpm');
|
||||
cmd = 'pnpm';
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug(`Using pnpm: ${cmd}`);
|
||||
cmd += ' install';
|
||||
cmd += ' --shrinkwrap-only';
|
||||
cmd += ' --ignore-scripts';
|
||||
cmd += ' --ignore-pnpmfile';
|
||||
// TODO: Switch to native util.promisify once using only node 8
|
||||
({ stdout, stderr } = await exec(cmd, {
|
||||
cwd: tmpDir,
|
||||
shell: true,
|
||||
env: { NODE_ENV: 'dev', PATH: process.env.PATH },
|
||||
}));
|
||||
logger.debug(`pnpm stdout:\n${stdout}`);
|
||||
logger.debug(`pnpm stderr:\n${stderr}`);
|
||||
const duration = process.hrtime(startTime);
|
||||
const seconds = Math.round(duration[0] + duration[1] / 1e9);
|
||||
lockFile = await fs.readFile(upath.join(tmpDir, 'shrinkwrap.yaml'), 'utf8');
|
||||
logger.info(
|
||||
{ seconds, type: 'shrinkwrap.yaml', stdout, stderr },
|
||||
'Generated lockfile'
|
||||
);
|
||||
} catch (err) /* istanbul ignore next */ {
|
||||
logger.info(
|
||||
{
|
||||
err,
|
||||
},
|
||||
'pnpm install error'
|
||||
);
|
||||
return { error: true, stderr: err.stderr };
|
||||
}
|
||||
return { lockFile };
|
||||
}
|
|
@ -71,6 +71,7 @@
|
|||
"npm": "5.6.0",
|
||||
"openpgp": "2.6.1",
|
||||
"parse-link-header": "1.0.1",
|
||||
"pnpm": "1.29.1",
|
||||
"registry-auth-token": "3.3.1",
|
||||
"root-require": "0.3.1",
|
||||
"semver": "5.4.1",
|
||||
|
|
|
@ -14,6 +14,7 @@ Array [
|
|||
"npmrc": "npmrc",
|
||||
"packageFile": "package.json",
|
||||
"packageLock": "package-lock.json",
|
||||
"shrinkwrapYaml": "shrinkwrap.yaml",
|
||||
"yarnLock": "yarn.lock",
|
||||
"yarnrc": "yarnrc",
|
||||
},
|
||||
|
|
|
@ -71,6 +71,7 @@ describe('manager/resolve', () => {
|
|||
platform.getFileList.mockReturnValueOnce([
|
||||
'yarn.lock',
|
||||
'package-lock.json',
|
||||
'shrinkwrap.yaml',
|
||||
]);
|
||||
platform.getFile.mockReturnValueOnce('{"name": "package.json"}');
|
||||
platform.getFile.mockReturnValueOnce('npmrc');
|
||||
|
|
|
@ -5,6 +5,9 @@ Object {
|
|||
"packageLockFileDirs": Array [
|
||||
"backend",
|
||||
],
|
||||
"shrinkwrapYamlDirs": Array [
|
||||
"frontend",
|
||||
],
|
||||
"yarnLockFileDirs": Array [
|
||||
".",
|
||||
],
|
||||
|
@ -16,6 +19,9 @@ Object {
|
|||
"packageLockFileDirs": Array [
|
||||
"backend",
|
||||
],
|
||||
"shrinkwrapYamlDirs": Array [
|
||||
"frontend",
|
||||
],
|
||||
"yarnLockFileDirs": Array [
|
||||
".",
|
||||
],
|
||||
|
@ -25,6 +31,7 @@ Object {
|
|||
exports[`workers/branch/lock-files determineLockFileDirs returns root directory if using yarn workspaces 1`] = `
|
||||
Object {
|
||||
"packageLockFileDirs": Array [],
|
||||
"shrinkwrapYamlDirs": Array [],
|
||||
"yarnLockFileDirs": Array [
|
||||
".",
|
||||
],
|
||||
|
|
|
@ -5,10 +5,12 @@ const upath = require('upath');
|
|||
|
||||
const npm = require('../../../lib/workers/branch/npm');
|
||||
const yarn = require('../../../lib/workers/branch/yarn');
|
||||
const pnpm = require('../../../lib/workers/branch/pnpm');
|
||||
|
||||
const {
|
||||
hasPackageLock,
|
||||
hasYarnLock,
|
||||
hasShrinkwrapYaml,
|
||||
determineLockFileDirs,
|
||||
writeExistingFiles,
|
||||
writeUpdatedPackageFiles,
|
||||
|
@ -110,6 +112,53 @@ describe('workers/branch/lock-files', () => {
|
|||
expect(e).toBeDefined();
|
||||
});
|
||||
});
|
||||
describe('hasShrinkWrapYaml', () => {
|
||||
let config;
|
||||
beforeEach(() => {
|
||||
config = {
|
||||
...defaultConfig,
|
||||
};
|
||||
});
|
||||
it('returns true if found and true', () => {
|
||||
config.packageFiles = [
|
||||
{
|
||||
packageFile: 'package.json',
|
||||
shrinkwrapYaml: 'some shrinkwrap',
|
||||
},
|
||||
];
|
||||
expect(hasShrinkwrapYaml(config, 'package.json')).toBe(true);
|
||||
});
|
||||
it('returns false if found and false', () => {
|
||||
config.packageFiles = [
|
||||
{
|
||||
packageFile: 'package.json',
|
||||
shrinkwrapYaml: 'some shrinkwrap',
|
||||
},
|
||||
{
|
||||
packageFile: 'backend/package.json',
|
||||
},
|
||||
];
|
||||
expect(hasShrinkwrapYaml(config, 'backend/package.json')).toBe(false);
|
||||
});
|
||||
it('throws error if not found', () => {
|
||||
config.packageFiles = [
|
||||
{
|
||||
packageFile: 'package.json',
|
||||
shrinkwrapYaml: 'some package lock',
|
||||
},
|
||||
{
|
||||
packageFile: 'backend/package.json',
|
||||
},
|
||||
];
|
||||
let e;
|
||||
try {
|
||||
hasShrinkwrapYaml(config, 'frontend/package.json');
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
expect(e).toBeDefined();
|
||||
});
|
||||
});
|
||||
describe('determineLockFileDirs', () => {
|
||||
let config;
|
||||
beforeEach(() => {
|
||||
|
@ -124,6 +173,10 @@ describe('workers/branch/lock-files', () => {
|
|||
packageFile: 'backend/package.json',
|
||||
packageLock: 'some package lock',
|
||||
},
|
||||
{
|
||||
packageFile: 'frontend/package.json',
|
||||
shrinkwrapYaml: 'some package lock',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
@ -143,6 +196,10 @@ describe('workers/branch/lock-files', () => {
|
|||
name: 'backend/package.json',
|
||||
contents: 'some contents',
|
||||
},
|
||||
{
|
||||
name: 'frontend/package.json',
|
||||
contents: 'some contents',
|
||||
},
|
||||
];
|
||||
const res = determineLockFileDirs(config);
|
||||
expect(res).toMatchSnapshot();
|
||||
|
@ -207,7 +264,7 @@ describe('workers/branch/lock-files', () => {
|
|||
];
|
||||
await writeExistingFiles(config);
|
||||
expect(fs.outputFile.mock.calls).toHaveLength(6);
|
||||
expect(fs.remove.mock.calls).toHaveLength(4);
|
||||
expect(fs.remove.mock.calls).toHaveLength(6);
|
||||
});
|
||||
it('writes package.json of local lib', async () => {
|
||||
const renoPath = upath.join(__dirname, '../../../');
|
||||
|
@ -230,7 +287,7 @@ describe('workers/branch/lock-files', () => {
|
|||
platform.getFile.mockReturnValue('some lock file contents');
|
||||
await writeExistingFiles(config);
|
||||
expect(fs.outputFile.mock.calls).toHaveLength(4);
|
||||
expect(fs.remove.mock.calls).toHaveLength(0);
|
||||
expect(fs.remove.mock.calls).toHaveLength(1);
|
||||
});
|
||||
it('Try to write package.json of local lib, but file not found', async () => {
|
||||
const renoPath = upath.join(__dirname, '../../../');
|
||||
|
@ -253,7 +310,7 @@ describe('workers/branch/lock-files', () => {
|
|||
platform.getFile.mockReturnValue(null);
|
||||
await writeExistingFiles(config);
|
||||
expect(fs.outputFile.mock.calls).toHaveLength(3);
|
||||
expect(fs.remove.mock.calls).toHaveLength(0);
|
||||
expect(fs.remove.mock.calls).toHaveLength(1);
|
||||
});
|
||||
it('detect malicious intent (error config in package.json) local lib is not in the repo', async () => {
|
||||
const renoPath = upath.join(__dirname, '../../../');
|
||||
|
@ -276,7 +333,7 @@ describe('workers/branch/lock-files', () => {
|
|||
platform.getFile.mockReturnValue(null);
|
||||
await writeExistingFiles(config);
|
||||
expect(fs.outputFile.mock.calls).toHaveLength(3);
|
||||
expect(fs.remove.mock.calls).toHaveLength(0);
|
||||
expect(fs.remove.mock.calls).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
describe('writeUpdatedPackageFiles', () => {
|
||||
|
@ -336,6 +393,10 @@ describe('workers/branch/lock-files', () => {
|
|||
yarn.generateLockFile.mockReturnValue({
|
||||
lockFile: 'some lock file contents',
|
||||
});
|
||||
pnpm.generateLockFile = jest.fn();
|
||||
pnpm.generateLockFile.mockReturnValue({
|
||||
lockFile: 'some lock file contents',
|
||||
});
|
||||
lockFiles.determineLockFileDirs = jest.fn();
|
||||
});
|
||||
afterEach(() => {
|
||||
|
@ -353,6 +414,7 @@ describe('workers/branch/lock-files', () => {
|
|||
lockFiles.determineLockFileDirs.mockReturnValueOnce({
|
||||
packageLockFileDirs: [],
|
||||
yarnLockFileDirs: [],
|
||||
shrinkwrapYamlDirs: [],
|
||||
});
|
||||
const res = await getUpdatedLockFiles(config);
|
||||
expect(res).toMatchSnapshot();
|
||||
|
@ -363,6 +425,7 @@ describe('workers/branch/lock-files', () => {
|
|||
lockFiles.determineLockFileDirs.mockReturnValueOnce({
|
||||
packageLockFileDirs: ['a', 'b'],
|
||||
yarnLockFileDirs: ['c', 'd'],
|
||||
shrinkwrapYamlDirs: ['e'],
|
||||
});
|
||||
const res = await getUpdatedLockFiles(config);
|
||||
expect(res).toMatchSnapshot();
|
||||
|
@ -370,17 +433,19 @@ describe('workers/branch/lock-files', () => {
|
|||
expect(res.updatedLockFiles).toHaveLength(0);
|
||||
expect(npm.generateLockFile.mock.calls).toHaveLength(2);
|
||||
expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
|
||||
expect(platform.getFile.mock.calls).toHaveLength(4);
|
||||
expect(platform.getFile.mock.calls).toHaveLength(5);
|
||||
});
|
||||
it('sets error if receiving null', async () => {
|
||||
lockFiles.determineLockFileDirs.mockReturnValueOnce({
|
||||
packageLockFileDirs: ['a', 'b'],
|
||||
yarnLockFileDirs: ['c', 'd'],
|
||||
shrinkwrapYamlDirs: ['e'],
|
||||
});
|
||||
npm.generateLockFile.mockReturnValueOnce({ error: true });
|
||||
yarn.generateLockFile.mockReturnValueOnce({ error: true });
|
||||
pnpm.generateLockFile.mockReturnValueOnce({ error: true });
|
||||
const res = await getUpdatedLockFiles(config);
|
||||
expect(res.lockFileErrors).toHaveLength(2);
|
||||
expect(res.lockFileErrors).toHaveLength(3);
|
||||
expect(res.updatedLockFiles).toHaveLength(0);
|
||||
expect(npm.generateLockFile.mock.calls).toHaveLength(2);
|
||||
expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
|
||||
|
@ -390,15 +455,17 @@ describe('workers/branch/lock-files', () => {
|
|||
lockFiles.determineLockFileDirs.mockReturnValueOnce({
|
||||
packageLockFileDirs: ['a', 'b'],
|
||||
yarnLockFileDirs: ['c', 'd'],
|
||||
shrinkwrapYamlDirs: ['e'],
|
||||
});
|
||||
npm.generateLockFile.mockReturnValueOnce('some new lock file contents');
|
||||
yarn.generateLockFile.mockReturnValueOnce('some new lock file contents');
|
||||
pnpm.generateLockFile.mockReturnValueOnce('some new lock file contents');
|
||||
const res = await getUpdatedLockFiles(config);
|
||||
expect(res.lockFileErrors).toHaveLength(0);
|
||||
expect(res.updatedLockFiles).toHaveLength(2);
|
||||
expect(res.updatedLockFiles).toHaveLength(3);
|
||||
expect(npm.generateLockFile.mock.calls).toHaveLength(2);
|
||||
expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
|
||||
expect(platform.getFile.mock.calls).toHaveLength(4);
|
||||
expect(platform.getFile.mock.calls).toHaveLength(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
95
test/workers/branch/pnpm.spec.js
Normal file
95
test/workers/branch/pnpm.spec.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
const pnpmHelper = require('../../../lib/workers/branch/pnpm');
|
||||
|
||||
const { getInstalledPath } = require('get-installed-path');
|
||||
|
||||
jest.mock('fs-extra');
|
||||
jest.mock('child-process-promise');
|
||||
jest.mock('get-installed-path');
|
||||
|
||||
getInstalledPath.mockImplementation(() => null);
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const { exec } = require('child-process-promise');
|
||||
|
||||
describe('generateLockFile', () => {
|
||||
it('generates lock files', async () => {
|
||||
getInstalledPath.mockReturnValueOnce('node_modules/pnpm');
|
||||
exec.mockReturnValueOnce({
|
||||
stdout: '',
|
||||
stderror: '',
|
||||
});
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir');
|
||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||
expect(res.lockFile).toEqual('package-lock-contents');
|
||||
});
|
||||
it('catches errors', async () => {
|
||||
getInstalledPath.mockReturnValueOnce('node_modules/pnpm');
|
||||
exec.mockReturnValueOnce({
|
||||
stdout: '',
|
||||
stderror: 'some-error',
|
||||
});
|
||||
fs.readFile = jest.fn(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
const res = await pnpmHelper.generateLockFile('some-dir');
|
||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||
expect(res.error).toBe(true);
|
||||
expect(res.lockFile).not.toBeDefined();
|
||||
});
|
||||
it('finds pnpm embedded in renovate', async () => {
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
getInstalledPath.mockImplementationOnce(() => '/node_modules/renovate');
|
||||
getInstalledPath.mockImplementationOnce(
|
||||
() => '/node_modules/renovate/node_modules/pnpm'
|
||||
);
|
||||
exec.mockReturnValueOnce({
|
||||
stdout: '',
|
||||
stderror: '',
|
||||
});
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir');
|
||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||
expect(res.lockFile).toEqual('package-lock-contents');
|
||||
});
|
||||
it('finds pnpm globally', async () => {
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
getInstalledPath.mockImplementationOnce(() => '/node_modules/renovate');
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
getInstalledPath.mockImplementationOnce(() => '/node_modules/pnpm');
|
||||
exec.mockReturnValueOnce({
|
||||
stdout: '',
|
||||
stderror: '',
|
||||
});
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir');
|
||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||
expect(res.lockFile).toEqual('package-lock-contents');
|
||||
});
|
||||
it('uses fallback pnpm', async () => {
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
getInstalledPath.mockImplementationOnce(() => '/node_modules/renovate');
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
getInstalledPath.mockImplementationOnce(() => {
|
||||
throw new Error('not found');
|
||||
});
|
||||
exec.mockReturnValueOnce({
|
||||
stdout: '',
|
||||
stderror: '',
|
||||
});
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir');
|
||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||
expect(res.lockFile).toEqual('package-lock-contents');
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue