UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

216 lines • 9.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateLockFile = generateLockFile; exports.getConstraintFromLockFile = getConstraintFromLockFile; const tslib_1 = require("tslib"); const is_1 = tslib_1.__importDefault(require("@sindresorhus/is")); const shlex_1 = require("shlex"); const upath_1 = tslib_1.__importDefault(require("upath")); const global_1 = require("../../../../config/global"); const error_messages_1 = require("../../../../constants/error-messages"); const logger_1 = require("../../../../logger"); const exec_1 = require("../../../../util/exec"); const fs_1 = require("../../../../util/fs"); const string_1 = require("../../../../util/string"); const yaml_1 = require("../../../../util/yaml"); const constants_1 = require("../constants"); const node_version_1 = require("./node-version"); const utils_1 = require("./utils"); function getPnpmConstraintFromUpgrades(upgrades) { for (const upgrade of upgrades) { if (upgrade.depName === 'pnpm' && upgrade.newVersion) { return upgrade.newVersion; } } return null; } async function generateLockFile(lockFileDir, env, config, upgrades = []) { const lockFileName = upath_1.default.join(lockFileDir, 'pnpm-lock.yaml'); logger_1.logger.debug(`Spawning pnpm install to create ${lockFileName}`); let lockFile = null; let stdout; let stderr; const commands = []; try { const lazyPgkJson = (0, utils_1.lazyLoadPackageJson)(lockFileDir); const pnpmToolConstraint = { toolName: 'pnpm', constraint: getPnpmConstraintFromUpgrades(upgrades) ?? // if pnpm is being upgraded, it comes first config.constraints?.pnpm ?? // from user config or extraction (0, utils_1.getPackageManagerVersion)('pnpm', await lazyPgkJson.getValue()) ?? // look in package.json > packageManager or engines (await getConstraintFromLockFile(lockFileName)), // use lockfileVersion to find pnpm version range }; const pnpmConfigCacheDir = await (0, fs_1.ensureCacheDir)(constants_1.PNPM_CACHE_DIR); const pnpmConfigStoreDir = await (0, fs_1.ensureCacheDir)(constants_1.PNPM_STORE_DIR); const extraEnv = { // those arwe no longer working and it's unclear if they ever worked NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE, npm_config_store: env.npm_config_store, // these are used by pnpm v5 to v10. Maybe earlier versions too npm_config_cache_dir: pnpmConfigCacheDir, npm_config_store_dir: pnpmConfigStoreDir, // pnpm stops reading npm_config_* env vars since v11 pnpm_config_cache_dir: pnpmConfigCacheDir, pnpm_config_store_dir: pnpmConfigStoreDir, }; const execOptions = { cwdFile: lockFileName, extraEnv, docker: {}, toolConstraints: [ await (0, node_version_1.getNodeToolConstraint)(config, upgrades, lockFileDir, lazyPgkJson), pnpmToolConstraint, ], }; /* v8 ignore next 4 -- needs test */ if (global_1.GlobalConfig.get('exposeAllEnv')) { extraEnv.NPM_AUTH = env.NPM_AUTH; extraEnv.NPM_EMAIL = env.NPM_EMAIL; } const pnpmWorkspaceFilePath = (0, fs_1.getSiblingFileName)(lockFileName, 'pnpm-workspace.yaml'); let args = '--lockfile-only'; // If it's not a workspaces project/monorepo, but single project with unrelated other npm project in source tree (for example, a git submodule), // `--recursive` will install un-wanted project. // we should avoid this. if (await (0, fs_1.localPathExists)(pnpmWorkspaceFilePath)) { const pnpmWorkspace = (0, yaml_1.parseSingleYaml)((await (0, fs_1.readLocalFile)(pnpmWorkspaceFilePath, 'utf8'))); if (pnpmWorkspace?.packages?.length) { logger_1.logger.debug(`Found pnpm workspace with ${pnpmWorkspace.packages.length} package definitions`); // we are in a monorepo, 'pnpm update' needs the '--recursive' flag contrary to 'pnpm install' args += ' --recursive'; } } if (!global_1.GlobalConfig.get('allowScripts') || config.ignoreScripts) { args += ' --ignore-scripts'; args += ' --ignore-pnpmfile'; } logger_1.logger.trace({ args }, 'pnpm command options'); const lockUpdates = upgrades.filter((upgrade) => upgrade.isLockfileUpdate); if (lockUpdates.length !== upgrades.length) { // This command updates the lock file based on package.json commands.push(`pnpm install ${args}`); } // rangeStrategy = update-lockfile if (lockUpdates.length) { logger_1.logger.debug('Performing lockfileUpdate (pnpm)'); commands.push(`pnpm update --no-save ${lockUpdates // TODO: types (#22198) .map((update) => `${update.packageName}@${update.newVersion}`) .filter(string_1.uniqueStrings) .map(shlex_1.quote) .join(' ')} ${args}`); } // postUpdateOptions if (config.postUpdateOptions?.includes('pnpmDedupe')) { commands.push('pnpm dedupe --ignore-scripts'); } if (upgrades.find((upgrade) => upgrade.isLockFileMaintenance)) { logger_1.logger.debug(`Removing ${lockFileName} first due to lock file maintenance upgrade`); try { await (0, fs_1.deleteLocalFile)(lockFileName); /* v8 ignore start -- needs test */ } catch (err) { logger_1.logger.debug({ err, lockFileName }, 'Error removing `pnpm-lock.yaml` for lock file maintenance'); } /* v8 ignore stop -- needs test */ } await (0, exec_1.exec)(commands, execOptions); lockFile = await (0, fs_1.readLocalFile)(lockFileName, 'utf8'); /* v8 ignore start -- needs test */ } catch (err) { if (err.message === error_messages_1.TEMPORARY_ERROR) { throw err; } logger_1.logger.debug({ commands, err, stdout, stderr, type: 'pnpm', }, 'lock file error'); return { error: true, stderr: err.stderr, stdout: err.stdout }; } /* v8 ignore stop -- needs test */ return { lockFile }; } async function getConstraintFromLockFile(lockFileName) { let constraint = null; try { const lockfileContent = await (0, fs_1.readLocalFile)(lockFileName, 'utf8'); if (!lockfileContent) { logger_1.logger.trace(`Empty pnpm lock file: ${lockFileName}`); return null; } // TODO: use schema (#9610) const pnpmLock = (0, yaml_1.parseSingleYaml)(lockfileContent); if (!is_1.default.number(pnpmLock?.lockfileVersion) && !is_1.default.numericString(pnpmLock?.lockfileVersion)) { logger_1.logger.trace(`Invalid pnpm lockfile version: ${lockFileName}`); return null; } // find matching lockfileVersion and use its constraints // if no match found use lockfileVersion 5 // lockfileVersion 5 is the minimum version required to generate the pnpm-lock.yaml file const { lowerConstraint, upperConstraint } = lockToPnpmVersionMapping.find((m) => m.lockfileVersion === pnpmLock.lockfileVersion) ?? { lockfileVersion: 5.0, lowerConstraint: '>=3', upperConstraint: '<3.5.0', }; constraint = lowerConstraint; if (upperConstraint) { constraint += ` ${upperConstraint}`; } } catch (err) { logger_1.logger.warn({ err }, 'Error getting pnpm constraints from lock file'); } return constraint; } /** * pnpm lockfiles have corresponding version numbers called "lockfileVersion" * each lockfileVersion can only be generated by a certain pnpm version range * eg. lockfileVersion: 5.4 can only be generated by pnpm version >=7 && <8 * official list can be found here : https://github.com/pnpm/spec/tree/master/lockfile * we use the mapping present below to find the compatible pnpm version range for a given lockfileVersion * * the various terms used in the mapping are explained below: * lowerConstraint : lowest pnpm version that can generate the lockfileVersion * upperConstraint : highest pnpm version that can generate the lockfileVersion * lowerBound : highest pnpm version that is less than the lowerConstraint * upperBound : lowest pnpm version that is greater than the upperConstraint * * To handle future lockfileVersions, we need to: * 1. add a upperBound and upperConstraint to the current latest lockfileVersion * 2. add an object for the new lockfileVersion with lowerBound and lowerConstraint * * lockfileVersion from v6 on are strings */ const lockToPnpmVersionMapping = [ { lockfileVersion: '9.0', lowerConstraint: '>=9' }, { lockfileVersion: '6.0', lowerConstraint: '>=7.24.2', upperConstraint: '<9', }, { lockfileVersion: 5.4, lowerConstraint: '>=7', upperConstraint: '<8', }, { lockfileVersion: 5.3, lowerConstraint: '>=6', upperConstraint: '<7', }, { lockfileVersion: 5.2, lowerConstraint: '>=5.10.0', upperConstraint: '<6', }, { lockfileVersion: 5.1, lowerConstraint: '>=3.5.0', upperConstraint: '<5.9.3', }, ]; //# sourceMappingURL=pnpm.js.map