diff --git a/lib/datasource/npm/npmrc.ts b/lib/datasource/npm/npmrc.ts index 41179ec1ac05059df0fcf4ef64dbd76b1a0f1715..ca83c7c17cd9dc07823ec72f74074be59cfb5504 100644 --- a/lib/datasource/npm/npmrc.ts +++ b/lib/datasource/npm/npmrc.ts @@ -87,7 +87,8 @@ export function setNpmrc(input?: string): void { npmrc[key] = envReplace(npmrc[key]); sanitize(key, npmrc[key]); } - } else { + } else if (npmrc) { + logger.debug('Resetting npmrc'); npmrc = null; npmrcRaw = null; } diff --git a/lib/datasource/npm/releases.ts b/lib/datasource/npm/releases.ts index ef724d708f103097b13bdfeaa57da83d09293e39..e26a83b42db27915c109c2a13438a68d16b72058 100644 --- a/lib/datasource/npm/releases.ts +++ b/lib/datasource/npm/releases.ts @@ -1,4 +1,3 @@ -import is from '@sindresorhus/is'; import type { GetReleasesConfig, ReleaseResult } from '../types'; import { getDependency } from './get'; import { setNpmrc } from './npmrc'; @@ -7,7 +6,7 @@ export async function getReleases({ lookupName, npmrc, }: GetReleasesConfig): Promise<ReleaseResult | null> { - if (is.string(npmrc)) { + if (npmrc) { setNpmrc(npmrc); } const res = await getDependency(lookupName); diff --git a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap index bff6a74c0161605ded6bfd9559d8d38199116ca2..b071d9868a4c09321003c9afa3f154075efd6005 100644 --- a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap +++ b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap @@ -11,6 +11,7 @@ Object { "skipReason": "invalid-name", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -18,7 +19,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "app", @@ -135,6 +135,7 @@ Object { "prettyDepType": "engine", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -142,7 +143,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "library", @@ -299,6 +299,7 @@ Object { "sourceUrl": "https://github.com/owner/n", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -306,7 +307,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "app", @@ -349,6 +349,7 @@ Object { "skipReason": "unknown-version", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -356,7 +357,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "app", @@ -410,6 +410,7 @@ Object { "skipReason": "unknown-volta", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -417,7 +418,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "library", @@ -465,6 +465,7 @@ Object { "skipReason": "unknown-version", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -472,7 +473,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": undefined, "packageJsonName": undefined, "packageJsonType": "library", @@ -602,6 +602,7 @@ Object { "prettyDepType": "resolutions", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -609,7 +610,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "1.0.0", "packageJsonName": "renovate", "packageJsonType": "app", @@ -739,6 +739,7 @@ Object { "prettyDepType": "resolutions", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": "yarn", "lernaPackages": undefined, "managerData": Object { @@ -746,7 +747,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "1.0.0", "packageJsonName": "renovate", "packageJsonType": "app", @@ -876,14 +876,14 @@ Object { "prettyDepType": "resolutions", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { "lernaJsonFile": undefined, }, "npmLock": undefined, - "npmrc": "", - "packageFile": "package.json", + "npmrc": undefined, "packageFileVersion": "1.0.0", "packageJsonName": "renovate", "packageJsonType": "app", @@ -899,6 +899,7 @@ exports[`manager/npm/extract .extractPackageFile() finds complex yarn workspaces Object { "constraints": Object {}, "deps": Array [], + "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -906,7 +907,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "0.0.8", "packageJsonName": "@a/b", "packageJsonType": "app", @@ -1038,6 +1038,7 @@ Object { "prettyDepType": "resolutions", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -1045,7 +1046,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "1.0.0", "packageJsonName": "renovate", "packageJsonType": "app", @@ -1061,6 +1061,7 @@ exports[`manager/npm/extract .extractPackageFile() finds simple yarn workspaces Object { "constraints": Object {}, "deps": Array [], + "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -1068,7 +1069,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "0.0.8", "packageJsonName": "@a/b", "packageJsonType": "app", @@ -1086,6 +1086,7 @@ exports[`manager/npm/extract .extractPackageFile() finds simple yarn workspaces Object { "constraints": Object {}, "deps": Array [], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -1093,7 +1094,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "0.0.8", "packageJsonName": "@a/b", "packageJsonType": "app", @@ -1225,6 +1225,7 @@ Object { "prettyDepType": "resolutions", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -1232,7 +1233,6 @@ Object { }, "npmLock": undefined, "npmrc": undefined, - "packageFile": "package.json", "packageFileVersion": "1.0.0", "packageJsonName": "renovate", "packageJsonType": "app", diff --git a/lib/manager/npm/extract/index.spec.ts b/lib/manager/npm/extract/index.spec.ts index 69ac38e6cb49fcee57fbc3236352badc7ab0633b..a61147a19391d6cbb9757e394199f19d94d44a40 100644 --- a/lib/manager/npm/extract/index.spec.ts +++ b/lib/manager/npm/extract/index.spec.ts @@ -80,7 +80,7 @@ describe('manager/npm/extract', () => { const res = await npmExtract.extractPackageFile( input01Content, 'package.json', - { ...defaultConfig, npmrc: 'some-npmrc' } + defaultConfig ); expect(res).toMatchSnapshot(); }); @@ -94,7 +94,7 @@ describe('manager/npm/extract', () => { const res = await npmExtract.extractPackageFile( input01Content, 'package.json', - { ...defaultConfig, ignoreNpmrcFile: true } + defaultConfig ); expect(res).toMatchSnapshot(); }); @@ -125,7 +125,7 @@ describe('manager/npm/extract', () => { 'package.json', {} ); - expect(res.npmrc).toEqual(''); + expect(res.npmrc).toBeUndefined(); }); it('finds lerna', async () => { fs.readLocalFile = jest.fn((fileName) => { diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index 88fcc5a2e598fb54e7dfee66769bb6c6c31c9cc3..33dd844c441586fa5cd49b507bdc2954ebfd9c98 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -6,7 +6,11 @@ import * as datasourceGithubTags from '../../../datasource/github-tags'; import { id as npmId } from '../../../datasource/npm'; import { logger } from '../../../logger'; import { SkipReason } from '../../../types'; -import { getSiblingFileName, readLocalFile } from '../../../util/fs'; +import { + deleteLocalFile, + getSiblingFileName, + readLocalFile, +} from '../../../util/fs'; import * as nodeVersioning from '../../../versioning/node'; import { isValid, isVersion } from '../../../versioning/npm'; import type { @@ -91,30 +95,23 @@ export async function extractPackageFile( delete lockFiles.shrinkwrapJson; let npmrc: string; + let ignoreNpmrcFile: boolean; const npmrcFileName = getSiblingFileName(fileName, '.npmrc'); - if (is.string(config.npmrc)) { - logger.debug('Using configured npmrc'); - } else if (config.ignoreNpmrcFile) { - npmrc = ''; + // istanbul ignore if + if (config.ignoreNpmrcFile) { + await deleteLocalFile(npmrcFileName); } else { npmrc = await readLocalFile(npmrcFileName, 'utf8'); - if (is.string(npmrc)) { - if (npmrc.includes('package-lock')) { - logger.debug( - { npmrcFileName }, - 'Stripping package-lock setting from .npmrc' - ); - npmrc = npmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); - } + if (npmrc?.includes('package-lock')) { + logger.debug('Stripping package-lock setting from npmrc'); + npmrc = npmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); + } + if (npmrc) { if (npmrc.includes('=${') && getAdminConfig().trustLevel !== 'high') { - logger.debug( - { npmrcFileName }, - 'Discarding .npmrc lines with variables' - ); - npmrc = npmrc - .split('\n') - .filter((line) => !line.includes('=${')) - .join('\n'); + logger.debug('Discarding .npmrc file with variables'); + ignoreNpmrcFile = true; + npmrc = undefined; + await deleteLocalFile(npmrcFileName); } } else { npmrc = undefined; @@ -361,12 +358,12 @@ export async function extractPackageFile( } return { - packageFile: fileName, deps, packageJsonName, packageFileVersion, packageJsonType, npmrc, + ignoreNpmrcFile, yarnrc, ...lockFiles, managerData: { @@ -394,13 +391,15 @@ export async function extractAllPackageFiles( ): Promise<PackageFile[]> { const npmFiles: PackageFile[] = []; for (const packageFile of packageFiles) { - // const npmrc = ini.parse((config.npmrc || '').replace(/\\n/g, '\n')); const content = await readLocalFile(packageFile, 'utf8'); // istanbul ignore else if (content) { - const res = await extractPackageFile(content, packageFile, config); - if (res) { - npmFiles.push(res); + const deps = await extractPackageFile(content, packageFile, config); + if (deps) { + npmFiles.push({ + packageFile, + ...deps, + }); } } else { logger.debug({ packageFile }, 'packageFile has no content'); diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts index 64d5ef21d0f8bcb81366e8ae5a0ef42cfc59d777..62305f5d49d6839c31c6a66ea342b2de3c77c74a 100644 --- a/lib/manager/npm/post-update/index.ts +++ b/lib/manager/npm/post-update/index.ts @@ -138,18 +138,29 @@ export async function writeExistingFiles( ); const npmrc: string = packageFile.npmrc || config.npmrc; const npmrcFilename = upath.join(basedir, '.npmrc'); - if (is.string(npmrc)) { - await outputFile(npmrcFilename, `${npmrc}\n`); + if (npmrc) { + try { + await outputFile(npmrcFilename, `${npmrc}\n`); + } catch (err) /* istanbul ignore next */ { + logger.warn({ npmrcFilename, err }, 'Error writing .npmrc'); + } + } else if (config.ignoreNpmrcFile) { + logger.debug('Removing ignored .npmrc file before artifact generation'); + await remove(npmrcFilename); } if (packageFile.yarnrc) { logger.debug(`Writing .yarnrc to ${basedir}`); const yarnrcFilename = upath.join(basedir, '.yarnrc'); - await outputFile( - yarnrcFilename, - packageFile.yarnrc - .replace('--install.pure-lockfile true', '') - .replace('--install.frozen-lockfile true', '') - ); + try { + await outputFile( + yarnrcFilename, + packageFile.yarnrc + .replace('--install.pure-lockfile true', '') + .replace('--install.frozen-lockfile true', '') + ); + } catch (err) /* istanbul ignore next */ { + logger.warn({ yarnrcFilename, err }, 'Error writing .yarnrc'); + } } const { npmLock } = packageFile; if (npmLock) { @@ -293,10 +304,14 @@ async function updateNpmrcContent( const newNpmrc = originalContent ? [originalContent, ...additionalLines] : additionalLines; - const newContent = newNpmrc.join('\n'); - if (newContent !== originalContent) { - logger.debug(`Writing updated .npmrc file to ${npmrcFilePath}`); - await writeFile(npmrcFilePath, `${newContent}\n`); + 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'); } } diff --git a/lib/manager/types.ts b/lib/manager/types.ts index 600fb7b300e9e1f96264ba8676cff27c9544bea2..1d8693d3fe51414dbb0d356cda6fdde876ce422d 100644 --- a/lib/manager/types.ts +++ b/lib/manager/types.ts @@ -24,7 +24,6 @@ export interface ExtractConfig extends ManagerConfig { gradle?: { timeout?: number }; aliases?: Record<string, string>; ignoreNpmrcFile?: boolean; - npmrc?: string; yarnrc?: string; skipInstalls?: boolean; versioning?: string; @@ -86,6 +85,7 @@ export interface PackageFile<T = Record<string, any>> datasource?: string; registryUrls?: string[]; deps: PackageDependency[]; + ignoreNpmrcFile?: boolean; lernaClient?: string; lernaPackages?: string[]; mavenProps?: Record<string, any>; diff --git a/lib/util/cache/repository/index.ts b/lib/util/cache/repository/index.ts index adfdab5d3781fe32721f5866a9dcfe83f50504f6..58fb957469b7ee7f8607a165126bf6dfdc7baa7a 100644 --- a/lib/util/cache/repository/index.ts +++ b/lib/util/cache/repository/index.ts @@ -9,7 +9,7 @@ import type { PackageFile } from '../../../manager/types'; import type { RepoInitConfig } from '../../../workers/repository/init/common'; // Increment this whenever there could be incompatibilities between old and new cache structure -export const CACHE_REVISION = 7; +export const CACHE_REVISION = 8; export interface BaseBranchCache { sha: string; // branch commit sha diff --git a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap index 52bad56bc98bae5470aaa15e69a8b3c9cba47a82..7b05cb15e52b9f236495581a3a6c26835f863c16 100644 --- a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap +++ b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap @@ -14,6 +14,7 @@ Array [ "prettyDepType": "dependency", }, ], + "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object {