mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
refactor(manager): final strict null checks (#15185)
* refactor(manager): final strict null checks * refactor: fix type issues * test: fix mocking
This commit is contained in:
parent
1c0073d9a9
commit
868ebbef63
34 changed files with 337 additions and 254 deletions
|
@ -7,6 +7,8 @@ const lockFileContent = loadFixture('Gemfile.rubyci.lock');
|
|||
describe('modules/manager/bundler/update-locked', () => {
|
||||
it('detects already updated', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile: 'Gemfile',
|
||||
lockFile: 'Gemfile.lock',
|
||||
lockFileContent,
|
||||
depName: 'activejob',
|
||||
newVersion: '5.2.3',
|
||||
|
@ -16,6 +18,8 @@ describe('modules/manager/bundler/update-locked', () => {
|
|||
|
||||
it('returns unsupported', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile: 'Gemfile',
|
||||
lockFile: 'Gemfile.lock',
|
||||
lockFileContent,
|
||||
depName: 'activejob',
|
||||
newVersion: '5.2.0',
|
||||
|
|
|
@ -2,11 +2,15 @@ import { loadFixture } from '../../../../test/util';
|
|||
import type { UpdateLockedConfig } from '../types';
|
||||
import { updateLockedDependency } from '.';
|
||||
|
||||
const lockFile = 'compose.lock';
|
||||
|
||||
const lockFileContent = loadFixture('composer5.lock');
|
||||
|
||||
describe('modules/manager/composer/update-locked', () => {
|
||||
it('detects already updated', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile: 'composer.json',
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
depName: 'awesome/git',
|
||||
newVersion: '1.2.0',
|
||||
|
@ -16,6 +20,8 @@ describe('modules/manager/composer/update-locked', () => {
|
|||
|
||||
it('returns unsupported', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile: 'composer.json',
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
depName: 'awesome/git',
|
||||
newVersion: '1.0.0',
|
||||
|
|
|
@ -17,7 +17,7 @@ const languageList = Object.values(ProgrammingLanguage);
|
|||
export function get<T extends keyof ManagerApi>(
|
||||
manager: string,
|
||||
name: T
|
||||
): ManagerApi[T] | null {
|
||||
): ManagerApi[T] | undefined {
|
||||
return managers.get(manager)?.[name];
|
||||
}
|
||||
export const getLanguageList = (): string[] => languageList;
|
||||
|
@ -27,7 +27,7 @@ export const getManagers = (): Map<string, ManagerApi> => managers;
|
|||
export async function detectAllGlobalConfig(): Promise<GlobalManagerConfig> {
|
||||
let config: GlobalManagerConfig = {};
|
||||
for (const managerName of managerList) {
|
||||
const manager = managers.get(managerName);
|
||||
const manager = managers.get(managerName)!;
|
||||
if (manager.detectGlobalConfig) {
|
||||
// This should use mergeChildConfig once more than one manager is supported, but introduces a cyclic dependency
|
||||
config = { ...config, ...(await manager.detectGlobalConfig()) };
|
||||
|
@ -44,7 +44,7 @@ export async function extractAllPackageFiles(
|
|||
if (!managers.has(manager)) {
|
||||
return null;
|
||||
}
|
||||
const m = managers.get(manager);
|
||||
const m = managers.get(manager)!;
|
||||
if (m.extractAllPackageFiles) {
|
||||
const res = await m.extractAllPackageFiles(config, files);
|
||||
// istanbul ignore if
|
||||
|
@ -65,18 +65,18 @@ export function extractPackageFile(
|
|||
if (!managers.has(manager)) {
|
||||
return null;
|
||||
}
|
||||
const m = managers.get(manager);
|
||||
const m = managers.get(manager)!;
|
||||
return m.extractPackageFile
|
||||
? m.extractPackageFile(content, fileName, config)
|
||||
: null;
|
||||
}
|
||||
|
||||
export function getRangeStrategy(config: RangeConfig): RangeStrategy {
|
||||
export function getRangeStrategy(config: RangeConfig): RangeStrategy | null {
|
||||
const { manager, rangeStrategy } = config;
|
||||
if (!managers.has(manager)) {
|
||||
if (!manager || !managers.has(manager)) {
|
||||
return null;
|
||||
}
|
||||
const m = managers.get(manager);
|
||||
const m = managers.get(manager)!;
|
||||
if (m.getRangeStrategy) {
|
||||
// Use manager's own function if it exists
|
||||
const managerRangeStrategy = m.getRangeStrategy(config);
|
||||
|
|
|
@ -66,7 +66,7 @@ export async function extractPackageFile(
|
|||
`npm file ${fileName} has name ${JSON.stringify(packageJsonName)}`
|
||||
);
|
||||
const packageFileVersion = packageJson.version;
|
||||
let yarnWorkspacesPackages: string[];
|
||||
let yarnWorkspacesPackages: string[] | undefined;
|
||||
if (is.array(packageJson.workspaces)) {
|
||||
yarnWorkspacesPackages = packageJson.workspaces;
|
||||
} else {
|
||||
|
@ -83,7 +83,10 @@ export async function extractPackageFile(
|
|||
pnpmShrinkwrap: 'pnpm-lock.yaml',
|
||||
};
|
||||
|
||||
for (const [key, val] of Object.entries(lockFiles)) {
|
||||
for (const [key, val] of Object.entries(lockFiles) as [
|
||||
'yarnLock' | 'packageLock' | 'shrinkwrapJson' | 'pnpmShrinkwrap',
|
||||
string
|
||||
][]) {
|
||||
const filePath = getSiblingFileName(fileName, val);
|
||||
if (await readLocalFile(filePath, 'utf8')) {
|
||||
lockFiles[key] = filePath;
|
||||
|
@ -95,7 +98,7 @@ export async function extractPackageFile(
|
|||
delete lockFiles.packageLock;
|
||||
delete lockFiles.shrinkwrapJson;
|
||||
|
||||
let npmrc: string;
|
||||
let npmrc: string | undefined;
|
||||
const npmrcFileName = getSiblingFileName(fileName, '.npmrc');
|
||||
let repoNpmrc = await readLocalFile(npmrcFileName, 'utf8');
|
||||
if (is.string(repoNpmrc)) {
|
||||
|
@ -135,15 +138,17 @@ export async function extractPackageFile(
|
|||
const yarnrcYmlFileName = getSiblingFileName(fileName, '.yarnrc.yml');
|
||||
const yarnZeroInstall = await isZeroInstall(yarnrcYmlFileName);
|
||||
|
||||
let lernaJsonFile: string;
|
||||
let lernaPackages: string[];
|
||||
let lernaClient: 'yarn' | 'npm';
|
||||
let lernaJsonFile: string | undefined;
|
||||
let lernaPackages: string[] | undefined;
|
||||
let lernaClient: 'yarn' | 'npm' | undefined;
|
||||
let hasFancyRefs = false;
|
||||
let lernaJson: {
|
||||
packages: string[];
|
||||
npmClient: string;
|
||||
useWorkspaces?: boolean;
|
||||
};
|
||||
let lernaJson:
|
||||
| {
|
||||
packages: string[];
|
||||
npmClient: string;
|
||||
useWorkspaces?: boolean;
|
||||
}
|
||||
| undefined;
|
||||
try {
|
||||
lernaJsonFile = getSiblingFileName(fileName, 'lerna.json');
|
||||
lernaJson = JSON.parse(await readLocalFile(lernaJsonFile, 'utf8'));
|
||||
|
@ -332,14 +337,16 @@ export async function extractPackageFile(
|
|||
return dep;
|
||||
}
|
||||
|
||||
for (const depType of Object.keys(depTypes)) {
|
||||
for (const depType of Object.keys(depTypes) as (keyof typeof depTypes)[]) {
|
||||
let dependencies = packageJson[depType];
|
||||
if (dependencies) {
|
||||
try {
|
||||
if (depType === 'packageManager') {
|
||||
const match = regEx('^(?<name>.+)@(?<range>.+)$').exec(dependencies);
|
||||
const match = regEx('^(?<name>.+)@(?<range>.+)$').exec(
|
||||
dependencies as string
|
||||
);
|
||||
// istanbul ignore next
|
||||
if (!match) {
|
||||
if (!match?.groups) {
|
||||
break;
|
||||
}
|
||||
dependencies = { [match.groups.name]: match.groups.range };
|
||||
|
@ -446,6 +453,6 @@ export async function extractAllPackageFiles(
|
|||
logger.debug({ packageFile }, 'packageFile has no content');
|
||||
}
|
||||
}
|
||||
await postExtract(npmFiles, config.updateInternalDeps);
|
||||
await postExtract(npmFiles, !!config.updateInternalDeps);
|
||||
return npmFiles;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ export async function getLockedVersions(
|
|||
logger.debug('Finding locked versions');
|
||||
for (const packageFile of packageFiles) {
|
||||
const { yarnLock, npmLock, pnpmShrinkwrap } = packageFile;
|
||||
const lockFiles = [];
|
||||
const lockFiles: string[] = [];
|
||||
if (yarnLock) {
|
||||
logger.trace('Found yarnLock');
|
||||
lockFiles.push(yarnLock);
|
||||
|
@ -22,14 +22,17 @@ export async function getLockedVersions(
|
|||
}
|
||||
const { lockfileVersion, isYarn1 } = lockFileCache[yarnLock];
|
||||
if (!isYarn1) {
|
||||
if (lockfileVersion >= 8) {
|
||||
if (lockfileVersion && lockfileVersion >= 8) {
|
||||
// https://github.com/yarnpkg/berry/commit/9bcd27ae34aee77a567dd104947407532fa179b3
|
||||
packageFile.constraints.yarn = '^3.0.0';
|
||||
} else if (lockfileVersion >= 6) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageFile.constraints!.yarn = '^3.0.0';
|
||||
} else if (lockfileVersion && lockfileVersion >= 6) {
|
||||
// https://github.com/yarnpkg/berry/commit/f753790380cbda5b55d028ea84b199445129f9ba
|
||||
packageFile.constraints.yarn = '^2.2.0';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageFile.constraints!.yarn = '^2.2.0';
|
||||
} else {
|
||||
packageFile.constraints.yarn = '^2.0.0';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageFile.constraints!.yarn = '^2.0.0';
|
||||
}
|
||||
}
|
||||
for (const dep of packageFile.deps) {
|
||||
|
@ -54,18 +57,20 @@ export async function getLockedVersions(
|
|||
}
|
||||
const { lockfileVersion } = lockFileCache[npmLock];
|
||||
if (lockfileVersion === 1) {
|
||||
if (packageFile.constraints.npm) {
|
||||
if (packageFile.constraints?.npm) {
|
||||
// Add a <7 constraint if it's not already a fixed version
|
||||
if (!semver.valid(packageFile.constraints.npm)) {
|
||||
packageFile.constraints.npm += ' <7';
|
||||
}
|
||||
} else {
|
||||
packageFile.constraints.npm = '<7';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageFile.constraints!.npm = '<7';
|
||||
}
|
||||
}
|
||||
for (const dep of packageFile.deps) {
|
||||
dep.lockedVersion = semver.valid(
|
||||
lockFileCache[npmLock].lockedVersions[dep.depName]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
lockFileCache[npmLock].lockedVersions[dep.depName!]
|
||||
);
|
||||
}
|
||||
} else if (pnpmShrinkwrap) {
|
||||
|
|
|
@ -28,10 +28,13 @@ export async function detectMonorepos(
|
|||
if (packages?.length) {
|
||||
const internalPackagePatterns = (
|
||||
is.array(packages) ? packages : [packages]
|
||||
).map((pattern) => getSiblingFileName(packageFile, pattern));
|
||||
)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
.map((pattern) => getSiblingFileName(packageFile!, pattern));
|
||||
const internalPackageFiles = packageFiles.filter((sp) =>
|
||||
matchesAnyPattern(
|
||||
getSubDirectory(sp.packageFile),
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
getSubDirectory(sp.packageFile!),
|
||||
internalPackagePatterns
|
||||
)
|
||||
);
|
||||
|
|
|
@ -24,7 +24,7 @@ describe('modules/manager/npm/extract/pnpm', () => {
|
|||
'..'
|
||||
);
|
||||
const res = await extractPnpmFilters(workSpaceFilePath);
|
||||
expect(res).toBeNull();
|
||||
expect(res).toBeUndefined();
|
||||
expect(logger.logger.trace).toHaveBeenCalledWith(
|
||||
{
|
||||
fileName: expect.any(String),
|
||||
|
@ -39,7 +39,7 @@ describe('modules/manager/npm/extract/pnpm', () => {
|
|||
});
|
||||
|
||||
const res = await extractPnpmFilters('pnpm-workspace.yml');
|
||||
expect(res).toBeNull();
|
||||
expect(res).toBeUndefined();
|
||||
expect(logger.logger.trace).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fileName: expect.any(String),
|
||||
|
|
|
@ -15,7 +15,7 @@ import type { PnpmWorkspaceFile } from './types';
|
|||
|
||||
export async function extractPnpmFilters(
|
||||
fileName: string
|
||||
): Promise<string[] | null> {
|
||||
): Promise<string[] | undefined> {
|
||||
try {
|
||||
const contents = load(await readLocalFile(fileName, 'utf8'), {
|
||||
json: true,
|
||||
|
@ -28,12 +28,12 @@ export async function extractPnpmFilters(
|
|||
{ fileName },
|
||||
'Failed to find required "packages" array in pnpm-workspace.yaml'
|
||||
);
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
return contents.packages;
|
||||
} catch (err) {
|
||||
logger.trace({ fileName, err }, 'Failed to parse pnpm-workspace.yaml');
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,8 @@ export async function detectPnpmWorkspaces(
|
|||
}
|
||||
|
||||
// search for corresponding pnpm workspace
|
||||
const pnpmWorkspace = await findPnpmWorkspace(packageFile);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
const pnpmWorkspace = await findPnpmWorkspace(packageFile!);
|
||||
if (pnpmWorkspace === null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -113,7 +114,8 @@ export async function detectPnpmWorkspaces(
|
|||
const packagePaths = packagePathCache.get(workspaceYamlPath);
|
||||
|
||||
const isPackageInWorkspace = packagePaths?.some((p) =>
|
||||
p.endsWith(packageFile)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
p.endsWith(packageFile!)
|
||||
);
|
||||
|
||||
if (isPackageInWorkspace) {
|
||||
|
|
|
@ -13,6 +13,8 @@ export interface NpmPackage extends PackageJson {
|
|||
_id?: any;
|
||||
dependenciesMeta?: DependenciesMeta;
|
||||
packageManager?: string;
|
||||
|
||||
volta?: PackageJson.Dependency;
|
||||
}
|
||||
|
||||
export type LockFileEntry = Record<
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function getYarnLock(filePath: string): Promise<LockFile> {
|
|||
try {
|
||||
const parsed = parseSyml(yarnLockRaw);
|
||||
const lockedVersions: Record<string, string> = {};
|
||||
let lockfileVersion: number;
|
||||
let lockfileVersion: number | undefined;
|
||||
|
||||
for (const [key, val] of Object.entries(parsed)) {
|
||||
if (key === '__metadata') {
|
||||
|
|
|
@ -29,6 +29,7 @@ import { ensureTrailingSlash } from '../../../../util/url';
|
|||
import { NpmDatasource } from '../../../datasource/npm';
|
||||
import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types';
|
||||
import { getZeroInstallPaths } from '../extract/yarn';
|
||||
import type { NpmDepType } from '../types';
|
||||
import { composeLockFile, parseLockFile } from '../utils';
|
||||
import * as lerna from './lerna';
|
||||
import * as npm from './npm';
|
||||
|
@ -44,18 +45,18 @@ import * as yarn from './yarn';
|
|||
|
||||
// Strips empty values, deduplicates, and returns the directories from filenames
|
||||
// istanbul ignore next
|
||||
const getDirs = (arr: string[]): string[] =>
|
||||
Array.from(new Set(arr.filter(Boolean)));
|
||||
const getDirs = (arr: (string | null | undefined)[]): string[] =>
|
||||
Array.from(new Set(arr.filter(is.string)));
|
||||
|
||||
// istanbul ignore next
|
||||
export function determineLockFileDirs(
|
||||
config: PostUpdateConfig,
|
||||
packageFiles: AdditionalPackageFiles
|
||||
): DetermineLockFileDirsResult {
|
||||
const npmLockDirs = [];
|
||||
const yarnLockDirs = [];
|
||||
const pnpmShrinkwrapDirs = [];
|
||||
const lernaJsonFiles = [];
|
||||
const npmLockDirs: (string | undefined)[] = [];
|
||||
const yarnLockDirs: (string | undefined)[] = [];
|
||||
const pnpmShrinkwrapDirs: (string | undefined)[] = [];
|
||||
const lernaJsonFiles: (string | undefined)[] = [];
|
||||
|
||||
for (const upgrade of config.upgrades) {
|
||||
if (upgrade.updateType === 'lockFileMaintenance' || upgrade.isRemediation) {
|
||||
|
@ -91,7 +92,8 @@ export function determineLockFileDirs(
|
|||
|
||||
function getPackageFile(fileName: string): Partial<PackageFile> {
|
||||
logger.trace('Looking for packageFile: ' + fileName);
|
||||
for (const packageFile of packageFiles.npm) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
for (const packageFile of packageFiles.npm!) {
|
||||
if (packageFile.packageFile === fileName) {
|
||||
logger.trace({ packageFile }, 'Found packageFile');
|
||||
return packageFile;
|
||||
|
@ -101,7 +103,8 @@ export function determineLockFileDirs(
|
|||
return {};
|
||||
}
|
||||
|
||||
for (const p of config.updatedPackageFiles) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
for (const p of config.updatedPackageFiles!) {
|
||||
logger.trace(`Checking ${String(p.path)} for lock files`);
|
||||
const packageFile = getPackageFile(p.path);
|
||||
// lerna first
|
||||
|
@ -147,7 +150,8 @@ export async function writeExistingFiles(
|
|||
for (const packageFile of npmFiles) {
|
||||
const basedir = upath.join(
|
||||
localDir,
|
||||
upath.dirname(packageFile.packageFile)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
upath.dirname(packageFile.packageFile!)
|
||||
);
|
||||
const npmrc: string = packageFile.npmrc || config.npmrc;
|
||||
const npmrcFilename = upath.join(basedir, '.npmrc');
|
||||
|
@ -171,9 +175,10 @@ export async function writeExistingFiles(
|
|||
logger.debug(`Writing ${npmLock}`);
|
||||
let existingNpmLock: string;
|
||||
try {
|
||||
existingNpmLock = await getFile(npmLock);
|
||||
existingNpmLock = (await getFile(npmLock)) ?? '';
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'Error reading npm lock file');
|
||||
existingNpmLock = '';
|
||||
}
|
||||
const { detectedIndent, lockFileParsed: npmLockParsed } =
|
||||
parseLockFile(existingNpmLock);
|
||||
|
@ -182,14 +187,15 @@ export async function writeExistingFiles(
|
|||
'packages' in npmLockParsed
|
||||
? Object.keys(npmLockParsed.packages)
|
||||
: [];
|
||||
const widens = [];
|
||||
const widens: string[] = [];
|
||||
let lockFileChanged = false;
|
||||
for (const upgrade of config.upgrades) {
|
||||
if (
|
||||
upgrade.rangeStrategy === 'widen' &&
|
||||
upgrade.npmLock === npmLock
|
||||
) {
|
||||
widens.push(upgrade.depName);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
widens.push(upgrade.depName!);
|
||||
}
|
||||
const { depName } = upgrade;
|
||||
for (const packageName of packageNames) {
|
||||
|
@ -215,7 +221,8 @@ export async function writeExistingFiles(
|
|||
npmLockParsed.dependencies
|
||||
) {
|
||||
widens.forEach((depName) => {
|
||||
delete npmLockParsed.dependencies[depName];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
delete npmLockParsed.dependencies![depName];
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
|
@ -284,12 +291,15 @@ export async function writeUpdatedPackageFiles(
|
|||
});
|
||||
for (const upgrade of config.upgrades) {
|
||||
if (upgrade.gitRef && upgrade.packageFile === packageFile.path) {
|
||||
massagedFile[upgrade.depType][upgrade.depName] = massagedFile[
|
||||
upgrade.depType
|
||||
][upgrade.depName].replace(
|
||||
'git+https://github.com',
|
||||
`git+https://${token}@github.com`
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
massagedFile[upgrade.depType as NpmDepType][upgrade.depName!] =
|
||||
massagedFile[
|
||||
upgrade.depType as NpmDepType
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
][upgrade.depName!].replace(
|
||||
'git+https://github.com',
|
||||
`git+https://${token}@github.com`
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
@ -305,7 +315,7 @@ export async function writeUpdatedPackageFiles(
|
|||
// istanbul ignore next
|
||||
async function getNpmrcContent(dir: string): Promise<string | null> {
|
||||
const npmrcFilePath = upath.join(dir, '.npmrc');
|
||||
let originalNpmrcContent = null;
|
||||
let originalNpmrcContent: string | null = null;
|
||||
try {
|
||||
originalNpmrcContent = await readFile(npmrcFilePath, 'utf8');
|
||||
logger.debug('npmrc file found in repository');
|
||||
|
@ -320,7 +330,7 @@ async function getNpmrcContent(dir: string): Promise<string | null> {
|
|||
// istanbul ignore next
|
||||
async function updateNpmrcContent(
|
||||
dir: string,
|
||||
originalContent: string,
|
||||
originalContent: string | null,
|
||||
additionalLines: string[]
|
||||
): Promise<void> {
|
||||
const npmrcFilePath = upath.join(dir, '.npmrc');
|
||||
|
@ -341,7 +351,7 @@ async function updateNpmrcContent(
|
|||
// istanbul ignore next
|
||||
async function resetNpmrcContent(
|
||||
dir: string,
|
||||
originalContent: string
|
||||
originalContent: string | null
|
||||
): Promise<void> {
|
||||
const npmrcFilePath = upath.join(dir, '.npmrc');
|
||||
if (originalContent) {
|
||||
|
@ -422,7 +432,7 @@ export async function updateYarnBinary(
|
|||
let yarnrcYml = existingYarnrcYmlContent;
|
||||
try {
|
||||
const yarnrcYmlFilename = upath.join(lockFileDir, '.yarnrc.yml');
|
||||
yarnrcYml ||= await getFile(yarnrcYmlFilename);
|
||||
yarnrcYml ||= (await getFile(yarnrcYmlFilename)) ?? undefined;
|
||||
const newYarnrcYml = await readLocalFile(yarnrcYmlFilename, 'utf8');
|
||||
if (!is.string(yarnrcYml) || !is.string(newYarnrcYml)) {
|
||||
return existingYarnrcYmlContent;
|
||||
|
@ -518,7 +528,7 @@ export async function getAdditionalFiles(
|
|||
|
||||
let token = '';
|
||||
try {
|
||||
({ token } = hostRules.find({
|
||||
({ token = '' } = hostRules.find({
|
||||
hostType: config.platform,
|
||||
url: 'https://api.github.com/',
|
||||
}));
|
||||
|
@ -527,7 +537,7 @@ export async function getAdditionalFiles(
|
|||
logger.warn({ err }, 'Error getting token for packageFile');
|
||||
}
|
||||
const tokenRe = regEx(`${token}`, 'g', false);
|
||||
const { localDir } = GlobalConfig.get();
|
||||
const localDir = GlobalConfig.get('localDir')!;
|
||||
for (const npmLock of dirs.npmLockDirs) {
|
||||
const lockFileDir = upath.dirname(npmLock);
|
||||
const fullLockFileDir = upath.join(localDir, lockFileDir);
|
||||
|
@ -585,7 +595,9 @@ export async function getAdditionalFiles(
|
|||
updatedArtifacts.push({
|
||||
type: 'addition',
|
||||
path: npmLock,
|
||||
contents: res.lockFile.replace(tokenRe, ''),
|
||||
// TODO: can this be undefined?
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
contents: res.lockFile!.replace(tokenRe, ''),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -601,8 +613,8 @@ export async function getAdditionalFiles(
|
|||
npmrcContent,
|
||||
additionalNpmrcContent
|
||||
);
|
||||
let yarnRcYmlFilename: string;
|
||||
let existingYarnrcYmlContent: string;
|
||||
let yarnRcYmlFilename: string | undefined;
|
||||
let existingYarnrcYmlContent: string | undefined;
|
||||
if (additionalYarnRcYml) {
|
||||
yarnRcYmlFilename = getSiblingFileName(yarnLock, '.yarnrc.yml');
|
||||
existingYarnrcYmlContent = await readLocalFile(yarnRcYmlFilename, 'utf8');
|
||||
|
@ -674,7 +686,9 @@ export async function getAdditionalFiles(
|
|||
updatedArtifacts.push({
|
||||
type: 'addition',
|
||||
path: lockFileName,
|
||||
contents: res.lockFile,
|
||||
//
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
contents: res.lockFile!,
|
||||
});
|
||||
await updateYarnOffline(lockFileDir, localDir, updatedArtifacts);
|
||||
}
|
||||
|
@ -689,7 +703,8 @@ export async function getAdditionalFiles(
|
|||
}
|
||||
await resetNpmrcContent(fullLockFileDir, npmrcContent);
|
||||
if (existingYarnrcYmlContent) {
|
||||
await writeLocalFile(yarnRcYmlFilename, existingYarnrcYmlContent);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
await writeLocalFile(yarnRcYmlFilename!, existingYarnrcYmlContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,7 +765,9 @@ export async function getAdditionalFiles(
|
|||
updatedArtifacts.push({
|
||||
type: 'addition',
|
||||
path: pnpmShrinkwrap,
|
||||
contents: res.lockFile,
|
||||
// TODO: can be undefined?
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
contents: res.lockFile!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -761,7 +778,8 @@ export async function getAdditionalFiles(
|
|||
let lockFile: string;
|
||||
logger.debug(`Finding package.json for lerna location "${lernaJsonFile}"`);
|
||||
const lernaPackageFile = packageFiles.npm.find(
|
||||
(p) => getSubDirectory(p.packageFile) === getSubDirectory(lernaJsonFile)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
(p) => getSubDirectory(p.packageFile!) === getSubDirectory(lernaJsonFile)
|
||||
);
|
||||
if (!lernaPackageFile) {
|
||||
logger.debug('No matching package.json found');
|
||||
|
@ -842,7 +860,8 @@ export async function getAdditionalFiles(
|
|||
const filename = packageFile.npmLock || packageFile.yarnLock;
|
||||
logger.trace('Checking for ' + filename);
|
||||
const existingContent = await getFile(
|
||||
filename,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
filename!,
|
||||
config.reuseExistingBranch ? config.branchName : config.baseBranch
|
||||
);
|
||||
if (existingContent) {
|
||||
|
@ -868,7 +887,8 @@ export async function getAdditionalFiles(
|
|||
logger.debug('File is updated: ' + lockFilePath);
|
||||
updatedArtifacts.push({
|
||||
type: 'addition',
|
||||
path: filename,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
path: filename!,
|
||||
contents: newContent,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import { exec as _exec } from 'child_process';
|
||||
import { envMock, mockExecAll } from '../../../../../test/exec-util';
|
||||
import { mocked } from '../../../../../test/util';
|
||||
import { envMock, exec, mockExecAll } from '../../../../../test/exec-util';
|
||||
import { env, partial } from '../../../../../test/util';
|
||||
import { GlobalConfig } from '../../../../config/global';
|
||||
import * as _env from '../../../../util/exec/env';
|
||||
import * as _lernaHelper from './lerna';
|
||||
import type { PackageFile, PostUpdateConfig } from '../../types';
|
||||
import * as lernaHelper from './lerna';
|
||||
|
||||
jest.mock('child_process');
|
||||
jest.mock('../../../../util/exec/env');
|
||||
jest.mock('../../npm/post-update/node-version');
|
||||
|
||||
const exec: jest.Mock<typeof _exec> = _exec as any;
|
||||
const env = mocked(_env);
|
||||
const lernaHelper = mocked(_lernaHelper);
|
||||
|
||||
function lernaPkgFile(lernaClient: string) {
|
||||
function lernaPkgFile(lernaClient: string): Partial<PackageFile> {
|
||||
return {
|
||||
lernaClient,
|
||||
deps: [{ depName: 'lerna', currentValue: '2.0.0' }],
|
||||
};
|
||||
}
|
||||
|
||||
function lernaPkgFileWithoutLernaDep(lernaClient: string) {
|
||||
function lernaPkgFileWithoutLernaDep(
|
||||
lernaClient: string
|
||||
): Partial<PackageFile> {
|
||||
return {
|
||||
lernaClient,
|
||||
};
|
||||
}
|
||||
|
||||
const config = partial<PostUpdateConfig>({});
|
||||
|
||||
describe('modules/manager/npm/post-update/lerna', () => {
|
||||
describe('generateLockFiles()', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -35,7 +34,12 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
});
|
||||
|
||||
it('returns if no lernaClient', async () => {
|
||||
const res = await lernaHelper.generateLockFiles({}, 'some-dir', {}, {});
|
||||
const res = await lernaHelper.generateLockFiles(
|
||||
{},
|
||||
'some-dir',
|
||||
config,
|
||||
{}
|
||||
);
|
||||
expect(res.error).toBeFalse();
|
||||
});
|
||||
|
||||
|
@ -43,7 +47,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFile('foo'),
|
||||
'some-dir',
|
||||
{},
|
||||
config,
|
||||
{}
|
||||
);
|
||||
expect(res.error).toBeFalse();
|
||||
|
@ -55,7 +59,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFile('npm'),
|
||||
'some-dir',
|
||||
{},
|
||||
config,
|
||||
{},
|
||||
skipInstalls
|
||||
);
|
||||
|
@ -69,7 +73,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFile('npm'),
|
||||
'some-dir',
|
||||
{},
|
||||
config,
|
||||
{},
|
||||
skipInstalls
|
||||
);
|
||||
|
@ -82,7 +86,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFile('yarn'),
|
||||
'some-dir',
|
||||
{ constraints: { yarn: '^1.10.0' } },
|
||||
{ ...config, constraints: { yarn: '^1.10.0' } },
|
||||
{}
|
||||
);
|
||||
expect(execSnapshots).toMatchSnapshot();
|
||||
|
@ -94,7 +98,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFileWithoutLernaDep('npm'),
|
||||
'some-dir',
|
||||
{},
|
||||
config,
|
||||
{}
|
||||
);
|
||||
expect(res.error).toBeFalse();
|
||||
|
@ -107,7 +111,7 @@ describe('modules/manager/npm/post-update/lerna', () => {
|
|||
const res = await lernaHelper.generateLockFiles(
|
||||
lernaPkgFile('npm'),
|
||||
'some-dir',
|
||||
{ constraints: { npm: '^6.0.0' } },
|
||||
{ ...config, constraints: { npm: '^6.0.0' } },
|
||||
{}
|
||||
);
|
||||
expect(res.error).toBeFalse();
|
||||
|
|
|
@ -4,7 +4,7 @@ import { GlobalConfig } from '../../../../config/global';
|
|||
import { TEMPORARY_ERROR } from '../../../../constants/error-messages';
|
||||
import { logger } from '../../../../logger';
|
||||
import { exec } from '../../../../util/exec';
|
||||
import type { ExecOptions } from '../../../../util/exec/types';
|
||||
import type { ExecOptions, ExtraEnv } from '../../../../util/exec/types';
|
||||
import type { PackageFile, PostUpdateConfig } from '../../types';
|
||||
import { getNodeConstraint } from './node-version';
|
||||
import type { GenerateLockFileResult } from './types';
|
||||
|
@ -21,7 +21,8 @@ export function getLernaVersion(
|
|||
);
|
||||
return 'latest';
|
||||
}
|
||||
return lernaDep.currentValue;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
return lernaDep.currentValue!;
|
||||
}
|
||||
|
||||
export async function generateLockFiles(
|
||||
|
@ -37,8 +38,8 @@ export async function generateLockFiles(
|
|||
return { error: false };
|
||||
}
|
||||
logger.debug(`Spawning lerna with ${lernaClient} to create lock files`);
|
||||
const preCommands = [];
|
||||
const cmd = [];
|
||||
const preCommands: string[] = [];
|
||||
const cmd: string[] = [];
|
||||
let cmdOptions = '';
|
||||
try {
|
||||
if (lernaClient === 'yarn') {
|
||||
|
@ -74,12 +75,13 @@ export async function generateLockFiles(
|
|||
}
|
||||
lernaCommand += cmdOptions;
|
||||
const tagConstraint = await getNodeConstraint(config);
|
||||
const extraEnv: ExtraEnv = {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
};
|
||||
const execOptions: ExecOptions = {
|
||||
cwd,
|
||||
extraEnv: {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
},
|
||||
extraEnv,
|
||||
docker: {
|
||||
image: 'node',
|
||||
tagScheme: 'node',
|
||||
|
@ -89,8 +91,8 @@ export async function generateLockFiles(
|
|||
};
|
||||
// istanbul ignore if
|
||||
if (GlobalConfig.get('exposeAllEnv')) {
|
||||
execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
}
|
||||
const lernaVersion = getLernaVersion(lernaPackageFile);
|
||||
logger.debug('Using lerna version ' + lernaVersion);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { getSiblingFileName, readLocalFile } from '../../../../util/fs';
|
|||
import { newlineRegex, regEx } from '../../../../util/regex';
|
||||
import type { PostUpdateConfig } from '../../types';
|
||||
|
||||
async function getNodeFile(filename: string): Promise<string> | null {
|
||||
async function getNodeFile(filename: string): Promise<string | null> {
|
||||
try {
|
||||
const constraint = (await readLocalFile(filename, 'utf8'))
|
||||
.split(newlineRegex)[0]
|
||||
|
@ -19,7 +19,9 @@ async function getNodeFile(filename: string): Promise<string> | null {
|
|||
return null;
|
||||
}
|
||||
|
||||
function getPackageJsonConstraint(config: PostUpdateConfig): string | null {
|
||||
function getPackageJsonConstraint(
|
||||
config: Partial<PostUpdateConfig>
|
||||
): string | null {
|
||||
const constraint: string = config.constraints?.node;
|
||||
if (constraint && semver.validRange(constraint)) {
|
||||
logger.debug(`Using node constraint "${constraint}" from package.json`);
|
||||
|
@ -29,8 +31,8 @@ function getPackageJsonConstraint(config: PostUpdateConfig): string | null {
|
|||
}
|
||||
|
||||
export async function getNodeConstraint(
|
||||
config: PostUpdateConfig
|
||||
): Promise<string> | null {
|
||||
config: Partial<PostUpdateConfig>
|
||||
): Promise<string | null> {
|
||||
const { packageFile } = config;
|
||||
const constraint =
|
||||
(await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) ||
|
||||
|
|
|
@ -6,7 +6,11 @@ import {
|
|||
} from '../../../../constants/error-messages';
|
||||
import { logger } from '../../../../logger';
|
||||
import { exec } from '../../../../util/exec';
|
||||
import type { ExecOptions, ToolConstraint } from '../../../../util/exec/types';
|
||||
import type {
|
||||
ExecOptions,
|
||||
ExtraEnv,
|
||||
ToolConstraint,
|
||||
} from '../../../../util/exec/types';
|
||||
import { move, pathExists, readFile, remove } from '../../../../util/fs';
|
||||
import type { PostUpdateConfig, Upgrade } from '../../types';
|
||||
import { composeLockFile, parseLockFile } from '../utils';
|
||||
|
@ -17,19 +21,19 @@ export async function generateLockFile(
|
|||
cwd: string,
|
||||
env: NodeJS.ProcessEnv,
|
||||
filename: string,
|
||||
config: PostUpdateConfig = {},
|
||||
config: Partial<PostUpdateConfig> = {},
|
||||
upgrades: Upgrade[] = []
|
||||
): Promise<GenerateLockFileResult> {
|
||||
logger.debug(`Spawning npm install to create ${cwd}/${filename}`);
|
||||
const { skipInstalls, postUpdateOptions } = config;
|
||||
|
||||
let lockFile = null;
|
||||
let lockFile: string | null = null;
|
||||
try {
|
||||
const npmToolConstraint: ToolConstraint = {
|
||||
toolName: 'npm',
|
||||
constraint: config.constraints?.npm,
|
||||
};
|
||||
const commands = [];
|
||||
const commands: string[] = [];
|
||||
let cmdOptions = '';
|
||||
if (postUpdateOptions?.includes('npmDedupe') || skipInstalls === false) {
|
||||
logger.debug('Performing node_modules install');
|
||||
|
@ -44,12 +48,13 @@ export async function generateLockFile(
|
|||
}
|
||||
|
||||
const tagConstraint = await getNodeConstraint(config);
|
||||
const extraEnv: ExtraEnv = {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
};
|
||||
const execOptions: ExecOptions = {
|
||||
cwd,
|
||||
extraEnv: {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
},
|
||||
extraEnv,
|
||||
toolConstraints: [npmToolConstraint],
|
||||
docker: {
|
||||
image: 'node',
|
||||
|
@ -59,8 +64,8 @@ export async function generateLockFile(
|
|||
};
|
||||
// istanbul ignore if
|
||||
if (GlobalConfig.get('exposeAllEnv')) {
|
||||
execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
}
|
||||
|
||||
if (!upgrades.every((upgrade) => upgrade.isLockfileUpdate)) {
|
||||
|
@ -131,14 +136,18 @@ export async function generateLockFile(
|
|||
const { detectedIndent, lockFileParsed } = parseLockFile(lockFile);
|
||||
if (lockFileParsed?.lockfileVersion === 2) {
|
||||
lockUpdates.forEach((lockUpdate) => {
|
||||
const depType = lockUpdate.depType as
|
||||
| 'dependencies'
|
||||
| 'optionalDependencies';
|
||||
if (
|
||||
lockFileParsed.packages?.['']?.[lockUpdate.depType]?.[
|
||||
lockUpdate.depName
|
||||
lockFileParsed.packages?.['']?.[depType]?.[
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
lockUpdate.depName!
|
||||
]
|
||||
) {
|
||||
lockFileParsed.packages[''][lockUpdate.depType][
|
||||
lockUpdate.depName
|
||||
] = lockUpdate.newValue;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
lockFileParsed.packages[''][depType]![lockUpdate.depName!] =
|
||||
lockUpdate.newValue!;
|
||||
}
|
||||
});
|
||||
lockFile = composeLockFile(lockFileParsed, detectedIndent);
|
||||
|
|
|
@ -1,34 +1,28 @@
|
|||
import { exec as _exec } from 'child_process';
|
||||
import { envMock, mockExecAll } from '../../../../../test/exec-util';
|
||||
import { envMock, exec, mockExecAll } from '../../../../../test/exec-util';
|
||||
import { Fixtures } from '../../../../../test/fixtures';
|
||||
import { mocked } from '../../../../../test/util';
|
||||
import * as _env from '../../../../util/exec/env';
|
||||
import * as _fs from '../../../../util/fs/proxies';
|
||||
import { env, fs, partial } from '../../../../../test/util';
|
||||
import type { PostUpdateConfig } from '../../types';
|
||||
import * as _pnpmHelper from './pnpm';
|
||||
import * as pnpmHelper from './pnpm';
|
||||
|
||||
jest.mock('child_process');
|
||||
jest.mock('../../../../util/exec/env');
|
||||
jest.mock('../../../../util/fs/proxies');
|
||||
jest.mock('./node-version');
|
||||
|
||||
const exec: jest.Mock<typeof _exec> = _exec as any;
|
||||
const env = mocked(_env);
|
||||
const fs = mocked(_fs);
|
||||
const pnpmHelper = mocked(_pnpmHelper);
|
||||
delete process.env.NPM_CONFIG_CACHE;
|
||||
|
||||
describe('modules/manager/npm/post-update/pnpm', () => {
|
||||
let config: PostUpdateConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
config = { cacheDir: 'some-cache-dir', constraints: { pnpm: '^2.0.0' } };
|
||||
jest.resetAllMocks();
|
||||
config = partial<PostUpdateConfig>({ constraints: { pnpm: '^2.0.0' } });
|
||||
env.getChildProcessEnv.mockReturnValue(envMock.basic);
|
||||
});
|
||||
|
||||
it('generates lock files', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
|
||||
fs.readFile.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir', {}, config);
|
||||
expect(fs.readFile).toHaveBeenCalledTimes(1);
|
||||
expect(res.lockFile).toBe('package-lock-contents');
|
||||
|
@ -37,9 +31,9 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('catches errors', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
fs.readFile = jest.fn(() => {
|
||||
fs.readFile.mockImplementation(() => {
|
||||
throw new Error('not found');
|
||||
}) as never;
|
||||
});
|
||||
const res = await pnpmHelper.generateLockFile('some-dir', {}, config);
|
||||
expect(fs.readFile).toHaveBeenCalledTimes(1);
|
||||
expect(res.error).toBeTrue();
|
||||
|
@ -49,7 +43,7 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('finds pnpm globally', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
|
||||
fs.readFile.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir', {}, config);
|
||||
expect(fs.readFile).toHaveBeenCalledTimes(1);
|
||||
expect(res.lockFile).toBe('package-lock-contents');
|
||||
|
@ -58,7 +52,7 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('performs lock file maintenance', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
|
||||
fs.readFile.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir', {}, config, [
|
||||
{ isLockFileMaintenance: true },
|
||||
]);
|
||||
|
@ -70,7 +64,7 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('uses the new version if packageManager is updated', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
|
||||
fs.readFile.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile('some-dir', {}, config, [
|
||||
{
|
||||
depType: 'packageManager',
|
||||
|
@ -86,12 +80,11 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('uses constraint version if parent json has constraints', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
const configTemp = { cacheDir: 'some-cache-dir' };
|
||||
const configTemp = partial<PostUpdateConfig>({});
|
||||
const fileContent = Fixtures.get('parent/package.json');
|
||||
fs.readFile = jest
|
||||
.fn()
|
||||
.mockReturnValueOnce(fileContent)
|
||||
.mockReturnValue('package-lock-contents');
|
||||
fs.readFile
|
||||
.mockResolvedValueOnce(fileContent)
|
||||
.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile(
|
||||
'some-folder',
|
||||
{},
|
||||
|
@ -129,12 +122,11 @@ describe('modules/manager/npm/post-update/pnpm', () => {
|
|||
|
||||
it('uses packageManager version and puts it into constraint', async () => {
|
||||
const execSnapshots = mockExecAll(exec);
|
||||
const configTemp = { cacheDir: 'some-cache-dir' };
|
||||
const configTemp = partial<PostUpdateConfig>({});
|
||||
const fileContent = Fixtures.get('manager-field/package.json');
|
||||
fs.readFile = jest
|
||||
.fn()
|
||||
.mockReturnValueOnce(fileContent)
|
||||
.mockReturnValue('package-lock-contents');
|
||||
fs.readFile
|
||||
.mockResolvedValueOnce(fileContent)
|
||||
.mockResolvedValue('package-lock-contents');
|
||||
const res = await pnpmHelper.generateLockFile(
|
||||
'some-folder',
|
||||
{},
|
||||
|
|
|
@ -3,7 +3,11 @@ import { GlobalConfig } from '../../../../config/global';
|
|||
import { TEMPORARY_ERROR } from '../../../../constants/error-messages';
|
||||
import { logger } from '../../../../logger';
|
||||
import { exec } from '../../../../util/exec';
|
||||
import type { ExecOptions, ToolConstraint } from '../../../../util/exec/types';
|
||||
import type {
|
||||
ExecOptions,
|
||||
ExtraEnv,
|
||||
ToolConstraint,
|
||||
} from '../../../../util/exec/types';
|
||||
import { readFile, remove } from '../../../../util/fs';
|
||||
import type { PostUpdateConfig, Upgrade } from '../../types';
|
||||
import type { NpmPackage } from '../extract/types';
|
||||
|
@ -18,9 +22,9 @@ export async function generateLockFile(
|
|||
): Promise<GenerateLockFileResult> {
|
||||
const lockFileName = upath.join(cwd, 'pnpm-lock.yaml');
|
||||
logger.debug(`Spawning pnpm install to create ${lockFileName}`);
|
||||
let lockFile = null;
|
||||
let stdout: string;
|
||||
let stderr: string;
|
||||
let lockFile: string | null = null;
|
||||
let stdout: string | undefined;
|
||||
let stderr: string | undefined;
|
||||
let cmd = 'pnpm';
|
||||
try {
|
||||
const pnpmToolConstraint: ToolConstraint = {
|
||||
|
@ -28,12 +32,13 @@ export async function generateLockFile(
|
|||
constraint: config.constraints?.pnpm ?? (await getPnpmContraint(cwd)),
|
||||
};
|
||||
const tagConstraint = await getNodeConstraint(config);
|
||||
const extraEnv: ExtraEnv = {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
};
|
||||
const execOptions: ExecOptions = {
|
||||
cwd,
|
||||
extraEnv: {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
},
|
||||
extraEnv,
|
||||
docker: {
|
||||
image: 'node',
|
||||
tagScheme: 'node',
|
||||
|
@ -43,8 +48,8 @@ export async function generateLockFile(
|
|||
};
|
||||
// istanbul ignore if
|
||||
if (GlobalConfig.get('exposeAllEnv')) {
|
||||
execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
}
|
||||
cmd = 'pnpm';
|
||||
let args = 'install --recursive --lockfile-only';
|
||||
|
@ -89,8 +94,8 @@ export async function generateLockFile(
|
|||
return { lockFile };
|
||||
}
|
||||
|
||||
async function getPnpmContraint(cwd: string): Promise<string> {
|
||||
let result;
|
||||
async function getPnpmContraint(cwd: string): Promise<string | undefined> {
|
||||
let result: string | undefined;
|
||||
const rootPackageJson = upath.join(cwd, 'package.json');
|
||||
const content = await readFile(rootPackageJson, 'utf8');
|
||||
if (content) {
|
||||
|
|
|
@ -14,7 +14,7 @@ export interface AdditionalPackageFiles {
|
|||
|
||||
export interface ArtifactError {
|
||||
lockFile: string;
|
||||
stderr: string;
|
||||
stderr?: string;
|
||||
}
|
||||
|
||||
export interface WriteExistingFilesResult {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { logger } from '../../../../logger';
|
||||
import { ExternalHostError } from '../../../../types/errors/external-host-error';
|
||||
import { exec } from '../../../../util/exec';
|
||||
import type { ExecOptions } from '../../../../util/exec/types';
|
||||
import type { ExecOptions, ExtraEnv } from '../../../../util/exec/types';
|
||||
import { exists, readFile, remove, writeFile } from '../../../../util/fs';
|
||||
import { newlineRegex, regEx } from '../../../../util/regex';
|
||||
import { uniqueStrings } from '../../../../util/string';
|
||||
|
@ -23,7 +23,7 @@ export async function checkYarnrc(
|
|||
cwd: string
|
||||
): Promise<{ offlineMirror: boolean; yarnPath: string | null }> {
|
||||
let offlineMirror = false;
|
||||
let yarnPath: string = null;
|
||||
let yarnPath: string | null = null;
|
||||
try {
|
||||
const yarnrc = await readFile(`${cwd}/.yarnrc`, 'utf8');
|
||||
if (is.string(yarnrc)) {
|
||||
|
@ -37,7 +37,7 @@ export async function checkYarnrc(
|
|||
if (pathLine) {
|
||||
yarnPath = pathLine.replace(regEx(/^yarn-path\s+"?(.+?)"?$/), '$1');
|
||||
}
|
||||
const yarnBinaryExists = await exists(yarnPath);
|
||||
const yarnBinaryExists = yarnPath ? await exists(yarnPath) : false;
|
||||
if (!yarnBinaryExists) {
|
||||
const scrubbedYarnrc = yarnrc.replace(
|
||||
regEx(/^yarn-path\s+"?.+?"?$/gm),
|
||||
|
@ -66,12 +66,12 @@ export function isYarnUpdate(upgrade: Upgrade): boolean {
|
|||
export async function generateLockFile(
|
||||
cwd: string,
|
||||
env: NodeJS.ProcessEnv,
|
||||
config: PostUpdateConfig = {},
|
||||
config: Partial<PostUpdateConfig> = {},
|
||||
upgrades: Upgrade[] = []
|
||||
): Promise<GenerateLockFileResult> {
|
||||
const lockFileName = upath.join(cwd, 'yarn.lock');
|
||||
logger.debug(`Spawning yarn install to create ${lockFileName}`);
|
||||
let lockFile = null;
|
||||
let lockFile: string | null = null;
|
||||
try {
|
||||
const yarnUpdate = upgrades.find(isYarnUpdate);
|
||||
const yarnCompatibility = yarnUpdate
|
||||
|
@ -93,13 +93,13 @@ export async function generateLockFile(
|
|||
|
||||
const preCommands = [installYarn];
|
||||
|
||||
const extraEnv: ExecOptions['extraEnv'] = {
|
||||
const extraEnv: ExtraEnv = {
|
||||
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
|
||||
npm_config_store: env.npm_config_store,
|
||||
CI: 'true',
|
||||
};
|
||||
|
||||
const commands = [];
|
||||
const commands: string[] = [];
|
||||
let cmdOptions = ''; // should have a leading space
|
||||
if (config.skipInstalls !== false) {
|
||||
if (isYarn1) {
|
||||
|
@ -157,8 +157,8 @@ export async function generateLockFile(
|
|||
};
|
||||
// istanbul ignore if
|
||||
if (GlobalConfig.get('exposeAllEnv')) {
|
||||
execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
extraEnv.NPM_AUTH = env.NPM_AUTH;
|
||||
extraEnv.NPM_EMAIL = env.NPM_EMAIL;
|
||||
}
|
||||
|
||||
if (yarnUpdate && !isYarn1) {
|
||||
|
@ -179,6 +179,7 @@ export async function generateLockFile(
|
|||
commands.push(
|
||||
`yarn upgrade ${lockUpdates
|
||||
.map((update) => update.depName)
|
||||
.filter(is.string)
|
||||
.filter(uniqueStrings)
|
||||
.join(' ')}${cmdOptions}`
|
||||
);
|
||||
|
|
|
@ -6,7 +6,8 @@ import type { RangeConfig } from '../types';
|
|||
export function getRangeStrategy(config: RangeConfig): RangeStrategy {
|
||||
const { depType, depName, packageJsonType, currentValue, rangeStrategy } =
|
||||
config;
|
||||
const isComplexRange = parseRange(currentValue).length > 1;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
const isComplexRange = parseRange(currentValue!).length > 1;
|
||||
if (rangeStrategy === 'bump' && isComplexRange) {
|
||||
logger.debug(
|
||||
{ currentValue },
|
||||
|
|
|
@ -62,3 +62,10 @@ export interface ParseLockFileResult {
|
|||
detectedIndent: string;
|
||||
lockFileParsed: LockFile | undefined;
|
||||
}
|
||||
|
||||
export type NpmDepType =
|
||||
| 'dependencies'
|
||||
| 'devDependencies'
|
||||
| 'optionalDependencies'
|
||||
| 'peerDependencies'
|
||||
| 'resolutions';
|
||||
|
|
|
@ -4,6 +4,7 @@ import { escapeRegExp, regEx } from '../../../../../util/regex';
|
|||
import { matchAt, replaceAt } from '../../../../../util/string';
|
||||
import type { UpdateDependencyConfig } from '../../../types';
|
||||
import type { DependenciesMeta, NpmPackage } from '../../extract/types';
|
||||
import type { NpmDepType } from '../../types';
|
||||
|
||||
function renameObjKey(
|
||||
oldObj: DependenciesMeta,
|
||||
|
@ -18,35 +19,36 @@ function renameObjKey(
|
|||
acc[key] = oldObj[key];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
}, {} as DependenciesMeta);
|
||||
}
|
||||
|
||||
function replaceAsString(
|
||||
parsedContents: NpmPackage,
|
||||
fileContent: string,
|
||||
depType: string,
|
||||
depType: NpmDepType | 'dependenciesMeta' | 'packageManager',
|
||||
depName: string,
|
||||
oldValue: string,
|
||||
newValue: string
|
||||
): string | null {
|
||||
): string {
|
||||
if (depType === 'packageManager') {
|
||||
parsedContents[depType] = newValue;
|
||||
} else if (depName === oldValue) {
|
||||
// The old value is the name of the dependency itself
|
||||
delete Object.assign(parsedContents[depType], {
|
||||
[newValue]: parsedContents[depType][oldValue],
|
||||
[newValue]: parsedContents[depType]![oldValue],
|
||||
})[oldValue];
|
||||
} else if (depType === 'dependenciesMeta') {
|
||||
if (oldValue !== newValue) {
|
||||
parsedContents.dependenciesMeta = renameObjKey(
|
||||
parsedContents.dependenciesMeta,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
parsedContents.dependenciesMeta!,
|
||||
oldValue,
|
||||
newValue
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// The old value is the version of the dependency
|
||||
parsedContents[depType][depName] = newValue;
|
||||
parsedContents[depType]![depName] = newValue;
|
||||
}
|
||||
// Look for the old version number
|
||||
const searchString = `"${oldValue}"`;
|
||||
|
@ -55,9 +57,9 @@ function replaceAsString(
|
|||
const escapedDepName = escapeRegExp(depName);
|
||||
const patchRe = regEx(`^(patch:${escapedDepName}@(npm:)?).*#`);
|
||||
const match = patchRe.exec(oldValue);
|
||||
if (match) {
|
||||
if (match && depType === 'resolutions') {
|
||||
const patch = oldValue.replace(match[0], `${match[1]}${newValue}#`);
|
||||
parsedContents[depType][depName] = patch;
|
||||
parsedContents[depType]![depName] = patch;
|
||||
newString = `"${patch}"`;
|
||||
}
|
||||
|
||||
|
@ -98,7 +100,8 @@ export function updateDependency({
|
|||
logger.debug('Updating package.json git digest');
|
||||
newValue = upgrade.currentRawValue.replace(
|
||||
upgrade.currentDigest,
|
||||
upgrade.newDigest.substring(0, upgrade.currentDigest.length)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
upgrade.newDigest!.substring(0, upgrade.currentDigest.length)
|
||||
);
|
||||
} else {
|
||||
logger.debug('Updating package.json git version tag');
|
||||
|
@ -115,36 +118,38 @@ export function updateDependency({
|
|||
try {
|
||||
const parsedContents: NpmPackage = JSON.parse(fileContent);
|
||||
// Save the old version
|
||||
let oldVersion: string;
|
||||
let oldVersion: string | undefined;
|
||||
if (depType === 'packageManager') {
|
||||
oldVersion = parsedContents[depType];
|
||||
newValue = `${depName}@${newValue}`;
|
||||
} else {
|
||||
oldVersion = parsedContents[depType][depName];
|
||||
oldVersion = parsedContents[depType as NpmDepType]![depName];
|
||||
}
|
||||
if (oldVersion === newValue) {
|
||||
logger.trace('Version is already updated');
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
|
||||
let newFileContent = replaceAsString(
|
||||
parsedContents,
|
||||
fileContent,
|
||||
depType,
|
||||
depType as NpmDepType,
|
||||
depName,
|
||||
oldVersion,
|
||||
newValue
|
||||
oldVersion!,
|
||||
newValue!
|
||||
);
|
||||
if (upgrade.newName) {
|
||||
newFileContent = replaceAsString(
|
||||
parsedContents,
|
||||
newFileContent,
|
||||
depType,
|
||||
depType as NpmDepType,
|
||||
depName,
|
||||
depName,
|
||||
upgrade.newName
|
||||
);
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/no-unnecessary-type-assertion */
|
||||
// istanbul ignore if
|
||||
if (!newFileContent) {
|
||||
logger.debug(
|
||||
|
@ -154,7 +159,7 @@ export function updateDependency({
|
|||
return fileContent;
|
||||
}
|
||||
if (parsedContents?.resolutions) {
|
||||
let depKey: string;
|
||||
let depKey: string | undefined;
|
||||
if (parsedContents.resolutions[depName]) {
|
||||
depKey = depName;
|
||||
} else if (parsedContents.resolutions[`**/${depName}`]) {
|
||||
|
@ -179,7 +184,8 @@ export function updateDependency({
|
|||
'resolutions',
|
||||
depKey,
|
||||
parsedContents.resolutions[depKey],
|
||||
newValue
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
newValue!
|
||||
);
|
||||
if (upgrade.newName) {
|
||||
if (depKey === `**/${depName}`) {
|
||||
|
|
|
@ -75,7 +75,7 @@ export async function findFirstParentVersion(
|
|||
for (const parentVersion of parentVersions) {
|
||||
const constraint = parentDep.releases.find(
|
||||
(release) => release.version === parentVersion
|
||||
).dependencies?.[targetDepName];
|
||||
)?.dependencies?.[targetDepName];
|
||||
if (!constraint) {
|
||||
logger.debug(
|
||||
`${targetDepName} has been removed from ${parentName}@${parentVersion}`
|
||||
|
|
|
@ -30,11 +30,14 @@ export async function updateLockedDependency(
|
|||
try {
|
||||
let packageJson: PackageJson;
|
||||
let packageLockJson: PackageLockOrEntry;
|
||||
const detectedIndent = detectIndent(lockFileContent).indent || ' ';
|
||||
let newPackageJsonContent: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
const detectedIndent = detectIndent(lockFileContent!).indent || ' ';
|
||||
let newPackageJsonContent: string | null | undefined;
|
||||
try {
|
||||
packageJson = JSON.parse(packageFileContent);
|
||||
packageLockJson = JSON.parse(lockFileContent);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageJson = JSON.parse(packageFileContent!);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
packageLockJson = JSON.parse(lockFileContent!);
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'Failed to parse files');
|
||||
return { status: 'update-failed' };
|
||||
|
@ -43,7 +46,8 @@ export async function updateLockedDependency(
|
|||
const lockedDeps = getLockedDependencies(
|
||||
packageLockJson,
|
||||
depName,
|
||||
currentVersion
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
currentVersion!
|
||||
);
|
||||
if (lockedDeps.some((dep) => dep.bundled)) {
|
||||
logger.info(
|
||||
|
@ -109,10 +113,12 @@ export async function updateLockedDependency(
|
|||
// Don't return {} if we're a parent update or else the whole update will fail
|
||||
// istanbul ignore if: too hard to replicate
|
||||
if (isParentUpdate) {
|
||||
const res: UpdateLockedResult = { status, files: {} };
|
||||
res.files[packageFile] = packageFileContent;
|
||||
res.files[lockFile] = lockFileContent;
|
||||
return res;
|
||||
const files: Record<string, string> = {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
files[packageFile!] = packageFileContent!;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
files[lockFile!] = lockFileContent!;
|
||||
return { status, files: files };
|
||||
}
|
||||
return { status };
|
||||
}
|
||||
|
@ -123,7 +129,8 @@ export async function updateLockedDependency(
|
|||
packageJson,
|
||||
packageLockJson,
|
||||
depName,
|
||||
currentVersion,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
currentVersion!,
|
||||
newVersion
|
||||
);
|
||||
logger.trace({ deps: lockedDeps, constraints }, 'Matching details');
|
||||
|
@ -134,7 +141,7 @@ export async function updateLockedDependency(
|
|||
);
|
||||
return { status: 'update-failed' };
|
||||
}
|
||||
const parentUpdates: UpdateLockedConfig[] = [];
|
||||
const parentUpdates: Partial<UpdateLockedConfig>[] = [];
|
||||
for (const {
|
||||
parentDepName,
|
||||
parentVersion,
|
||||
|
@ -172,7 +179,7 @@ export async function updateLockedDependency(
|
|||
logger.debug(
|
||||
`Update of ${depName} to ${newVersion} can be achieved due to parent ${parentDepName}`
|
||||
);
|
||||
const parentUpdate: UpdateLockedConfig = {
|
||||
const parentUpdate: Partial<UpdateLockedConfig> = {
|
||||
depName: parentDepName,
|
||||
currentVersion: parentVersion,
|
||||
newVersion: parentNewVersion,
|
||||
|
@ -187,15 +194,17 @@ export async function updateLockedDependency(
|
|||
return { status: 'update-failed' };
|
||||
}
|
||||
} else if (depType) {
|
||||
// TODO: `newValue` can probably null
|
||||
// The constaint comes from the package.json file, so we need to update it
|
||||
const newValue = semver.getNewValue({
|
||||
currentValue: constraint,
|
||||
rangeStrategy: 'replace',
|
||||
currentVersion,
|
||||
newVersion,
|
||||
});
|
||||
})!;
|
||||
newPackageJsonContent = updateDependency({
|
||||
fileContent: packageFileContent,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
fileContent: packageFileContent!,
|
||||
upgrade: { depName, depType, newValue },
|
||||
});
|
||||
}
|
||||
|
@ -215,9 +224,9 @@ export async function updateLockedDependency(
|
|||
for (const parentUpdate of parentUpdates) {
|
||||
const parentUpdateConfig = {
|
||||
...config,
|
||||
...parentUpdate,
|
||||
lockFileContent: newLockFileContent,
|
||||
packageFileContent: newPackageJsonContent || packageFileContent,
|
||||
...parentUpdate,
|
||||
};
|
||||
const parentUpdateResult = await updateLockedDependency(
|
||||
parentUpdateConfig,
|
||||
|
@ -235,7 +244,7 @@ export async function updateLockedDependency(
|
|||
newLockFileContent =
|
||||
parentUpdateResult.files[lockFile] || newLockFileContent;
|
||||
}
|
||||
const files = {};
|
||||
const files: Record<string, string> = {};
|
||||
if (newLockFileContent) {
|
||||
files[lockFile] = newLockFileContent;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { loadFixture } from '../../../../../../../test/util';
|
||||
import { loadFixture, partial } from '../../../../../../../test/util';
|
||||
import type { UpdateLockedConfig } from '../../../../types';
|
||||
import { updateLockedDependency } from '.';
|
||||
|
||||
|
@ -10,7 +10,7 @@ describe('modules/manager/npm/update/locked-dependency/yarn-lock/index', () => {
|
|||
let config: UpdateLockedConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
config = {};
|
||||
config = partial<UpdateLockedConfig>({ packageFile: 'package.json' });
|
||||
});
|
||||
|
||||
it('returns if cannot parse lock file', () => {
|
||||
|
|
|
@ -16,7 +16,8 @@ export function updateLockedDependency(
|
|||
);
|
||||
let yarnLock: YarnLock;
|
||||
try {
|
||||
yarnLock = parseSyml(lockFileContent);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
yarnLock = parseSyml(lockFileContent!);
|
||||
} catch (err) {
|
||||
logger.warn({ err }, 'Failed to parse yarn files');
|
||||
return { status: 'update-failed' };
|
||||
|
@ -26,7 +27,12 @@ export function updateLockedDependency(
|
|||
return { status: 'unsupported' };
|
||||
}
|
||||
try {
|
||||
const lockedDeps = getLockedDependencies(yarnLock, depName, currentVersion);
|
||||
const lockedDeps = getLockedDependencies(
|
||||
yarnLock,
|
||||
depName,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
currentVersion!
|
||||
);
|
||||
if (!lockedDeps.length) {
|
||||
const newLockedDeps = getLockedDependencies(
|
||||
yarnLock,
|
||||
|
@ -61,7 +67,8 @@ export function updateLockedDependency(
|
|||
);
|
||||
return { status: 'update-failed' };
|
||||
}
|
||||
let newLockFileContent = lockFileContent;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
let newLockFileContent = lockFileContent!;
|
||||
for (const dependency of updateLockedDeps) {
|
||||
const { depName, constraint, newVersion } = dependency;
|
||||
newLockFileContent = replaceConstraintVersion(
|
||||
|
|
|
@ -12,7 +12,7 @@ export function bumpPackageVersion(
|
|||
{ bumpVersion, currentValue },
|
||||
'Checking if we should bump package.json version'
|
||||
);
|
||||
let newPjVersion: string;
|
||||
let newPjVersion: string | null;
|
||||
let bumpedContent = content;
|
||||
try {
|
||||
if (bumpVersion.startsWith('mirror:')) {
|
||||
|
|
|
@ -2,11 +2,16 @@ import { loadFixture } from '../../../../test/util';
|
|||
import type { UpdateLockedConfig } from '../types';
|
||||
import { updateLockedDependency } from '.';
|
||||
|
||||
const lockFileContent = loadFixture('pyproject.11.toml.lock');
|
||||
const lockFile = 'pyproject.11.toml.lock';
|
||||
const packageFile = 'pyproject.11.toml';
|
||||
|
||||
const lockFileContent = loadFixture(lockFile);
|
||||
|
||||
describe('modules/manager/poetry/update-locked', () => {
|
||||
it('detects already updated', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile,
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
depName: 'urllib3',
|
||||
newVersion: '1.26.3',
|
||||
|
@ -16,6 +21,8 @@ describe('modules/manager/poetry/update-locked', () => {
|
|||
|
||||
it('returns unsupported', () => {
|
||||
const config: UpdateLockedConfig = {
|
||||
packageFile,
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
depName: 'urllib3',
|
||||
newVersion: '1.26.4',
|
||||
|
|
|
@ -133,7 +133,7 @@ export async function updateArtifacts({
|
|||
}
|
||||
|
||||
const res = writeLockUpdates(updates, lockFilePath, lockFileContent);
|
||||
return res ? [res] : null;
|
||||
return [res];
|
||||
} catch (err) {
|
||||
/* istanbul ignore next */
|
||||
return [
|
||||
|
|
|
@ -123,7 +123,7 @@ export interface Package<T> extends ManagerData<T> {
|
|||
pinDigests?: boolean;
|
||||
currentRawValue?: string;
|
||||
major?: { enabled?: boolean };
|
||||
prettyDepType?: any;
|
||||
prettyDepType?: string;
|
||||
}
|
||||
|
||||
export interface LookupUpdate {
|
||||
|
@ -159,7 +159,7 @@ export interface PackageDependency<T = Record<string, any>> extends Package<T> {
|
|||
digestOneAndOnly?: boolean;
|
||||
fixedVersion?: string;
|
||||
currentVersion?: string;
|
||||
lockedVersion?: string;
|
||||
lockedVersion?: string | null;
|
||||
propSource?: string;
|
||||
registryUrls?: string[] | null;
|
||||
rangeStrategy?: RangeStrategy;
|
||||
|
@ -224,13 +224,13 @@ export interface BumpPackageVersionResult {
|
|||
}
|
||||
|
||||
export interface UpdateLockedConfig {
|
||||
packageFile?: string;
|
||||
packageFile: string;
|
||||
packageFileContent?: string;
|
||||
lockFile?: string;
|
||||
lockFile: string;
|
||||
lockFileContent?: string;
|
||||
depName?: string;
|
||||
depName: string;
|
||||
currentVersion?: string;
|
||||
newVersion?: string;
|
||||
newVersion: string;
|
||||
allowParentUpdates?: boolean;
|
||||
allowHigherOrRemoved?: boolean;
|
||||
}
|
||||
|
@ -296,9 +296,9 @@ export interface PostUpdateConfig<T = Record<string, any>>
|
|||
ignoreScripts?: boolean;
|
||||
|
||||
platform?: string;
|
||||
upgrades?: Upgrade[];
|
||||
upgrades: Upgrade[];
|
||||
npmLock?: string;
|
||||
yarnLock?: string;
|
||||
branchName?: string;
|
||||
branchName: string;
|
||||
reuseExistingBranch?: boolean;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ export interface VersioningApi {
|
|||
isSingleVersion(version: string): boolean;
|
||||
isStable(version: string): boolean;
|
||||
isValid(input: string): boolean;
|
||||
isVersion(input: string): boolean;
|
||||
isVersion(input: string | undefined | null): boolean;
|
||||
|
||||
// digestion of version
|
||||
getMajor(version: string | SemVer): null | number;
|
||||
|
|
|
@ -75,7 +75,11 @@ export async function getUpdatedPackageFiles(
|
|||
} else if (upgrade.isRemediation) {
|
||||
const { status, files } = await updateLockedDependency({
|
||||
...upgrade,
|
||||
depName,
|
||||
newVersion,
|
||||
packageFile,
|
||||
packageFileContent,
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
allowParentUpdates: true,
|
||||
allowHigherOrRemoved: true,
|
||||
|
@ -100,8 +104,11 @@ export async function getUpdatedPackageFiles(
|
|||
if (updateLockedDependency) {
|
||||
const { status, files } = await updateLockedDependency({
|
||||
...upgrade,
|
||||
lockFile,
|
||||
depName,
|
||||
newVersion,
|
||||
packageFile,
|
||||
packageFileContent,
|
||||
lockFile,
|
||||
lockFileContent,
|
||||
allowParentUpdates: false,
|
||||
});
|
||||
|
|
|
@ -10,7 +10,11 @@ import type { PostUpdateConfig } from '../../../../../modules/manager/types';
|
|||
import * as _fs from '../../../../../util/fs/proxies';
|
||||
import * as _hostRules from '../../../../../util/host-rules';
|
||||
|
||||
const config: PostUpdateConfig = getConfig();
|
||||
const config: PostUpdateConfig = {
|
||||
...getConfig(),
|
||||
upgrades: [],
|
||||
branchName: 'some-branch',
|
||||
};
|
||||
|
||||
const fs = mocked(_fs);
|
||||
const lockFiles = mocked(_lockFiles);
|
||||
|
|
|
@ -39,35 +39,6 @@
|
|||
"lib/config/validation-helpers/managers.ts",
|
||||
"lib/config/validation.ts",
|
||||
"lib/modules/datasource/github-releases/test/index.ts",
|
||||
"lib/modules/manager/api.ts",
|
||||
"lib/modules/manager/index.ts",
|
||||
"lib/modules/manager/npm/detect.ts",
|
||||
"lib/modules/manager/npm/extract/index.ts",
|
||||
"lib/modules/manager/npm/extract/locked-versions.ts",
|
||||
"lib/modules/manager/npm/extract/monorepo.ts",
|
||||
"lib/modules/manager/npm/extract/npm.ts",
|
||||
"lib/modules/manager/npm/extract/pnpm.ts",
|
||||
"lib/modules/manager/npm/extract/utils.ts",
|
||||
"lib/modules/manager/npm/extract/yarn.ts",
|
||||
"lib/modules/manager/npm/index.ts",
|
||||
"lib/modules/manager/npm/post-update/index.ts",
|
||||
"lib/modules/manager/npm/post-update/lerna.ts",
|
||||
"lib/modules/manager/npm/post-update/node-version.ts",
|
||||
"lib/modules/manager/npm/post-update/npm.ts",
|
||||
"lib/modules/manager/npm/post-update/pnpm.ts",
|
||||
"lib/modules/manager/npm/post-update/yarn.ts",
|
||||
"lib/modules/manager/npm/range.ts",
|
||||
"lib/modules/manager/npm/update/dependency/index.ts",
|
||||
"lib/modules/manager/npm/update/index.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/common/parent-version.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/index.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/package-lock/dep-constraints.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/package-lock/get-locked.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/package-lock/index.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/yarn-lock/index.ts",
|
||||
"lib/modules/manager/npm/update/locked-dependency/yarn-lock/replace.ts",
|
||||
"lib/modules/manager/npm/update/package-version/index.ts",
|
||||
"lib/modules/platform/api.ts",
|
||||
"lib/modules/platform/azure/azure-got-wrapper.ts",
|
||||
"lib/modules/platform/azure/azure-helper.ts",
|
||||
|
|
Loading…
Reference in a new issue