fix: replacing env variables to values in .npmrc (#5623)

close #5604
close #2570

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
Dmitriy Dudkevich
2022-11-11 23:50:56 +03:00
committed by GitHub
parent a276532641
commit 3dab7f83c2
11 changed files with 102 additions and 64 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/config": minor
---
New function added: `readLocalConfig(dir: string)`.

View File

@@ -0,0 +1,7 @@
---
"@pnpm/plugin-commands-installation": patch
"@pnpm/plugin-commands-rebuild": patch
"pnpm": patch
---
Replace environment variable placeholders with their values, when reading `.npmrc` files in subdirectories inside a workspace [#2570](https://github.com/pnpm/pnpm/issues/2570).

View File

@@ -32,15 +32,17 @@
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/config#readme",
"dependencies": {
"@pnpm/config.env-replace": "1.0.0",
"@pnpm/constants": "workspace:*",
"@pnpm/error": "workspace:*",
"@pnpm/git-utils": "workspace:*",
"@pnpm/matcher": "workspace:*",
"@pnpm/npm-conf": "2.0.2",
"@pnpm/npm-conf": "2.0.4",
"@pnpm/pnpmfile": "workspace:*",
"@pnpm/read-project-manifest": "workspace:*",
"@pnpm/types": "workspace:*",
"camelcase": "^6.3.0",
"camelcase-keys": "^6.2.2",
"can-write-to-dir": "^1.1.1",
"is-subdir": "^1.2.0",
"is-windows": "^1.0.2",
@@ -48,6 +50,7 @@
"path-absolute": "^1.0.1",
"path-name": "^1.0.0",
"ramda": "npm:@pnpm/ramda@0.28.1",
"read-ini-file": "^3.1.0",
"realpath-missing": "^1.1.0",
"which": "^2.0.2"
},

View File

@@ -25,6 +25,8 @@ import {
} from './Config'
import { getWorkspaceConcurrency } from './concurrency'
export * from './readLocalConfig'
export { Config, UniversalOptions }
const npmDefaults = loadNpmConf.defaults

View File

@@ -0,0 +1,31 @@
import path from 'path'
import camelcaseKeys from 'camelcase-keys'
import { envReplace } from '@pnpm/config.env-replace'
import readIniFile from 'read-ini-file'
export async function readLocalConfig (prefix: string) {
try {
const ini = await readIniFile(path.join(prefix, '.npmrc')) as Record<string, string>
const config = camelcaseKeys(ini) as (Record<string, string> & { hoist?: boolean })
if (config.shamefullyFlatten) {
config.hoistPattern = '*'
// TODO: print a warning
}
if (config.hoist === false) {
config.hoistPattern = ''
}
for (const [key, val] of Object.entries(config)) {
if (typeof val === 'string') {
try {
config[key] = envReplace(val, process.env)
} catch (err) {
// ignore
}
}
}
return config
} catch (err: any) { // eslint-disable-line
if (err.code !== 'ENOENT') throw err
return {}
}
}

View File

@@ -89,7 +89,6 @@
"@zkochan/rimraf": "^2.1.2",
"@zkochan/table": "^1.0.0",
"@zkochan/which": "^2.0.3",
"camelcase-keys": "^6.2.2",
"chalk": "^4.1.2",
"enquirer": "^2.3.6",
"is-ci": "^3.0.1",
@@ -101,7 +100,6 @@
"path-absolute": "^1.0.1",
"path-exists": "^4.0.0",
"ramda": "npm:@pnpm/ramda@0.28.1",
"read-ini-file": "^3.1.0",
"render-help": "^1.0.2",
"version-selector-type": "^3.0.0"
},

View File

@@ -4,7 +4,7 @@ import {
RecursiveSummary,
throwOnCommandFail,
} from '@pnpm/cli-utils'
import { Config } from '@pnpm/config'
import { Config, readLocalConfig } from '@pnpm/config'
import { PnpmError } from '@pnpm/error'
import { arrayOfWorkspacePackagesToMap } from '@pnpm/find-workspace-packages'
import { logger } from '@pnpm/logger'
@@ -29,12 +29,10 @@ import {
mutateModules,
ProjectOptions,
} from '@pnpm/core'
import camelcaseKeys from 'camelcase-keys'
import isSubdir from 'is-subdir'
import mem from 'mem'
import pFilter from 'p-filter'
import pLimit from 'p-limit'
import readIniFile from 'read-ini-file'
import { getOptionsFromRootManifest } from './getOptionsFromRootManifest'
import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './updateWorkspaceDependencies'
import { updateToLatestSpecsFromManifest, createLatestSpecs } from './updateToLatestSpecsFromManifest'
@@ -425,24 +423,6 @@ async function unlinkPkgs (dependencyNames: string[], manifest: ProjectManifest,
)
}
async function readLocalConfig (prefix: string) {
try {
const ini = await readIniFile(path.join(prefix, '.npmrc')) as Record<string, string>
const config = camelcaseKeys(ini) as (Record<string, string> & { hoist?: boolean })
if (config.shamefullyFlatten) {
config.hoistPattern = '*'
// TODO: print a warning
}
if (config.hoist === false) {
config.hoistPattern = ''
}
return config
} catch (err: any) { // eslint-disable-line
if (err.code !== 'ENOENT') throw err
return {}
}
}
function calculateRepositoryRoot (
workspaceDir: string,
projectDirs: string[]

View File

@@ -658,6 +658,36 @@ test('recursive install in a monorepo with different modules directories', async
await projects['project-2'].has('is-positive', 'modules_2')
})
test('recursive install in a monorepo with parsing env variables', async () => {
const projects = preparePackages([
{
name: 'project',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
},
},
])
process.env['SOME_NAME'] = 'some_name'
// eslint-disable-next-line no-template-curly-in-string
await fs.writeFile('project/.npmrc', 'modules-dir=${SOME_NAME}_modules', 'utf8')
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
await install.handler({
...DEFAULT_OPTS,
allProjects,
allProjectsGraph,
dir: process.cwd(),
recursive: true,
selectedProjectsGraph,
workspaceDir: process.cwd(),
})
await projects['project'].has('is-positive', `${process.env['SOME_NAME']}_modules`)
})
test('prefer-workspace-package', async () => {
await addDistTag({
distTag: 'latest',

View File

@@ -66,13 +66,11 @@
"@pnpm/store-connection-manager": "workspace:*",
"@pnpm/store-controller-types": "workspace:*",
"@pnpm/types": "workspace:*",
"camelcase-keys": "^6.2.2",
"dependency-path": "workspace:*",
"load-json-file": "^6.2.0",
"mem": "^8.1.1",
"p-limit": "^3.1.0",
"ramda": "npm:@pnpm/ramda@0.28.1",
"read-ini-file": "^3.1.0",
"render-help": "^1.0.2",
"run-groups": "^3.0.1",
"semver": "^7.3.8"

View File

@@ -1,20 +1,18 @@
import path from 'path'
import {
RecursiveSummary,
throwOnCommandFail,
} from '@pnpm/cli-utils'
import {
Config,
readLocalConfig,
} from '@pnpm/config'
import { arrayOfWorkspacePackagesToMap } from '@pnpm/find-workspace-packages'
import { logger } from '@pnpm/logger'
import { sortPackages } from '@pnpm/sort-packages'
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
import { Project, ProjectManifest } from '@pnpm/types'
import camelcaseKeys from 'camelcase-keys'
import mem from 'mem'
import pLimit from 'p-limit'
import readIniFile from 'read-ini-file'
import { rebuildProjects as rebuildAll, RebuildOptions, rebuildSelectedPkgs } from './implementation'
type RecursiveRebuildOpts = CreateStoreControllerOptions & Pick<Config,
@@ -163,21 +161,3 @@ export async function recursiveRebuild (
throwOnFail(result)
}
async function readLocalConfig (prefix: string) {
try {
const ini = await readIniFile(path.join(prefix, '.npmrc')) as Record<string, string>
const config = camelcaseKeys(ini) as (Record<string, string> & { hoist?: boolean })
if (config.shamefullyFlatten) {
config.hoistPattern = '*'
// TODO: print a warning
}
if (config.hoist === false) {
config.hoistPattern = ''
}
return config
} catch (err: any) { // eslint-disable-line
if (err.code !== 'ENOENT') throw err
return {}
}
}

38
pnpm-lock.yaml generated
View File

@@ -465,6 +465,9 @@ importers:
packages/config:
dependencies:
'@pnpm/config.env-replace':
specifier: 1.0.0
version: 1.0.0
'@pnpm/constants':
specifier: workspace:*
version: link:../constants
@@ -478,8 +481,8 @@ importers:
specifier: workspace:*
version: link:../matcher
'@pnpm/npm-conf':
specifier: 2.0.2
version: 2.0.2
specifier: 2.0.4
version: 2.0.4
'@pnpm/pnpmfile':
specifier: workspace:*
version: link:../pnpmfile
@@ -492,6 +495,9 @@ importers:
camelcase:
specifier: ^6.3.0
version: 6.3.0
camelcase-keys:
specifier: ^6.2.2
version: 6.2.2
can-write-to-dir:
specifier: ^1.1.1
version: 1.1.1
@@ -513,6 +519,9 @@ importers:
ramda:
specifier: npm:@pnpm/ramda@0.28.1
version: /@pnpm/ramda/0.28.1
read-ini-file:
specifier: ^3.1.0
version: 3.1.0
realpath-missing:
specifier: ^1.1.0
version: 1.1.0
@@ -3355,9 +3364,6 @@ importers:
'@zkochan/which':
specifier: ^2.0.3
version: 2.0.3
camelcase-keys:
specifier: ^6.2.2
version: 6.2.2
chalk:
specifier: ^4.1.2
version: 4.1.2
@@ -3391,9 +3397,6 @@ importers:
ramda:
specifier: npm:@pnpm/ramda@0.28.1
version: /@pnpm/ramda/0.28.1
read-ini-file:
specifier: ^3.1.0
version: 3.1.0
render-help:
specifier: ^1.0.2
version: 1.0.2
@@ -3897,9 +3900,6 @@ importers:
'@pnpm/types':
specifier: workspace:*
version: link:../types
camelcase-keys:
specifier: ^6.2.2
version: 6.2.2
dependency-path:
specifier: workspace:*
version: link:../dependency-path
@@ -3915,9 +3915,6 @@ importers:
ramda:
specifier: npm:@pnpm/ramda@0.28.1
version: /@pnpm/ramda/0.28.1
read-ini-file:
specifier: ^3.1.0
version: 3.1.0
render-help:
specifier: ^1.0.2
version: 1.0.2
@@ -6869,6 +6866,11 @@ packages:
chalk: 4.1.2
dev: false
/@pnpm/config.env-replace/1.0.0:
resolution: {integrity: sha512-ZVPVDi1E8oeXlYqkGRtX0CkzLTwE2zt62bjWaWKaAvI8NZqHzlMvGeSNDpW+JB3+aKanYb4UETJOF1/CxGPemA==}
engines: {node: '>=12.22.0'}
dev: false
/@pnpm/config/16.0.0_kt75g7u7xait7ts3kctxzlcgqq:
resolution: {integrity: sha512-/KR8uQ1GWnnk3MciZbSWZG2VYzE/6WomekG7QdZ6iu3KT1YOJ0LGoSfbXCVKyirVZ748k5HIaLL51H7NsDPBLQ==}
engines: {node: '>=14.6'}
@@ -7477,10 +7479,11 @@ packages:
config-chain: 1.1.13
dev: true
/@pnpm/npm-conf/2.0.2:
resolution: {integrity: sha512-vp0T6HQcklEpSILEutr8o4Gxf3lIPJtxbDT1kGNyYo0ZVL1UGgazeaGr9rc4ut8veI7tiVCBr7cJbDgym/q3Kg==}
/@pnpm/npm-conf/2.0.4:
resolution: {integrity: sha512-xWjBhnntYvAjYt1alEoFJiThMe0ZhSY7iZuxBUR+DH3tH2RyGrP2KU75NZfo/jhc3dSBUqZrd1DnIIgkQ0WyKw==}
engines: {node: '>=12'}
dependencies:
'@pnpm/config.env-replace': 1.0.0
'@pnpm/network.ca-file': 1.0.1
config-chain: 1.1.13
dev: false
@@ -17154,13 +17157,14 @@ time:
/@commitlint/prompt-cli/17.1.2: '2022-08-29T07:53:18.629Z'
/@pnpm/byline/1.0.0: '2021-10-31T23:25:00.031Z'
/@pnpm/colorize-semver-diff/1.0.1: '2020-10-25T15:50:17.812Z'
/@pnpm/config.env-replace/1.0.0: '2022-11-11T20:22:17.274Z'
/@pnpm/exec/2.0.0: '2020-10-29T23:51:01.271Z'
/@pnpm/graph-sequencer/1.0.0: '2022-03-20T20:48:58.797Z'
/@pnpm/logger/5.0.0: '2022-10-14T13:56:04.285Z'
/@pnpm/meta-updater/0.2.1: '2022-10-17T23:32:30.921Z'
/@pnpm/network.agent/0.0.3: '2022-06-12T19:51:53.044Z'
/@pnpm/nopt/0.2.1: '2021-06-01T19:45:54.552Z'
/@pnpm/npm-conf/2.0.2: '2022-10-21T14:43:04.271Z'
/@pnpm/npm-conf/2.0.4: '2022-11-11T20:26:48.028Z'
/@pnpm/npm-lifecycle/2.0.0-1: '2022-02-21T22:36:47.308Z'
/@pnpm/npm-package-arg/1.0.0: '2022-06-28T12:48:31.287Z'
/@pnpm/os.env.path-extender/0.2.7: '2022-10-17T23:03:23.674Z'