Skip to content
Snippets Groups Projects
Commit 00dabb5d authored by Rhys Arkins's avatar Rhys Arkins Committed by GitHub
Browse files

feat: raise pr with warning if lock file generation fails (#994)

Previously, upgrades with failing lock files were not raised as PRs. Usually this is because of missing private module configuration. Now, Renovate will raise a PR but add a comment warning of the error, with the error log. It's raised as a comment because we now won't need to regenerate the lock file error every run, and we don't want to "lose" it if the PR description gets updated.

Closes #600 
parent e8810b33
No related branches found
No related tags found
No related merge requests found
...@@ -79,9 +79,6 @@ async function processBranch(branchConfig) { ...@@ -79,9 +79,6 @@ async function processBranch(branchConfig) {
logger.debug('No package files need updating'); logger.debug('No package files need updating');
} }
Object.assign(config, await getUpdatedLockFiles(config)); Object.assign(config, await getUpdatedLockFiles(config));
if (config.lockFileError) {
return 'lockFileError';
}
if (config.updatedLockFiles.length) { if (config.updatedLockFiles.length) {
logger.debug( logger.debug(
{ updatedLockFiles: config.updatedLockFiles }, { updatedLockFiles: config.updatedLockFiles },
...@@ -124,11 +121,43 @@ async function processBranch(branchConfig) { ...@@ -124,11 +121,43 @@ async function processBranch(branchConfig) {
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
// TODO: ensurePr should check for automerge itself // TODO: ensurePr should check for automerge itself
if (pr) { if (pr) {
const topic = 'Lock file problem';
if (config.lockFileErrors && config.lockFileErrors.length) {
logger.warn(
{ lockFileErrors: config.lockFileErrors },
'lockFileErrors'
);
let content = `Renovate failed when attempting to generate `;
content +=
config.lockFileErrors.length > 1 ? 'lock files' : 'a lock file';
content +=
'. This is usually happens when you have private modules but have not added configuration for [private module support](https://renovateapp.com/docs/deep-dives/private-modules). It is strongly recommended that you do not merge this PR as-is.';
content +=
'\n\nRenovate **will not retry** generating a lockfile for this PR unless either (a) the `package.json` in this branch needs updating, or (b) ';
if (config.recreateClosed) {
content +=
'you manually delete this PR so that it can be regenerated.';
} else {
content +=
'you rename then delete this PR unmerged, so that it can be regenerated.';
}
content += '\n\nThe output from `stderr` is included below:';
const subtopics = [];
config.lockFileErrors.forEach(error => {
subtopics.push({
topic: error.lockFile,
content: `\`\`\`\n${error.stderr}\n\`\`\``,
});
});
await config.api.ensureComment(pr.number, topic, content, subtopics);
} else {
await config.api.ensureCommentRemoval(pr.number, topic);
const prAutomerged = await prWorker.checkAutoMerge(pr, config); const prAutomerged = await prWorker.checkAutoMerge(pr, config);
if (prAutomerged) { if (prAutomerged) {
return 'automerged'; return 'automerged';
} }
} }
}
} catch (err) { } catch (err) {
logger.error({ err }, `Error ensuring PR: ${err.message}`); logger.error({ err }, `Error ensuring PR: ${err.message}`);
// Don't throw here - we don't want to stop the other renovations // Don't throw here - we don't want to stop the other renovations
......
...@@ -194,14 +194,13 @@ async function getUpdatedLockFiles(config) { ...@@ -194,14 +194,13 @@ async function getUpdatedLockFiles(config) {
const { logger } = config; const { logger } = config;
logger.trace({ config }, 'getUpdatedLockFiles'); logger.trace({ config }, 'getUpdatedLockFiles');
logger.debug('Getting updated lock files'); logger.debug('Getting updated lock files');
let lockFileError = false; const lockFileErrors = [];
const updatedLockFiles = []; const updatedLockFiles = [];
try {
if ( if (
config.type === 'lockFileMaintenance' && config.type === 'lockFileMaintenance' &&
(await config.api.branchExists(config.branchName)) (await config.api.branchExists(config.branchName))
) { ) {
return { lockFileError, updatedLockFiles }; return { lockFileErrors, updatedLockFiles };
} }
const dirs = module.exports.determineLockFileDirs(config); const dirs = module.exports.determineLockFileDirs(config);
logger.debug({ dirs }, 'lock file dirs'); logger.debug({ dirs }, 'lock file dirs');
...@@ -210,58 +209,60 @@ async function getUpdatedLockFiles(config) { ...@@ -210,58 +209,60 @@ async function getUpdatedLockFiles(config) {
for (const lockFileDir of dirs.packageLockFileDirs) { for (const lockFileDir of dirs.packageLockFileDirs) {
logger.debug(`Generating package-lock.json for ${lockFileDir}`); logger.debug(`Generating package-lock.json for ${lockFileDir}`);
const newContent = await npm.generateLockFile( const lockFileName = path.join(lockFileDir, 'package-lock.json');
const res = await npm.generateLockFile(
path.join(config.tmpDir.path, lockFileDir), path.join(config.tmpDir.path, lockFileDir),
logger logger
); );
if (newContent) { if (res.error) {
const lockFileName = path.join(lockFileDir, 'package-lock.json'); lockFileErrors.push({
lockFile: lockFileName,
stderr: res.stderr,
});
} else {
const existingContent = await config.api.getFileContent( const existingContent = await config.api.getFileContent(
lockFileName, lockFileName,
config.parentBranch config.parentBranch
); );
if (newContent !== existingContent) { if (res.lockFile !== existingContent) {
logger.debug('package-lock.json needs updating'); logger.debug('package-lock.json needs updating');
updatedLockFiles.push({ updatedLockFiles.push({
name: lockFileName, name: lockFileName,
contents: newContent, contents: res.lockFile,
}); });
} else { } else {
logger.debug("package-lock.json hasn't changed"); logger.debug("package-lock.json hasn't changed");
} }
} else {
lockFileError = true;
} }
} }
for (const lockFileDir of dirs.yarnLockFileDirs) { for (const lockFileDir of dirs.yarnLockFileDirs) {
logger.debug(`Generating yarn.lock for ${lockFileDir}`); logger.debug(`Generating yarn.lock for ${lockFileDir}`);
const newContent = await yarn.generateLockFile( const lockFileName = path.join(lockFileDir, 'yarn.lock');
const res = await yarn.generateLockFile(
path.join(config.tmpDir.path, lockFileDir), path.join(config.tmpDir.path, lockFileDir),
logger logger
); );
if (newContent) { if (res.error) {
const lockFileName = path.join(lockFileDir, 'yarn.lock'); lockFileErrors.push({
lockFile: lockFileName,
stderr: res.stderr,
});
} else {
const existingContent = await config.api.getFileContent( const existingContent = await config.api.getFileContent(
lockFileName, lockFileName,
config.parentBranch config.parentBranch
); );
if (newContent !== existingContent) { if (res.lockFile !== existingContent) {
logger.debug('yarn.lock needs updating'); logger.debug('yarn.lock needs updating');
updatedLockFiles.push({ updatedLockFiles.push({
name: lockFileName, name: lockFileName,
contents: newContent, contents: res.lockFile,
}); });
} else { } else {
logger.debug("yarn.lock hasn't changed"); logger.debug("yarn.lock hasn't changed");
} }
} else {
lockFileError = true;
}
} }
} catch (err) {
logger.error({ err }, 'getUpdatedLockFiles error');
lockFileError = true;
} }
return { lockFileError, updatedLockFiles }; return { lockFileErrors, updatedLockFiles };
} }
...@@ -82,6 +82,7 @@ async function generateLockFile(tmpDir, logger) { ...@@ -82,6 +82,7 @@ async function generateLockFile(tmpDir, logger) {
}, },
'npm install error' 'npm install error'
); );
return { error: true, stderr };
} }
return lockFile; return { lockFile };
} }
...@@ -72,7 +72,7 @@ async function generateLockFile(tmpDir, logger) { ...@@ -72,7 +72,7 @@ async function generateLockFile(tmpDir, logger) {
'Generated lockfile' 'Generated lockfile'
); );
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {
logger.warn( logger.info(
{ {
err, err,
stdout, stdout,
...@@ -80,6 +80,7 @@ async function generateLockFile(tmpDir, logger) { ...@@ -80,6 +80,7 @@ async function generateLockFile(tmpDir, logger) {
}, },
'yarn install error' 'yarn install error'
); );
return { error: true, stderr: err.stderr };
} }
return lockFile; return { lockFile };
} }
...@@ -33,14 +33,14 @@ Object { ...@@ -33,14 +33,14 @@ Object {
exports[`workers/branch/lock-files getUpdatedLockFiles adds multiple lock files 1`] = ` exports[`workers/branch/lock-files getUpdatedLockFiles adds multiple lock files 1`] = `
Object { Object {
"lockFileError": false, "lockFileErrors": Array [],
"updatedLockFiles": Array [ "updatedLockFiles": Array [
Object { Object {
"contents": "some new lock file contents", "contents": undefined,
"name": "a/package-lock.json", "name": "a/package-lock.json",
}, },
Object { Object {
"contents": "some new lock file contents", "contents": undefined,
"name": "c/yarn.lock", "name": "c/yarn.lock",
}, },
], ],
...@@ -49,42 +49,37 @@ Object { ...@@ -49,42 +49,37 @@ Object {
exports[`workers/branch/lock-files getUpdatedLockFiles returns no error and empty lockfiles if lock file maintenance exists 1`] = ` exports[`workers/branch/lock-files getUpdatedLockFiles returns no error and empty lockfiles if lock file maintenance exists 1`] = `
Object { Object {
"lockFileError": false, "lockFileErrors": Array [],
"updatedLockFiles": Array [], "updatedLockFiles": Array [],
} }
`; `;
exports[`workers/branch/lock-files getUpdatedLockFiles returns no error and empty lockfiles if none updated 1`] = ` exports[`workers/branch/lock-files getUpdatedLockFiles returns no error and empty lockfiles if none updated 1`] = `
Object { Object {
"lockFileError": false, "lockFileErrors": Array [],
"updatedLockFiles": Array [], "updatedLockFiles": Array [],
} }
`; `;
exports[`workers/branch/lock-files getUpdatedLockFiles returns npm errors 1`] = ` exports[`workers/branch/lock-files getUpdatedLockFiles sets error if receiving null 1`] = `
Object { Object {
"lockFileError": true, "lockFileErrors": Array [
"updatedLockFiles": Array [],
}
`;
exports[`workers/branch/lock-files getUpdatedLockFiles returns yarn errors 1`] = `
Object { Object {
"lockFileError": true, "lockFile": "a/package-lock.json",
"updatedLockFiles": Array [], "stderr": undefined,
} },
`;
exports[`workers/branch/lock-files getUpdatedLockFiles sets error if receiving null 1`] = `
Object { Object {
"lockFileError": true, "lockFile": "c/yarn.lock",
"stderr": undefined,
},
],
"updatedLockFiles": Array [], "updatedLockFiles": Array [],
} }
`; `;
exports[`workers/branch/lock-files getUpdatedLockFiles tries multiple lock files 1`] = ` exports[`workers/branch/lock-files getUpdatedLockFiles tries multiple lock files 1`] = `
Object { Object {
"lockFileError": false, "lockFileErrors": Array [],
"updatedLockFiles": Array [], "updatedLockFiles": Array [],
} }
`; `;
......
...@@ -27,9 +27,15 @@ describe('workers/branch', () => { ...@@ -27,9 +27,15 @@ describe('workers/branch', () => {
describe('processBranch', () => { describe('processBranch', () => {
let config; let config;
beforeEach(() => { beforeEach(() => {
prWorker.ensurePr = jest.fn();
prWorker.checkAutoMerge = jest.fn();
config = { config = {
...defaultConfig, ...defaultConfig,
api: { branchExists: jest.fn(), ensureComment: jest.fn() }, api: {
branchExists: jest.fn(),
ensureComment: jest.fn(),
ensureCommentRemoval: jest.fn(),
},
errors: [], errors: [],
warnings: [], warnings: [],
logger, logger,
...@@ -101,8 +107,44 @@ describe('workers/branch', () => { ...@@ -101,8 +107,44 @@ describe('workers/branch', () => {
prWorker.checkAutoMerge.mockReturnValueOnce(true); prWorker.checkAutoMerge.mockReturnValueOnce(true);
await branchWorker.processBranch(config); await branchWorker.processBranch(config);
expect(prWorker.ensurePr.mock.calls).toHaveLength(1); expect(prWorker.ensurePr.mock.calls).toHaveLength(1);
expect(config.api.ensureCommentRemoval.mock.calls).toHaveLength(1);
expect(prWorker.checkAutoMerge.mock.calls).toHaveLength(1); expect(prWorker.checkAutoMerge.mock.calls).toHaveLength(1);
}); });
it('ensures PR and adds lock file error comment', async () => {
packageFiles.getUpdatedPackageFiles.mockReturnValueOnce([{}]);
lockFiles.getUpdatedLockFiles.mockReturnValueOnce({
lockFileError: false,
updatedLockFiles: [{}],
});
config.api.branchExists.mockReturnValueOnce(true);
automerge.tryBranchAutomerge.mockReturnValueOnce('failed');
prWorker.ensurePr.mockReturnValueOnce({});
prWorker.checkAutoMerge.mockReturnValueOnce(true);
config.lockFileErrors = [{}];
await branchWorker.processBranch(config);
expect(config.api.ensureComment.mock.calls).toHaveLength(1);
expect(config.api.ensureCommentRemoval.mock.calls).toHaveLength(0);
expect(prWorker.ensurePr.mock.calls).toHaveLength(1);
expect(prWorker.checkAutoMerge.mock.calls).toHaveLength(0);
});
it('ensures PR and adds lock file error comment recreate closed', async () => {
packageFiles.getUpdatedPackageFiles.mockReturnValueOnce([{}]);
lockFiles.getUpdatedLockFiles.mockReturnValueOnce({
lockFileError: false,
updatedLockFiles: [{}],
});
config.recreateClosed = true;
config.api.branchExists.mockReturnValueOnce(true);
automerge.tryBranchAutomerge.mockReturnValueOnce('failed');
prWorker.ensurePr.mockReturnValueOnce({});
prWorker.checkAutoMerge.mockReturnValueOnce(true);
config.lockFileErrors = [{}];
await branchWorker.processBranch(config);
expect(config.api.ensureComment.mock.calls).toHaveLength(1);
expect(config.api.ensureCommentRemoval.mock.calls).toHaveLength(0);
expect(prWorker.ensurePr.mock.calls).toHaveLength(1);
expect(prWorker.checkAutoMerge.mock.calls).toHaveLength(0);
});
it('swallows branch errors', async () => { it('swallows branch errors', async () => {
packageFiles.getUpdatedPackageFiles.mockImplementationOnce(() => { packageFiles.getUpdatedPackageFiles.mockImplementationOnce(() => {
throw new Error('some error'); throw new Error('some error');
......
...@@ -284,9 +284,13 @@ describe('workers/branch/lock-files', () => { ...@@ -284,9 +284,13 @@ describe('workers/branch/lock-files', () => {
tmpDir: { path: 'some-tmp-dir' }, tmpDir: { path: 'some-tmp-dir' },
}; };
npm.generateLockFile = jest.fn(); npm.generateLockFile = jest.fn();
npm.generateLockFile.mockReturnValue('some lock file contents'); npm.generateLockFile.mockReturnValue({
lockFile: 'some lock file contents',
});
yarn.generateLockFile = jest.fn(); yarn.generateLockFile = jest.fn();
yarn.generateLockFile.mockReturnValue('some lock file contents'); yarn.generateLockFile.mockReturnValue({
lockFile: 'some lock file contents',
});
lockFiles.determineLockFileDirs = jest.fn(); lockFiles.determineLockFileDirs = jest.fn();
}); });
it('returns no error and empty lockfiles if lock file maintenance exists', async () => { it('returns no error and empty lockfiles if lock file maintenance exists', async () => {
...@@ -294,7 +298,7 @@ describe('workers/branch/lock-files', () => { ...@@ -294,7 +298,7 @@ describe('workers/branch/lock-files', () => {
config.api.branchExists.mockReturnValueOnce(true); config.api.branchExists.mockReturnValueOnce(true);
const res = await getUpdatedLockFiles(config); const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(false); expect(res.lockFileErrors).toHaveLength(0);
expect(res.updatedLockFiles).toHaveLength(0); expect(res.updatedLockFiles).toHaveLength(0);
}); });
it('returns no error and empty lockfiles if none updated', async () => { it('returns no error and empty lockfiles if none updated', async () => {
...@@ -304,7 +308,7 @@ describe('workers/branch/lock-files', () => { ...@@ -304,7 +308,7 @@ describe('workers/branch/lock-files', () => {
}); });
const res = await getUpdatedLockFiles(config); const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(false); expect(res.lockFileErrors).toHaveLength(0);
expect(res.updatedLockFiles).toHaveLength(0); expect(res.updatedLockFiles).toHaveLength(0);
}); });
it('tries multiple lock files', async () => { it('tries multiple lock files', async () => {
...@@ -314,7 +318,7 @@ describe('workers/branch/lock-files', () => { ...@@ -314,7 +318,7 @@ describe('workers/branch/lock-files', () => {
}); });
const res = await getUpdatedLockFiles(config); const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(false); expect(res.lockFileErrors).toHaveLength(0);
expect(res.updatedLockFiles).toHaveLength(0); expect(res.updatedLockFiles).toHaveLength(0);
expect(npm.generateLockFile.mock.calls).toHaveLength(2); expect(npm.generateLockFile.mock.calls).toHaveLength(2);
expect(yarn.generateLockFile.mock.calls).toHaveLength(2); expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
...@@ -325,11 +329,11 @@ describe('workers/branch/lock-files', () => { ...@@ -325,11 +329,11 @@ describe('workers/branch/lock-files', () => {
packageLockFileDirs: ['a', 'b'], packageLockFileDirs: ['a', 'b'],
yarnLockFileDirs: ['c', 'd'], yarnLockFileDirs: ['c', 'd'],
}); });
npm.generateLockFile.mockReturnValueOnce(null); npm.generateLockFile.mockReturnValueOnce({ error: true });
yarn.generateLockFile.mockReturnValueOnce(null); yarn.generateLockFile.mockReturnValueOnce({ error: true });
const res = await getUpdatedLockFiles(config); const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(true); expect(res.lockFileErrors).toHaveLength(2);
expect(res.updatedLockFiles).toHaveLength(0); expect(res.updatedLockFiles).toHaveLength(0);
expect(npm.generateLockFile.mock.calls).toHaveLength(2); expect(npm.generateLockFile.mock.calls).toHaveLength(2);
expect(yarn.generateLockFile.mock.calls).toHaveLength(2); expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
...@@ -344,43 +348,11 @@ describe('workers/branch/lock-files', () => { ...@@ -344,43 +348,11 @@ describe('workers/branch/lock-files', () => {
yarn.generateLockFile.mockReturnValueOnce('some new lock file contents'); yarn.generateLockFile.mockReturnValueOnce('some new lock file contents');
const res = await getUpdatedLockFiles(config); const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(false); expect(res.lockFileErrors).toHaveLength(0);
expect(res.updatedLockFiles).toHaveLength(2); expect(res.updatedLockFiles).toHaveLength(2);
expect(npm.generateLockFile.mock.calls).toHaveLength(2); expect(npm.generateLockFile.mock.calls).toHaveLength(2);
expect(yarn.generateLockFile.mock.calls).toHaveLength(2); expect(yarn.generateLockFile.mock.calls).toHaveLength(2);
expect(config.api.getFileContent.mock.calls).toHaveLength(4); expect(config.api.getFileContent.mock.calls).toHaveLength(4);
}); });
it('returns npm errors', async () => {
lockFiles.determineLockFileDirs.mockReturnValueOnce({
packageLockFileDirs: ['a', 'b'],
yarnLockFileDirs: ['c', 'd'],
});
npm.generateLockFile.mockImplementationOnce(() => {
throw new Error('some error');
});
const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(true);
expect(res.updatedLockFiles).toHaveLength(0);
expect(npm.generateLockFile.mock.calls).toHaveLength(1);
expect(yarn.generateLockFile.mock.calls).toHaveLength(0);
expect(config.api.getFileContent.mock.calls).toHaveLength(0);
});
it('returns yarn errors', async () => {
lockFiles.determineLockFileDirs.mockReturnValueOnce({
packageLockFileDirs: [],
yarnLockFileDirs: ['c', 'd'],
});
yarn.generateLockFile.mockImplementationOnce(() => {
throw new Error('some error');
});
const res = await getUpdatedLockFiles(config);
expect(res).toMatchSnapshot();
expect(res.lockFileError).toBe(true);
expect(res.updatedLockFiles).toHaveLength(0);
expect(npm.generateLockFile.mock.calls).toHaveLength(0);
expect(yarn.generateLockFile.mock.calls).toHaveLength(1);
expect(config.api.getFileContent.mock.calls).toHaveLength(0);
});
}); });
}); });
...@@ -19,9 +19,10 @@ describe('generateLockFile', () => { ...@@ -19,9 +19,10 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await npmHelper.generateLockFile('some-dir', logger); const res = await npmHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.error).not.toBeDefined();
expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('catches errors', async () => { it('catches errors', async () => {
getInstalledPath.mockReturnValueOnce('node_modules/npm'); getInstalledPath.mockReturnValueOnce('node_modules/npm');
...@@ -32,9 +33,10 @@ describe('generateLockFile', () => { ...@@ -32,9 +33,10 @@ describe('generateLockFile', () => {
fs.readFile = jest.fn(() => { fs.readFile = jest.fn(() => {
throw new Error('not found'); throw new Error('not found');
}); });
const lockFile = await npmHelper.generateLockFile('some-dir', logger); const res = await npmHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toBe(null); expect(res.error).toBe(true);
expect(res.lockFile).not.toBeDefined();
}); });
it('finds npm embedded in renovate', async () => { it('finds npm embedded in renovate', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -49,9 +51,9 @@ describe('generateLockFile', () => { ...@@ -49,9 +51,9 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await npmHelper.generateLockFile('some-dir', logger); const res = await npmHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('finds npm globally', async () => { it('finds npm globally', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -67,9 +69,9 @@ describe('generateLockFile', () => { ...@@ -67,9 +69,9 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await npmHelper.generateLockFile('some-dir', logger); const res = await npmHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('uses fallback npm', async () => { it('uses fallback npm', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -87,8 +89,8 @@ describe('generateLockFile', () => { ...@@ -87,8 +89,8 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await npmHelper.generateLockFile('some-dir', logger); const res = await npmHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
}); });
...@@ -19,9 +19,9 @@ describe('generateLockFile', () => { ...@@ -19,9 +19,9 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await yarnHelper.generateLockFile('some-dir', logger); const res = await yarnHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('catches errors', async () => { it('catches errors', async () => {
getInstalledPath.mockReturnValueOnce('node_modules/yarn'); getInstalledPath.mockReturnValueOnce('node_modules/yarn');
...@@ -32,9 +32,10 @@ describe('generateLockFile', () => { ...@@ -32,9 +32,10 @@ describe('generateLockFile', () => {
fs.readFile = jest.fn(() => { fs.readFile = jest.fn(() => {
throw new Error('not found'); throw new Error('not found');
}); });
const lockFile = await yarnHelper.generateLockFile('some-dir', logger); const res = await yarnHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toBe(null); expect(res.error).toBe(true);
expect(res.lockFile).not.toBeDefined();
}); });
it('finds yarn embedded in renovate', async () => { it('finds yarn embedded in renovate', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -49,9 +50,9 @@ describe('generateLockFile', () => { ...@@ -49,9 +50,9 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await yarnHelper.generateLockFile('some-dir', logger); const res = await yarnHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('finds yarn globally', async () => { it('finds yarn globally', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -67,9 +68,9 @@ describe('generateLockFile', () => { ...@@ -67,9 +68,9 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await yarnHelper.generateLockFile('some-dir', logger); const res = await yarnHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
it('uses fallback yarn', async () => { it('uses fallback yarn', async () => {
getInstalledPath.mockImplementationOnce(() => { getInstalledPath.mockImplementationOnce(() => {
...@@ -87,8 +88,8 @@ describe('generateLockFile', () => { ...@@ -87,8 +88,8 @@ describe('generateLockFile', () => {
stderror: '', stderror: '',
}); });
fs.readFile = jest.fn(() => 'package-lock-contents'); fs.readFile = jest.fn(() => 'package-lock-contents');
const lockFile = await yarnHelper.generateLockFile('some-dir', logger); const res = await yarnHelper.generateLockFile('some-dir', logger);
expect(fs.readFile.mock.calls.length).toEqual(1); expect(fs.readFile.mock.calls.length).toEqual(1);
expect(lockFile).toEqual('package-lock-contents'); expect(res.lockFile).toEqual('package-lock-contents');
}); });
}); });
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment