2020-08-06 05:59:22 +00:00
|
|
|
import is from '@sindresorhus/is';
|
2021-05-21 20:20:23 +00:00
|
|
|
import deepmerge from 'deepmerge';
|
2021-11-17 15:21:36 +00:00
|
|
|
import detectIndent from 'detect-indent';
|
2021-05-26 13:01:09 +00:00
|
|
|
import { dump, load } from 'js-yaml';
|
2020-07-06 09:17:06 +00:00
|
|
|
import upath from 'upath';
|
2021-11-23 20:10:45 +00:00
|
|
|
import { GlobalConfig } from '../../../config/global';
|
2020-07-06 09:17:06 +00:00
|
|
|
import { SYSTEM_INSUFFICIENT_DISK_SPACE } from '../../../constants/error-messages';
|
|
|
|
import { id as npmId } from '../../../datasource/npm';
|
|
|
|
import { logger } from '../../../logger';
|
|
|
|
import { ExternalHostError } from '../../../types/errors/external-host-error';
|
|
|
|
import { getChildProcessEnv } from '../../../util/exec/env';
|
2020-07-04 10:47:52 +00:00
|
|
|
import {
|
2020-07-06 09:17:06 +00:00
|
|
|
deleteLocalFile,
|
2021-06-24 13:06:04 +00:00
|
|
|
ensureCacheDir,
|
2021-05-21 20:20:23 +00:00
|
|
|
getSiblingFileName,
|
2021-03-19 14:33:23 +00:00
|
|
|
getSubDirectory,
|
2020-07-04 10:47:52 +00:00
|
|
|
outputFile,
|
|
|
|
readFile,
|
2021-05-21 20:20:23 +00:00
|
|
|
readLocalFile,
|
2020-07-04 10:47:52 +00:00
|
|
|
remove,
|
|
|
|
unlink,
|
|
|
|
writeFile,
|
2021-05-21 20:20:23 +00:00
|
|
|
writeLocalFile,
|
2020-07-06 09:17:06 +00:00
|
|
|
} from '../../../util/fs';
|
2020-07-04 16:15:29 +00:00
|
|
|
import { branchExists, getFile, getRepoStatus } from '../../../util/git';
|
2020-05-01 16:03:48 +00:00
|
|
|
import * as hostRules from '../../../util/host-rules';
|
2021-10-20 04:38:49 +00:00
|
|
|
import { regEx } from '../../../util/regex';
|
2021-12-29 06:26:13 +00:00
|
|
|
import { ensureTrailingSlash } from '../../../util/url';
|
2021-03-02 20:44:55 +00:00
|
|
|
import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types';
|
2021-08-29 12:59:58 +00:00
|
|
|
import { getZeroInstallPaths } from '../extract/yarn';
|
2019-07-25 06:17:19 +00:00
|
|
|
import * as lerna from './lerna';
|
2020-05-01 16:03:48 +00:00
|
|
|
import * as npm from './npm';
|
2019-07-25 06:17:19 +00:00
|
|
|
import * as pnpm from './pnpm';
|
2021-05-21 20:20:23 +00:00
|
|
|
import { processHostRules } from './rules';
|
2021-05-11 17:08:02 +00:00
|
|
|
import type {
|
|
|
|
AdditionalPackageFiles,
|
|
|
|
ArtifactError,
|
|
|
|
DetermineLockFileDirsResult,
|
|
|
|
UpdatedArtifacts,
|
|
|
|
WriteExistingFilesResult,
|
|
|
|
} from './types';
|
2020-05-01 16:03:48 +00:00
|
|
|
import * as yarn from './yarn';
|
2017-08-26 14:10:18 +00:00
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
// Strips empty values, deduplicates, and returns the directories from filenames
|
|
|
|
// istanbul ignore next
|
2019-11-23 20:44:55 +00:00
|
|
|
const getDirs = (arr: string[]): string[] =>
|
|
|
|
Array.from(new Set(arr.filter(Boolean)));
|
2017-08-26 14:10:18 +00:00
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
// istanbul ignore next
|
2019-07-25 06:17:19 +00:00
|
|
|
export function determineLockFileDirs(
|
|
|
|
config: PostUpdateConfig,
|
|
|
|
packageFiles: AdditionalPackageFiles
|
|
|
|
): DetermineLockFileDirsResult {
|
2018-05-09 06:03:59 +00:00
|
|
|
const npmLockDirs = [];
|
|
|
|
const yarnLockDirs = [];
|
|
|
|
const pnpmShrinkwrapDirs = [];
|
2021-03-19 14:33:23 +00:00
|
|
|
const lernaJsonFiles = [];
|
2017-08-26 14:10:18 +00:00
|
|
|
|
|
|
|
for (const upgrade of config.upgrades) {
|
2021-03-01 14:35:13 +00:00
|
|
|
if (upgrade.updateType === 'lockFileMaintenance' || upgrade.isRemediation) {
|
2018-05-09 06:03:59 +00:00
|
|
|
// Return every directory that contains a lockfile
|
2021-03-19 14:58:24 +00:00
|
|
|
if (upgrade.managerData?.lernaJsonFile && upgrade.npmLock) {
|
|
|
|
lernaJsonFiles.push(upgrade.managerData.lernaJsonFile);
|
2018-09-07 07:22:04 +00:00
|
|
|
} else {
|
|
|
|
yarnLockDirs.push(upgrade.yarnLock);
|
|
|
|
npmLockDirs.push(upgrade.npmLock);
|
|
|
|
pnpmShrinkwrapDirs.push(upgrade.pnpmShrinkwrap);
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2021-11-08 19:20:03 +00:00
|
|
|
continue;
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2019-01-24 05:23:08 +00:00
|
|
|
if (upgrade.isLockfileUpdate) {
|
|
|
|
yarnLockDirs.push(upgrade.yarnLock);
|
|
|
|
npmLockDirs.push(upgrade.npmLock);
|
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 07:48:20 +00:00
|
|
|
if (
|
|
|
|
config.upgrades.every(
|
2019-07-25 06:17:19 +00:00
|
|
|
(upgrade: Upgrade) =>
|
2019-01-24 05:23:08 +00:00
|
|
|
upgrade.updateType === 'lockFileMaintenance' || upgrade.isLockfileUpdate
|
2018-09-10 07:48:20 +00:00
|
|
|
)
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
yarnLockDirs: getDirs(yarnLockDirs),
|
|
|
|
npmLockDirs: getDirs(npmLockDirs),
|
|
|
|
pnpmShrinkwrapDirs: getDirs(pnpmShrinkwrapDirs),
|
2021-03-19 14:33:23 +00:00
|
|
|
lernaJsonFiles: getDirs(lernaJsonFiles),
|
2018-09-10 07:48:20 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-07-25 06:17:19 +00:00
|
|
|
function getPackageFile(fileName: string): Partial<PackageFile> {
|
2018-05-09 06:03:59 +00:00
|
|
|
logger.trace('Looking for packageFile: ' + fileName);
|
|
|
|
for (const packageFile of packageFiles.npm) {
|
|
|
|
if (packageFile.packageFile === fileName) {
|
|
|
|
logger.trace({ packageFile }, 'Found packageFile');
|
|
|
|
return packageFile;
|
|
|
|
}
|
|
|
|
logger.trace('No match');
|
2018-01-15 15:55:33 +00:00
|
|
|
}
|
2018-05-09 06:03:59 +00:00
|
|
|
return {};
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
for (const p of config.updatedPackageFiles) {
|
2020-08-27 06:59:23 +00:00
|
|
|
logger.trace(`Checking ${String(p.name)} for lock files`);
|
2018-05-09 06:03:59 +00:00
|
|
|
const packageFile = getPackageFile(p.name);
|
|
|
|
// lerna first
|
2021-03-19 14:58:24 +00:00
|
|
|
if (packageFile.managerData?.lernaJsonFile && packageFile.npmLock) {
|
2018-05-09 06:03:59 +00:00
|
|
|
logger.debug(`${packageFile.packageFile} has lerna lock file`);
|
2021-03-19 14:58:24 +00:00
|
|
|
lernaJsonFiles.push(packageFile.managerData.lernaJsonFile);
|
2019-03-20 21:46:56 +00:00
|
|
|
} else if (
|
2021-03-19 14:58:24 +00:00
|
|
|
packageFile.managerData?.lernaJsonFile &&
|
2019-03-20 21:46:56 +00:00
|
|
|
packageFile.yarnLock &&
|
|
|
|
!packageFile.hasYarnWorkspaces
|
|
|
|
) {
|
2021-03-19 14:58:24 +00:00
|
|
|
lernaJsonFiles.push(packageFile.managerData.lernaJsonFile);
|
2018-05-09 06:03:59 +00:00
|
|
|
} else {
|
|
|
|
// push full lock file names and convert them later
|
|
|
|
yarnLockDirs.push(packageFile.yarnLock);
|
|
|
|
npmLockDirs.push(packageFile.npmLock);
|
|
|
|
pnpmShrinkwrapDirs.push(packageFile.pnpmShrinkwrap);
|
2017-09-29 06:08:52 +00:00
|
|
|
}
|
2017-08-27 06:17:34 +00:00
|
|
|
}
|
|
|
|
|
2018-02-05 19:06:24 +00:00
|
|
|
return {
|
2018-05-09 06:03:59 +00:00
|
|
|
yarnLockDirs: getDirs(yarnLockDirs),
|
|
|
|
npmLockDirs: getDirs(npmLockDirs),
|
|
|
|
pnpmShrinkwrapDirs: getDirs(pnpmShrinkwrapDirs),
|
2021-03-19 14:33:23 +00:00
|
|
|
lernaJsonFiles: getDirs(lernaJsonFiles),
|
2018-02-05 19:06:24 +00:00
|
|
|
};
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
// istanbul ignore next
|
2019-07-25 06:17:19 +00:00
|
|
|
export async function writeExistingFiles(
|
|
|
|
config: PostUpdateConfig,
|
|
|
|
packageFiles: AdditionalPackageFiles
|
2019-11-23 20:44:55 +00:00
|
|
|
): Promise<void> {
|
2018-05-09 06:03:59 +00:00
|
|
|
if (!packageFiles.npm) {
|
2017-08-26 14:10:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-05-09 06:03:59 +00:00
|
|
|
const npmFiles = packageFiles.npm;
|
2018-03-24 05:31:01 +00:00
|
|
|
logger.debug(
|
2020-04-12 16:09:36 +00:00
|
|
|
{ packageFiles: npmFiles.map((n) => n.packageFile) },
|
2018-03-24 05:31:01 +00:00
|
|
|
'Writing package.json files'
|
|
|
|
);
|
2021-11-23 20:10:45 +00:00
|
|
|
const { localDir } = GlobalConfig.get();
|
2018-02-09 05:55:47 +00:00
|
|
|
for (const packageFile of npmFiles) {
|
2017-11-24 06:50:49 +00:00
|
|
|
const basedir = upath.join(
|
2021-05-26 11:22:16 +00:00
|
|
|
localDir,
|
2020-11-12 20:46:08 +00:00
|
|
|
upath.dirname(packageFile.packageFile)
|
2017-08-26 14:10:18 +00:00
|
|
|
);
|
2020-08-27 18:11:00 +00:00
|
|
|
const npmrc: string = packageFile.npmrc || config.npmrc;
|
2020-08-11 14:04:19 +00:00
|
|
|
const npmrcFilename = upath.join(basedir, '.npmrc');
|
2021-04-01 16:09:36 +00:00
|
|
|
if (is.string(npmrc)) {
|
2021-04-01 12:19:47 +00:00
|
|
|
try {
|
|
|
|
await outputFile(npmrcFilename, `${npmrc}\n`);
|
|
|
|
} catch (err) /* istanbul ignore next */ {
|
|
|
|
logger.warn({ npmrcFilename, err }, 'Error writing .npmrc');
|
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2018-05-15 18:03:06 +00:00
|
|
|
const { npmLock } = packageFile;
|
|
|
|
if (npmLock) {
|
2021-05-26 11:22:16 +00:00
|
|
|
const npmLockPath = upath.join(localDir, npmLock);
|
2018-07-04 17:20:34 +00:00
|
|
|
if (
|
|
|
|
process.env.RENOVATE_REUSE_PACKAGE_LOCK === 'false' ||
|
2018-07-05 10:02:53 +00:00
|
|
|
config.reuseLockFiles === false
|
2018-07-04 17:20:34 +00:00
|
|
|
) {
|
2018-05-15 18:52:25 +00:00
|
|
|
logger.debug(`Ensuring ${npmLock} is removed`);
|
2020-07-04 10:47:52 +00:00
|
|
|
await remove(npmLockPath);
|
2018-05-15 18:03:06 +00:00
|
|
|
} else {
|
|
|
|
logger.debug(`Writing ${npmLock}`);
|
2021-11-11 11:46:40 +00:00
|
|
|
let existingNpmLock: string;
|
2021-11-17 15:21:36 +00:00
|
|
|
let detectedIndent: string;
|
2021-11-11 11:46:40 +00:00
|
|
|
let npmLockParsed: any;
|
|
|
|
try {
|
|
|
|
existingNpmLock = await getFile(npmLock);
|
2021-11-17 15:21:36 +00:00
|
|
|
detectedIndent = detectIndent(existingNpmLock).indent || ' ';
|
2021-11-11 11:46:40 +00:00
|
|
|
npmLockParsed = JSON.parse(existingNpmLock);
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn({ err }, 'Error parsing npm lock file');
|
|
|
|
}
|
|
|
|
if (npmLockParsed) {
|
|
|
|
const packageNames = Object.keys(npmLockParsed?.packages || {}); // lockfileVersion=2
|
|
|
|
const widens = [];
|
|
|
|
let lockFileChanged = false;
|
|
|
|
for (const upgrade of config.upgrades) {
|
2021-11-08 14:20:16 +00:00
|
|
|
if (
|
2021-11-11 11:46:40 +00:00
|
|
|
upgrade.rangeStrategy === 'widen' &&
|
|
|
|
upgrade.npmLock === npmLock
|
2021-11-08 14:20:16 +00:00
|
|
|
) {
|
2021-11-11 11:46:40 +00:00
|
|
|
widens.push(upgrade.depName);
|
2021-11-08 14:20:16 +00:00
|
|
|
}
|
2021-11-11 11:46:40 +00:00
|
|
|
const { depName } = upgrade;
|
|
|
|
for (const packageName of packageNames) {
|
|
|
|
if (
|
|
|
|
packageName === `node_modules/${depName}` ||
|
|
|
|
packageName.startsWith(`node_modules/${depName}/`)
|
|
|
|
) {
|
|
|
|
logger.trace({ packageName }, 'Massaging out package name');
|
|
|
|
lockFileChanged = true;
|
|
|
|
delete npmLockParsed.packages[packageName];
|
|
|
|
}
|
2018-10-17 10:33:49 +00:00
|
|
|
}
|
2021-11-11 11:46:40 +00:00
|
|
|
}
|
|
|
|
if (widens.length) {
|
|
|
|
logger.debug(
|
|
|
|
`Removing ${String(widens)} from ${npmLock} to force an update`
|
2018-09-22 16:17:49 +00:00
|
|
|
);
|
2021-11-11 11:46:40 +00:00
|
|
|
lockFileChanged = true;
|
|
|
|
try {
|
|
|
|
if (npmLockParsed.dependencies) {
|
|
|
|
widens.forEach((depName) => {
|
|
|
|
delete npmLockParsed.dependencies[depName];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn(
|
|
|
|
{ npmLock },
|
|
|
|
'Error massaging package-lock.json for widen'
|
|
|
|
);
|
|
|
|
}
|
2018-09-22 16:17:49 +00:00
|
|
|
}
|
2021-11-11 11:46:40 +00:00
|
|
|
if (lockFileChanged) {
|
|
|
|
logger.debug('Massaging npm lock file before writing to disk');
|
2021-11-17 15:21:36 +00:00
|
|
|
existingNpmLock = JSON.stringify(
|
|
|
|
npmLockParsed,
|
|
|
|
null,
|
|
|
|
detectedIndent
|
|
|
|
);
|
2021-11-11 11:46:40 +00:00
|
|
|
}
|
|
|
|
await outputFile(npmLockPath, existingNpmLock);
|
2018-09-22 16:17:49 +00:00
|
|
|
}
|
2018-05-15 18:03:06 +00:00
|
|
|
}
|
2018-03-08 08:39:32 +00:00
|
|
|
}
|
2018-05-15 18:52:25 +00:00
|
|
|
const { yarnLock } = packageFile;
|
2020-05-14 19:04:10 +00:00
|
|
|
if (yarnLock && config.reuseLockFiles === false) {
|
|
|
|
await deleteLocalFile(yarnLock);
|
2017-10-08 03:52:58 +00:00
|
|
|
}
|
2018-01-15 15:55:33 +00:00
|
|
|
// istanbul ignore next
|
2020-05-14 19:04:10 +00:00
|
|
|
if (packageFile.pnpmShrinkwrap && config.reuseLockFiles === false) {
|
|
|
|
await deleteLocalFile(packageFile.pnpmShrinkwrap);
|
2018-01-15 15:55:33 +00:00
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
// istanbul ignore next
|
2019-11-23 20:44:55 +00:00
|
|
|
export async function writeUpdatedPackageFiles(
|
|
|
|
config: PostUpdateConfig
|
|
|
|
): Promise<void> {
|
2017-08-26 14:10:18 +00:00
|
|
|
logger.trace({ config }, 'writeUpdatedPackageFiles');
|
|
|
|
logger.debug('Writing any updated package files');
|
|
|
|
if (!config.updatedPackageFiles) {
|
|
|
|
logger.debug('No files found');
|
|
|
|
return;
|
|
|
|
}
|
2021-11-23 20:10:45 +00:00
|
|
|
const { localDir } = GlobalConfig.get();
|
2021-12-14 17:43:50 +00:00
|
|
|
const supportedLockFiles = ['package-lock.json'];
|
2017-08-26 14:10:18 +00:00
|
|
|
for (const packageFile of config.updatedPackageFiles) {
|
2021-12-14 17:43:50 +00:00
|
|
|
if (
|
|
|
|
supportedLockFiles.some((fileName) => packageFile.name.endsWith(fileName))
|
|
|
|
) {
|
|
|
|
logger.debug(`Writing lock file: ${packageFile.name}`);
|
2021-03-01 14:35:13 +00:00
|
|
|
await outputFile(
|
2021-05-26 11:22:16 +00:00
|
|
|
upath.join(localDir, packageFile.name),
|
2021-03-01 14:35:13 +00:00
|
|
|
packageFile.contents
|
|
|
|
);
|
2021-11-08 19:20:03 +00:00
|
|
|
continue;
|
2021-03-01 14:35:13 +00:00
|
|
|
}
|
2017-09-14 20:10:51 +00:00
|
|
|
if (!packageFile.name.endsWith('package.json')) {
|
2021-11-08 19:20:03 +00:00
|
|
|
continue;
|
2017-09-14 20:10:51 +00:00
|
|
|
}
|
2020-08-27 06:59:23 +00:00
|
|
|
logger.debug(`Writing ${String(packageFile.name)}`);
|
2021-11-17 15:21:36 +00:00
|
|
|
const detectedIndent =
|
|
|
|
detectIndent(packageFile.contents.toString()).indent || ' ';
|
2021-03-01 13:52:19 +00:00
|
|
|
const massagedFile = JSON.parse(packageFile.contents.toString());
|
2018-09-17 09:18:18 +00:00
|
|
|
try {
|
2019-05-24 15:40:39 +00:00
|
|
|
const { token } = hostRules.find({
|
|
|
|
hostType: config.platform,
|
|
|
|
url: 'https://api.github.com/',
|
|
|
|
});
|
2018-09-17 09:18:18 +00:00
|
|
|
for (const upgrade of config.upgrades) {
|
|
|
|
if (upgrade.gitRef && upgrade.packageFile === packageFile.name) {
|
|
|
|
massagedFile[upgrade.depType][upgrade.depName] = massagedFile[
|
|
|
|
upgrade.depType
|
|
|
|
][upgrade.depName].replace(
|
|
|
|
'git+https://github.com',
|
|
|
|
`git+https://${token}@github.com`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn({ err }, 'Error adding token to package files');
|
|
|
|
}
|
2020-07-04 10:47:52 +00:00
|
|
|
await outputFile(
|
2021-05-26 11:22:16 +00:00
|
|
|
upath.join(localDir, packageFile.name),
|
2021-11-17 15:21:36 +00:00
|
|
|
JSON.stringify(massagedFile, null, detectedIndent)
|
2017-08-26 14:10:18 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 07:04:25 +00:00
|
|
|
// istanbul ignore next
|
|
|
|
async function getNpmrcContent(dir: string): Promise<string | null> {
|
|
|
|
const npmrcFilePath = upath.join(dir, '.npmrc');
|
|
|
|
let originalNpmrcContent = null;
|
|
|
|
try {
|
2020-07-04 10:47:52 +00:00
|
|
|
originalNpmrcContent = await readFile(npmrcFilePath, 'utf8');
|
2020-03-30 07:04:25 +00:00
|
|
|
logger.debug('npmrc file found in repository');
|
|
|
|
} catch {
|
|
|
|
logger.debug('No npmrc file found in repository');
|
|
|
|
originalNpmrcContent = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return originalNpmrcContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// istanbul ignore next
|
|
|
|
async function updateNpmrcContent(
|
|
|
|
dir: string,
|
|
|
|
originalContent: string,
|
|
|
|
additionalLines: string[]
|
|
|
|
): Promise<void> {
|
|
|
|
const npmrcFilePath = upath.join(dir, '.npmrc');
|
|
|
|
const newNpmrc = originalContent
|
|
|
|
? [originalContent, ...additionalLines]
|
|
|
|
: additionalLines;
|
2021-04-01 12:19:47 +00:00
|
|
|
try {
|
|
|
|
const newContent = newNpmrc.join('\n');
|
|
|
|
if (newContent !== originalContent) {
|
|
|
|
logger.debug(`Writing updated .npmrc file to ${npmrcFilePath}`);
|
|
|
|
await writeFile(npmrcFilePath, `${newContent}\n`);
|
|
|
|
}
|
|
|
|
} catch {
|
|
|
|
logger.warn('Unable to write custom npmrc file');
|
2020-03-30 07:04:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// istanbul ignore next
|
|
|
|
async function resetNpmrcContent(
|
|
|
|
dir: string,
|
|
|
|
originalContent: string
|
|
|
|
): Promise<void> {
|
|
|
|
const npmrcFilePath = upath.join(dir, '.npmrc');
|
|
|
|
if (originalContent) {
|
|
|
|
try {
|
2020-07-04 10:47:52 +00:00
|
|
|
await writeFile(npmrcFilePath, originalContent);
|
2020-03-30 07:04:25 +00:00
|
|
|
} catch {
|
|
|
|
logger.warn('Unable to reset npmrc to original contents');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
try {
|
2020-07-04 10:47:52 +00:00
|
|
|
await unlink(npmrcFilePath);
|
2020-03-30 07:04:25 +00:00
|
|
|
} catch {
|
|
|
|
logger.warn('Unable to delete custom npmrc');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-19 21:12:30 +00:00
|
|
|
// istanbul ignore next
|
|
|
|
async function updateYarnOffline(
|
|
|
|
lockFileDir: string,
|
2021-05-26 11:22:16 +00:00
|
|
|
localDir: string,
|
2020-10-19 21:12:30 +00:00
|
|
|
updatedArtifacts: UpdatedArtifacts[]
|
|
|
|
): Promise<void> {
|
|
|
|
try {
|
|
|
|
const resolvedPaths: string[] = [];
|
|
|
|
const yarnrcYml = await getFile(upath.join(lockFileDir, '.yarnrc.yml'));
|
|
|
|
const yarnrc = await getFile(upath.join(lockFileDir, '.yarnrc'));
|
|
|
|
|
|
|
|
// As .yarnrc.yml overrides .yarnrc in Yarn 1 (https://git.io/JUcco)
|
|
|
|
// both files may exist, so check for .yarnrc.yml first
|
|
|
|
if (yarnrcYml) {
|
|
|
|
// Yarn 2 (offline cache and zero-installs)
|
2021-08-29 12:59:58 +00:00
|
|
|
const paths = getZeroInstallPaths(yarnrcYml);
|
|
|
|
resolvedPaths.push(...paths.map((p) => upath.join(lockFileDir, p)));
|
2020-10-19 21:12:30 +00:00
|
|
|
} else if (yarnrc) {
|
|
|
|
// Yarn 1 (offline mirror)
|
|
|
|
const mirrorLine = yarnrc
|
|
|
|
.split('\n')
|
|
|
|
.find((line) => line.startsWith('yarn-offline-mirror '));
|
|
|
|
if (mirrorLine) {
|
2021-12-29 06:26:13 +00:00
|
|
|
const mirrorPath = ensureTrailingSlash(
|
|
|
|
mirrorLine.split(' ')[1].replace(regEx(/"/g), '')
|
|
|
|
);
|
2020-10-19 21:12:30 +00:00
|
|
|
resolvedPaths.push(upath.join(lockFileDir, mirrorPath));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logger.debug({ resolvedPaths }, 'updateYarnOffline resolvedPaths');
|
|
|
|
|
|
|
|
if (resolvedPaths.length) {
|
|
|
|
const status = await getRepoStatus();
|
|
|
|
for (const f of status.modified.concat(status.not_added)) {
|
|
|
|
if (resolvedPaths.some((p) => f.startsWith(p))) {
|
2021-05-26 11:22:16 +00:00
|
|
|
const localModified = upath.join(localDir, f);
|
2020-10-19 21:12:30 +00:00
|
|
|
updatedArtifacts.push({
|
|
|
|
name: f,
|
|
|
|
contents: await readFile(localModified),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const f of status.deleted || []) {
|
|
|
|
if (resolvedPaths.some((p) => f.startsWith(p))) {
|
|
|
|
updatedArtifacts.push({
|
|
|
|
name: '|delete|',
|
|
|
|
contents: f,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
logger.error({ err }, 'Error updating yarn offline packages');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-01 11:37:13 +00:00
|
|
|
// exported for testing
|
|
|
|
export async function updateYarnBinary(
|
|
|
|
lockFileDir: string,
|
|
|
|
updatedArtifacts: UpdatedArtifacts[],
|
|
|
|
existingYarnrcYmlContent: string | undefined
|
|
|
|
): Promise<string | undefined> {
|
|
|
|
let yarnrcYml = existingYarnrcYmlContent;
|
|
|
|
try {
|
|
|
|
const yarnrcYmlFilename = upath.join(lockFileDir, '.yarnrc.yml');
|
|
|
|
yarnrcYml ||= await getFile(yarnrcYmlFilename);
|
|
|
|
const newYarnrcYml = await readLocalFile(yarnrcYmlFilename, 'utf8');
|
|
|
|
if (!is.string(yarnrcYml) || !is.string(newYarnrcYml)) {
|
|
|
|
return existingYarnrcYmlContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
const oldYarnPath = (load(yarnrcYml) as Record<string, string>).yarnPath;
|
|
|
|
const newYarnPath = (load(newYarnrcYml) as Record<string, string>).yarnPath;
|
|
|
|
const oldYarnFullPath = upath.join(lockFileDir, oldYarnPath);
|
|
|
|
const newYarnFullPath = upath.join(lockFileDir, newYarnPath);
|
|
|
|
logger.debug({ oldYarnPath, newYarnPath }, 'Found updated Yarn binary');
|
|
|
|
|
|
|
|
yarnrcYml = yarnrcYml.replace(oldYarnPath, newYarnPath);
|
|
|
|
updatedArtifacts.push(
|
|
|
|
{
|
|
|
|
name: yarnrcYmlFilename,
|
|
|
|
contents: yarnrcYml,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: '|delete|',
|
|
|
|
contents: oldYarnFullPath,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: newYarnFullPath,
|
|
|
|
contents: await readLocalFile(newYarnFullPath, 'utf8'),
|
|
|
|
executable: true,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} catch (err) /* istanbul ignore next */ {
|
|
|
|
logger.error({ err }, 'Error updating Yarn binary');
|
|
|
|
}
|
|
|
|
return existingYarnrcYmlContent && yarnrcYml;
|
|
|
|
}
|
|
|
|
|
2018-05-09 06:03:59 +00:00
|
|
|
// istanbul ignore next
|
2019-07-25 06:17:19 +00:00
|
|
|
export async function getAdditionalFiles(
|
|
|
|
config: PostUpdateConfig,
|
|
|
|
packageFiles: AdditionalPackageFiles
|
|
|
|
): Promise<WriteExistingFilesResult> {
|
2018-05-09 06:03:59 +00:00
|
|
|
logger.trace({ config }, 'getAdditionalFiles');
|
2019-07-25 06:17:19 +00:00
|
|
|
const artifactErrors: ArtifactError[] = [];
|
2020-10-19 21:12:30 +00:00
|
|
|
const updatedArtifacts: UpdatedArtifacts[] = [];
|
2020-08-10 14:18:08 +00:00
|
|
|
if (!packageFiles.npm?.length) {
|
2019-02-08 13:31:30 +00:00
|
|
|
return { artifactErrors, updatedArtifacts };
|
2018-05-11 05:23:26 +00:00
|
|
|
}
|
2018-03-22 09:41:26 +00:00
|
|
|
if (!config.updateLockFiles) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug('Skipping lock file generation');
|
2019-02-08 13:31:30 +00:00
|
|
|
return { artifactErrors, updatedArtifacts };
|
2018-03-22 09:41:26 +00:00
|
|
|
}
|
2021-03-02 21:07:33 +00:00
|
|
|
if (
|
|
|
|
!config.updatedPackageFiles?.length &&
|
2021-05-15 10:13:19 +00:00
|
|
|
config.transitiveRemediation &&
|
|
|
|
config.upgrades?.every(
|
|
|
|
(upgrade) => upgrade.isRemediation || upgrade.isVulnerabilityAlert
|
|
|
|
)
|
2021-03-02 21:07:33 +00:00
|
|
|
) {
|
|
|
|
logger.debug('Skipping lock file generation for remediations');
|
|
|
|
return { artifactErrors, updatedArtifacts };
|
|
|
|
}
|
2021-12-20 05:30:24 +00:00
|
|
|
if (
|
|
|
|
config.reuseExistingBranch &&
|
|
|
|
!config.updatedPackageFiles?.length &&
|
|
|
|
config.upgrades?.every((upgrade) => upgrade.isLockfileUpdate)
|
|
|
|
) {
|
|
|
|
logger.debug('Existing branch contains all necessary lock file updates');
|
|
|
|
return { artifactErrors, updatedArtifacts };
|
|
|
|
}
|
2018-05-11 05:23:26 +00:00
|
|
|
logger.debug('Getting updated lock files');
|
2017-10-19 12:05:10 +00:00
|
|
|
if (
|
2018-07-04 08:11:53 +00:00
|
|
|
config.updateType === 'lockFileMaintenance' &&
|
2020-05-15 10:45:03 +00:00
|
|
|
config.reuseExistingBranch &&
|
2020-08-30 20:03:58 +00:00
|
|
|
branchExists(config.branchName)
|
2017-10-19 12:05:10 +00:00
|
|
|
) {
|
2018-03-16 05:28:46 +00:00
|
|
|
logger.debug('Skipping lockFileMaintenance update');
|
2019-02-08 13:31:30 +00:00
|
|
|
return { artifactErrors, updatedArtifacts };
|
2017-10-19 12:05:10 +00:00
|
|
|
}
|
2019-07-25 06:17:19 +00:00
|
|
|
const dirs = determineLockFileDirs(config, packageFiles);
|
2021-02-24 14:18:43 +00:00
|
|
|
logger.trace({ dirs }, 'lock file dirs');
|
2019-07-25 06:17:19 +00:00
|
|
|
await writeExistingFiles(config, packageFiles);
|
|
|
|
await writeUpdatedPackageFiles(config);
|
2017-08-26 14:10:18 +00:00
|
|
|
|
2021-05-21 20:20:23 +00:00
|
|
|
const { additionalNpmrcContent, additionalYarnRcYml } = processHostRules();
|
2020-03-30 07:04:25 +00:00
|
|
|
|
2021-08-13 11:49:49 +00:00
|
|
|
const env = {
|
|
|
|
...getChildProcessEnv(),
|
|
|
|
NPM_CONFIG_CACHE: await ensureCacheDir('npm'),
|
|
|
|
YARN_CACHE_FOLDER: await ensureCacheDir('yarn'),
|
|
|
|
YARN_GLOBAL_FOLDER: await ensureCacheDir('berry'),
|
|
|
|
npm_config_store: await ensureCacheDir('pnpm'),
|
|
|
|
NODE_ENV: 'dev',
|
|
|
|
};
|
2018-01-25 09:38:30 +00:00
|
|
|
|
2018-09-17 09:18:18 +00:00
|
|
|
let token = '';
|
|
|
|
try {
|
2019-05-24 15:40:39 +00:00
|
|
|
({ token } = hostRules.find({
|
|
|
|
hostType: config.platform,
|
|
|
|
url: 'https://api.github.com/',
|
|
|
|
}));
|
2018-09-17 09:18:18 +00:00
|
|
|
token += '@';
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn({ err }, 'Error getting token for packageFile');
|
|
|
|
}
|
2021-12-17 08:43:33 +00:00
|
|
|
const tokenRe = regEx(`${token}`, 'g', false);
|
2021-11-23 20:10:45 +00:00
|
|
|
const { localDir } = GlobalConfig.get();
|
2021-03-19 15:10:58 +00:00
|
|
|
for (const npmLock of dirs.npmLockDirs) {
|
|
|
|
const lockFileDir = upath.dirname(npmLock);
|
2021-05-26 11:22:16 +00:00
|
|
|
const fullLockFileDir = upath.join(localDir, lockFileDir);
|
2020-03-30 07:04:25 +00:00
|
|
|
const npmrcContent = await getNpmrcContent(fullLockFileDir);
|
|
|
|
await updateNpmrcContent(
|
|
|
|
fullLockFileDir,
|
|
|
|
npmrcContent,
|
|
|
|
additionalNpmrcContent
|
|
|
|
);
|
2021-03-19 15:10:58 +00:00
|
|
|
const fileName = upath.basename(npmLock);
|
2018-05-09 08:42:38 +00:00
|
|
|
logger.debug(`Generating ${fileName} for ${lockFileDir}`);
|
2019-01-24 05:23:08 +00:00
|
|
|
const upgrades = config.upgrades.filter(
|
2021-03-19 15:10:58 +00:00
|
|
|
(upgrade) => upgrade.npmLock === npmLock
|
2019-01-24 05:23:08 +00:00
|
|
|
);
|
2017-10-19 12:05:10 +00:00
|
|
|
const res = await npm.generateLockFile(
|
2020-03-30 07:04:25 +00:00
|
|
|
fullLockFileDir,
|
2018-03-08 08:39:32 +00:00
|
|
|
env,
|
2018-08-15 15:13:07 +00:00
|
|
|
fileName,
|
2019-03-07 15:37:07 +00:00
|
|
|
config,
|
2019-01-24 05:23:08 +00:00
|
|
|
upgrades
|
2017-10-19 12:05:10 +00:00
|
|
|
);
|
|
|
|
if (res.error) {
|
2018-03-21 10:17:54 +00:00
|
|
|
// istanbul ignore if
|
2020-08-10 14:18:08 +00:00
|
|
|
if (res.stderr?.includes('No matching version found for')) {
|
2018-03-21 10:17:54 +00:00
|
|
|
for (const upgrade of config.upgrades) {
|
|
|
|
if (
|
|
|
|
res.stderr.includes(
|
|
|
|
`No matching version found for ${upgrade.depName}`
|
|
|
|
)
|
|
|
|
) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2018-05-28 18:12:17 +00:00
|
|
|
{ dependency: upgrade.depName, type: 'npm' },
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2018-03-21 10:17:54 +00:00
|
|
|
);
|
2020-02-14 08:19:45 +00:00
|
|
|
const err = new Error(
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
|
|
|
);
|
2020-06-22 19:28:02 +00:00
|
|
|
throw new ExternalHostError(err, npmId);
|
2018-03-21 10:17:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-08 13:31:30 +00:00
|
|
|
artifactErrors.push({
|
2021-03-19 15:10:58 +00:00
|
|
|
lockFile: npmLock,
|
2018-07-14 05:50:37 +00:00
|
|
|
stderr: res.stderr,
|
|
|
|
});
|
2017-10-19 12:05:10 +00:00
|
|
|
} else {
|
2020-07-04 12:28:49 +00:00
|
|
|
const existingContent = await getFile(
|
2021-03-19 15:10:58 +00:00
|
|
|
npmLock,
|
2020-05-15 10:45:03 +00:00
|
|
|
config.reuseExistingBranch ? config.branchName : config.baseBranch
|
2017-08-26 14:10:18 +00:00
|
|
|
);
|
2021-03-04 05:21:55 +00:00
|
|
|
if (res.lockFile === existingContent) {
|
2021-03-19 15:10:58 +00:00
|
|
|
logger.debug(`${npmLock} hasn't changed`);
|
2021-03-04 05:21:55 +00:00
|
|
|
} else {
|
2021-03-19 15:10:58 +00:00
|
|
|
logger.debug(`${npmLock} needs updating`);
|
2019-02-08 13:31:30 +00:00
|
|
|
updatedArtifacts.push({
|
2021-03-19 15:10:58 +00:00
|
|
|
name: npmLock,
|
2021-12-17 08:43:33 +00:00
|
|
|
contents: res.lockFile.replace(tokenRe, ''),
|
2017-10-19 12:05:10 +00:00
|
|
|
});
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-30 07:04:25 +00:00
|
|
|
await resetNpmrcContent(fullLockFileDir, npmrcContent);
|
2017-10-19 12:05:10 +00:00
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
|
2021-03-19 15:10:58 +00:00
|
|
|
for (const yarnLock of dirs.yarnLockDirs) {
|
|
|
|
const lockFileDir = upath.dirname(yarnLock);
|
2021-05-26 11:22:16 +00:00
|
|
|
const fullLockFileDir = upath.join(localDir, lockFileDir);
|
2020-03-30 07:04:25 +00:00
|
|
|
const npmrcContent = await getNpmrcContent(fullLockFileDir);
|
|
|
|
await updateNpmrcContent(
|
|
|
|
fullLockFileDir,
|
|
|
|
npmrcContent,
|
|
|
|
additionalNpmrcContent
|
|
|
|
);
|
2021-05-21 20:20:23 +00:00
|
|
|
let yarnRcYmlFilename: string;
|
|
|
|
let existingYarnrcYmlContent: string;
|
|
|
|
if (additionalYarnRcYml) {
|
|
|
|
yarnRcYmlFilename = getSiblingFileName(yarnLock, '.yarnrc.yml');
|
|
|
|
existingYarnrcYmlContent = await readLocalFile(yarnRcYmlFilename, 'utf8');
|
|
|
|
if (existingYarnrcYmlContent) {
|
|
|
|
try {
|
2021-05-26 13:01:09 +00:00
|
|
|
const existingYarnrRcYml = load(existingYarnrcYmlContent) as Record<
|
|
|
|
string,
|
|
|
|
unknown
|
|
|
|
>;
|
2021-05-21 20:20:23 +00:00
|
|
|
const updatedYarnYrcYml = deepmerge(
|
|
|
|
existingYarnrRcYml,
|
|
|
|
additionalYarnRcYml
|
|
|
|
);
|
2021-05-26 13:01:09 +00:00
|
|
|
await writeLocalFile(yarnRcYmlFilename, dump(updatedYarnYrcYml));
|
2021-05-21 20:20:23 +00:00
|
|
|
logger.debug('Added authentication to .yarnrc.yml');
|
|
|
|
} catch (err) {
|
|
|
|
logger.warn({ err }, 'Error appending .yarnrc.yml content');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-19 12:05:10 +00:00
|
|
|
logger.debug(`Generating yarn.lock for ${lockFileDir}`);
|
2017-11-24 06:50:49 +00:00
|
|
|
const lockFileName = upath.join(lockFileDir, 'yarn.lock');
|
2019-01-24 05:23:08 +00:00
|
|
|
const upgrades = config.upgrades.filter(
|
2021-03-19 15:10:58 +00:00
|
|
|
(upgrade) => upgrade.yarnLock === yarnLock
|
2019-01-24 05:23:08 +00:00
|
|
|
);
|
2017-10-19 12:05:10 +00:00
|
|
|
const res = await yarn.generateLockFile(
|
2021-05-26 11:22:16 +00:00
|
|
|
upath.join(localDir, lockFileDir),
|
2018-09-14 18:38:52 +00:00
|
|
|
env,
|
2019-01-24 05:23:08 +00:00
|
|
|
config,
|
|
|
|
upgrades
|
2017-10-19 12:05:10 +00:00
|
|
|
);
|
|
|
|
if (res.error) {
|
2018-03-21 10:17:54 +00:00
|
|
|
// istanbul ignore if
|
2020-08-10 14:18:08 +00:00
|
|
|
if (res.stderr?.includes(`Couldn't find any versions for`)) {
|
2018-03-21 10:17:54 +00:00
|
|
|
for (const upgrade of config.upgrades) {
|
|
|
|
/* eslint-disable no-useless-escape */
|
|
|
|
if (
|
|
|
|
res.stderr.includes(
|
|
|
|
`Couldn't find any versions for \\\"${upgrade.depName}\\\"`
|
|
|
|
)
|
|
|
|
) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2018-05-28 18:12:17 +00:00
|
|
|
{ dependency: upgrade.depName, type: 'yarn' },
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2018-03-21 10:17:54 +00:00
|
|
|
);
|
2020-06-22 19:28:02 +00:00
|
|
|
throw new ExternalHostError(
|
2020-02-14 08:19:45 +00:00
|
|
|
new Error(
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2020-06-22 19:28:02 +00:00
|
|
|
),
|
|
|
|
npmId
|
2020-02-14 08:19:45 +00:00
|
|
|
);
|
2018-03-21 10:17:54 +00:00
|
|
|
}
|
|
|
|
/* eslint-enable no-useless-escape */
|
|
|
|
}
|
|
|
|
}
|
2019-02-08 13:31:30 +00:00
|
|
|
artifactErrors.push({
|
2021-03-19 15:10:58 +00:00
|
|
|
lockFile: yarnLock,
|
2021-11-05 05:21:29 +00:00
|
|
|
stderr: res.stderr || res.stdout,
|
2018-07-14 05:50:37 +00:00
|
|
|
});
|
2017-10-19 12:05:10 +00:00
|
|
|
} else {
|
2020-07-04 12:28:49 +00:00
|
|
|
const existingContent = await getFile(
|
2017-10-19 12:05:10 +00:00
|
|
|
lockFileName,
|
2020-05-15 10:45:03 +00:00
|
|
|
config.reuseExistingBranch ? config.branchName : config.baseBranch
|
2017-08-26 14:10:18 +00:00
|
|
|
);
|
2021-03-04 05:21:55 +00:00
|
|
|
if (res.lockFile === existingContent) {
|
|
|
|
logger.debug("yarn.lock hasn't changed");
|
|
|
|
} else {
|
2017-10-19 12:05:10 +00:00
|
|
|
logger.debug('yarn.lock needs updating');
|
2019-02-08 13:31:30 +00:00
|
|
|
updatedArtifacts.push({
|
2017-10-19 12:05:10 +00:00
|
|
|
name: lockFileName,
|
|
|
|
contents: res.lockFile,
|
|
|
|
});
|
2021-05-26 11:22:16 +00:00
|
|
|
await updateYarnOffline(lockFileDir, localDir, updatedArtifacts);
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2021-11-01 11:37:13 +00:00
|
|
|
|
|
|
|
if (upgrades.some(yarn.isYarnUpdate)) {
|
|
|
|
existingYarnrcYmlContent = await updateYarnBinary(
|
|
|
|
lockFileDir,
|
|
|
|
updatedArtifacts,
|
|
|
|
existingYarnrcYmlContent
|
|
|
|
);
|
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2020-03-30 07:04:25 +00:00
|
|
|
await resetNpmrcContent(fullLockFileDir, npmrcContent);
|
2021-05-21 20:20:23 +00:00
|
|
|
if (existingYarnrcYmlContent) {
|
|
|
|
await writeLocalFile(yarnRcYmlFilename, existingYarnrcYmlContent);
|
|
|
|
}
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|
2018-01-15 15:55:33 +00:00
|
|
|
|
2021-03-19 15:10:58 +00:00
|
|
|
for (const pnpmShrinkwrap of dirs.pnpmShrinkwrapDirs) {
|
|
|
|
const lockFileDir = upath.dirname(pnpmShrinkwrap);
|
2021-05-26 11:22:16 +00:00
|
|
|
const fullLockFileDir = upath.join(localDir, lockFileDir);
|
2020-03-30 07:04:25 +00:00
|
|
|
const npmrcContent = await getNpmrcContent(fullLockFileDir);
|
|
|
|
await updateNpmrcContent(
|
|
|
|
fullLockFileDir,
|
|
|
|
npmrcContent,
|
|
|
|
additionalNpmrcContent
|
|
|
|
);
|
2019-04-26 11:35:37 +00:00
|
|
|
logger.debug(`Generating pnpm-lock.yaml for ${lockFileDir}`);
|
2020-06-03 10:28:37 +00:00
|
|
|
const upgrades = config.upgrades.filter(
|
2021-03-19 15:10:58 +00:00
|
|
|
(upgrade) => upgrade.pnpmShrinkwrap === pnpmShrinkwrap
|
2020-06-03 10:28:37 +00:00
|
|
|
);
|
2018-01-15 15:55:33 +00:00
|
|
|
const res = await pnpm.generateLockFile(
|
2021-05-26 11:22:16 +00:00
|
|
|
upath.join(localDir, lockFileDir),
|
2018-09-14 18:38:52 +00:00
|
|
|
env,
|
2020-06-03 10:28:37 +00:00
|
|
|
config,
|
|
|
|
upgrades
|
2018-01-15 15:55:33 +00:00
|
|
|
);
|
|
|
|
if (res.error) {
|
2018-03-21 10:17:54 +00:00
|
|
|
// istanbul ignore if
|
2020-08-10 14:18:08 +00:00
|
|
|
if (res.stdout?.includes(`No compatible version found:`)) {
|
2018-03-21 10:17:54 +00:00
|
|
|
for (const upgrade of config.upgrades) {
|
|
|
|
if (
|
|
|
|
res.stdout.includes(
|
|
|
|
`No compatible version found: ${upgrade.depName}`
|
|
|
|
)
|
|
|
|
) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2018-05-28 18:12:17 +00:00
|
|
|
{ dependency: upgrade.depName, type: 'pnpm' },
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2018-03-21 10:17:54 +00:00
|
|
|
);
|
2020-06-22 19:28:02 +00:00
|
|
|
throw new ExternalHostError(
|
2020-02-14 08:19:45 +00:00
|
|
|
Error(
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2020-06-22 19:28:02 +00:00
|
|
|
),
|
|
|
|
npmId
|
2020-02-14 08:19:45 +00:00
|
|
|
);
|
2018-03-21 10:17:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-08 13:31:30 +00:00
|
|
|
artifactErrors.push({
|
2021-03-19 15:10:58 +00:00
|
|
|
lockFile: pnpmShrinkwrap,
|
2021-06-02 06:40:54 +00:00
|
|
|
stderr: res.stderr || res.stdout,
|
2018-07-14 05:50:37 +00:00
|
|
|
});
|
2018-01-15 15:55:33 +00:00
|
|
|
} else {
|
2020-07-04 12:28:49 +00:00
|
|
|
const existingContent = await getFile(
|
2021-03-19 15:10:58 +00:00
|
|
|
pnpmShrinkwrap,
|
2020-05-15 10:45:03 +00:00
|
|
|
config.reuseExistingBranch ? config.branchName : config.baseBranch
|
2018-01-15 15:55:33 +00:00
|
|
|
);
|
2021-03-04 05:21:55 +00:00
|
|
|
if (res.lockFile === existingContent) {
|
|
|
|
logger.debug("pnpm-lock.yaml hasn't changed");
|
|
|
|
} else {
|
2019-04-26 11:35:37 +00:00
|
|
|
logger.debug('pnpm-lock.yaml needs updating');
|
2019-02-08 13:31:30 +00:00
|
|
|
updatedArtifacts.push({
|
2021-03-19 15:10:58 +00:00
|
|
|
name: pnpmShrinkwrap,
|
2018-01-15 15:55:33 +00:00
|
|
|
contents: res.lockFile,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2020-03-30 07:04:25 +00:00
|
|
|
await resetNpmrcContent(fullLockFileDir, npmrcContent);
|
2018-01-15 15:55:33 +00:00
|
|
|
}
|
|
|
|
|
2021-03-19 14:33:23 +00:00
|
|
|
for (const lernaJsonFile of dirs.lernaJsonFiles) {
|
2019-07-25 06:17:19 +00:00
|
|
|
let lockFile: string;
|
2021-03-19 14:33:23 +00:00
|
|
|
logger.debug(`Finding package.json for lerna location "${lernaJsonFile}"`);
|
2018-06-28 10:33:45 +00:00
|
|
|
const lernaPackageFile = packageFiles.npm.find(
|
2021-03-19 14:33:23 +00:00
|
|
|
(p) => getSubDirectory(p.packageFile) === getSubDirectory(lernaJsonFile)
|
2018-05-09 07:45:10 +00:00
|
|
|
);
|
2018-06-28 10:33:45 +00:00
|
|
|
if (!lernaPackageFile) {
|
|
|
|
logger.debug('No matching package.json found');
|
|
|
|
throw new Error('lerna-no-lockfile');
|
|
|
|
}
|
2018-06-28 11:41:11 +00:00
|
|
|
if (lernaPackageFile.lernaClient === 'npm') {
|
|
|
|
lockFile = config.npmLock || 'package-lock.json';
|
|
|
|
} else {
|
|
|
|
lockFile = config.yarnLock || 'yarn.lock';
|
|
|
|
}
|
2019-04-25 07:31:09 +00:00
|
|
|
const skipInstalls =
|
|
|
|
lockFile === 'npm-shrinkwrap.json' ? false : config.skipInstalls;
|
2021-03-19 14:33:23 +00:00
|
|
|
const fullLearnaFileDir = upath.join(
|
2021-05-26 11:22:16 +00:00
|
|
|
localDir,
|
2021-03-19 14:33:23 +00:00
|
|
|
getSubDirectory(lernaJsonFile)
|
|
|
|
);
|
2020-03-30 07:04:25 +00:00
|
|
|
const npmrcContent = await getNpmrcContent(fullLearnaFileDir);
|
|
|
|
await updateNpmrcContent(
|
|
|
|
fullLearnaFileDir,
|
|
|
|
npmrcContent,
|
|
|
|
additionalNpmrcContent
|
|
|
|
);
|
2018-05-09 07:45:10 +00:00
|
|
|
const res = await lerna.generateLockFiles(
|
2020-07-18 14:40:35 +00:00
|
|
|
lernaPackageFile,
|
2020-03-30 07:04:25 +00:00
|
|
|
fullLearnaFileDir,
|
2020-04-13 05:43:39 +00:00
|
|
|
config,
|
2018-08-15 15:13:07 +00:00
|
|
|
env,
|
2020-04-13 05:43:39 +00:00
|
|
|
skipInstalls
|
2018-05-09 07:45:10 +00:00
|
|
|
);
|
2018-02-05 19:06:24 +00:00
|
|
|
// istanbul ignore else
|
2020-03-09 19:34:28 +00:00
|
|
|
if (res.stderr) {
|
2018-02-27 18:05:00 +00:00
|
|
|
// istanbul ignore if
|
2020-03-09 19:34:28 +00:00
|
|
|
if (res.stderr.includes('ENOSPC: no space left on device')) {
|
2020-01-12 07:50:11 +00:00
|
|
|
throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);
|
2018-02-27 18:05:00 +00:00
|
|
|
}
|
2018-05-28 16:47:58 +00:00
|
|
|
for (const upgrade of config.upgrades) {
|
|
|
|
/* eslint-disable no-useless-escape */
|
|
|
|
if (
|
|
|
|
res.stderr.includes(
|
|
|
|
`Couldn't find any versions for \\\"${upgrade.depName}\\\"`
|
|
|
|
)
|
|
|
|
) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2018-05-28 18:12:17 +00:00
|
|
|
{ dependency: upgrade.depName, type: 'yarn' },
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2018-05-28 16:47:58 +00:00
|
|
|
);
|
2020-06-22 19:28:02 +00:00
|
|
|
throw new ExternalHostError(
|
2020-02-14 08:19:45 +00:00
|
|
|
Error(
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2020-06-22 19:28:02 +00:00
|
|
|
),
|
|
|
|
npmId
|
2020-02-14 08:19:45 +00:00
|
|
|
);
|
2018-05-28 16:47:58 +00:00
|
|
|
}
|
|
|
|
/* eslint-enable no-useless-escape */
|
|
|
|
if (
|
|
|
|
res.stderr.includes(
|
|
|
|
`No matching version found for ${upgrade.depName}`
|
|
|
|
)
|
|
|
|
) {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2018-05-28 18:12:17 +00:00
|
|
|
{ dependency: upgrade.depName, type: 'npm' },
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2018-05-28 16:47:58 +00:00
|
|
|
);
|
2020-06-22 19:28:02 +00:00
|
|
|
throw new ExternalHostError(
|
2020-02-14 08:19:45 +00:00
|
|
|
Error(
|
|
|
|
'lock file failed for the dependency being updated - skipping branch creation'
|
2020-06-22 19:28:02 +00:00
|
|
|
),
|
|
|
|
npmId
|
2020-02-14 08:19:45 +00:00
|
|
|
);
|
2018-05-28 16:47:58 +00:00
|
|
|
}
|
|
|
|
}
|
2019-02-08 13:31:30 +00:00
|
|
|
artifactErrors.push({
|
2018-07-14 05:50:37 +00:00
|
|
|
lockFile,
|
|
|
|
stderr: res.stderr,
|
|
|
|
});
|
2018-02-05 19:06:24 +00:00
|
|
|
} else {
|
2018-05-09 06:03:59 +00:00
|
|
|
for (const packageFile of packageFiles.npm) {
|
2018-09-14 04:07:53 +00:00
|
|
|
const filename = packageFile.npmLock || packageFile.yarnLock;
|
2018-05-28 20:25:33 +00:00
|
|
|
logger.trace('Checking for ' + filename);
|
2020-07-04 12:28:49 +00:00
|
|
|
const existingContent = await getFile(
|
2018-02-05 19:06:24 +00:00
|
|
|
filename,
|
2020-05-15 10:45:03 +00:00
|
|
|
config.reuseExistingBranch ? config.branchName : config.baseBranch
|
2018-02-05 19:06:24 +00:00
|
|
|
);
|
|
|
|
if (existingContent) {
|
2018-05-28 20:25:33 +00:00
|
|
|
logger.trace('Found lock file');
|
2021-05-26 11:22:16 +00:00
|
|
|
const lockFilePath = upath.join(localDir, filename);
|
2018-05-28 20:25:33 +00:00
|
|
|
logger.trace('Checking against ' + lockFilePath);
|
2018-02-20 08:26:47 +00:00
|
|
|
try {
|
2019-07-25 06:17:19 +00:00
|
|
|
let newContent: string;
|
2019-04-28 08:51:21 +00:00
|
|
|
try {
|
2020-07-04 10:47:52 +00:00
|
|
|
newContent = await readFile(lockFilePath, 'utf8');
|
2019-04-28 08:51:21 +00:00
|
|
|
} catch (err) {
|
2020-07-04 10:47:52 +00:00
|
|
|
newContent = await readFile(
|
2019-07-24 08:29:48 +00:00
|
|
|
lockFilePath.replace(
|
|
|
|
'npm-shrinkwrap.json',
|
|
|
|
'package-lock.json'
|
|
|
|
),
|
|
|
|
'utf8'
|
2019-04-28 08:51:21 +00:00
|
|
|
);
|
|
|
|
}
|
2021-03-04 05:21:55 +00:00
|
|
|
if (newContent === existingContent) {
|
|
|
|
logger.trace('File is unchanged');
|
|
|
|
} else {
|
2018-05-28 20:25:33 +00:00
|
|
|
logger.debug('File is updated: ' + lockFilePath);
|
2019-02-08 13:31:30 +00:00
|
|
|
updatedArtifacts.push({
|
2018-02-20 08:26:47 +00:00
|
|
|
name: filename,
|
|
|
|
contents: newContent,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (err) {
|
2019-02-13 15:50:17 +00:00
|
|
|
if (config.updateType === 'lockFileMaintenance') {
|
2020-02-24 07:43:01 +00:00
|
|
|
logger.debug(
|
2019-04-28 08:51:21 +00:00
|
|
|
{ packageFile, lockFilePath },
|
2019-04-24 13:47:06 +00:00
|
|
|
'No lock file found after lerna lockFileMaintenance'
|
2019-02-13 15:50:17 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
logger.warn(
|
2019-04-28 08:51:21 +00:00
|
|
|
{ packageFile, lockFilePath },
|
2019-02-13 15:50:17 +00:00
|
|
|
'No lock file found after lerna bootstrap'
|
|
|
|
);
|
|
|
|
}
|
2018-02-05 19:06:24 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-05-28 20:25:33 +00:00
|
|
|
logger.trace('No lock file found');
|
2018-02-05 19:06:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-30 07:04:25 +00:00
|
|
|
await resetNpmrcContent(fullLearnaFileDir, npmrcContent);
|
2018-02-05 19:06:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 13:31:30 +00:00
|
|
|
return { artifactErrors, updatedArtifacts };
|
2017-08-26 14:10:18 +00:00
|
|
|
}
|