feat(exec): add missing support for executionEnv (#8411)

close #8356
This commit is contained in:
Khải
2024-08-13 06:51:36 +07:00
committed by GitHub
parent 417af7763c
commit 0ffb3adcfe
3 changed files with 95 additions and 4 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-script-runners": major
"pnpm": minor
---
`pnpm exec` now supports executionEnv [#8356](https://github.com/pnpm/pnpm/issues/8356).

View File

@@ -5,6 +5,7 @@ import { type Config, types } from '@pnpm/config'
import { makeNodeRequireOption } from '@pnpm/lifecycle'
import { logger } from '@pnpm/logger'
import { tryReadProjectManifest } from '@pnpm/read-project-manifest'
import { prepareExecutionEnv } from '@pnpm/plugin-commands-env'
import { sortPackages } from '@pnpm/sort-packages'
import { type Project, type ProjectsGraph, type ProjectRootDir, type ProjectRootDirRealPath } from '@pnpm/types'
import execa from 'execa'
@@ -136,12 +137,15 @@ export type ExecOpts = Required<Pick<Config, 'selectedProjectsGraph'>> & {
reportSummary?: boolean
implicitlyFellbackFromRun?: boolean
} & Pick<Config,
| 'bin'
| 'dir'
| 'extraBinPaths'
| 'extraEnv'
| 'lockfileDir'
| 'modulesDir'
| 'nodeOptions'
| 'pnpmHomeDir'
| 'rawConfig'
| 'recursive'
| 'reporterHidePrefix'
| 'userAgent'
@@ -196,15 +200,23 @@ export async function handler (
const workspacePnpPath = opts.workspaceDir && existsPnp(opts.workspaceDir)
let exitCode = 0
const prependPaths = [
'./node_modules/.bin',
...opts.extraBinPaths,
]
const mapPrefixToPrependPaths: Record<ProjectRootDir, string[]> = {}
await Promise.all(chunks.flat().map(async prefix => {
const executionEnv = await prepareExecutionEnv(opts, {
extraBinPaths: opts.extraBinPaths,
executionEnv: opts.selectedProjectsGraph[prefix]?.package.manifest.pnpm?.executionEnv,
})
mapPrefixToPrependPaths[prefix] = [
'./node_modules/.bin',
...executionEnv.extraBinPaths,
]
}))
const reporterShowPrefix = opts.recursive && opts.reporterHidePrefix === false
for (const chunk of chunks) {
// eslint-disable-next-line no-await-in-loop
await Promise.all(chunk.map(async (prefix) =>
limitRun(async () => {
const prependPaths = mapPrefixToPrependPaths[prefix]
result[prefix].status = 'running'
const startTime = process.hrtime()
try {

73
pnpm/test/exec.ts Normal file
View File

@@ -0,0 +1,73 @@
import { prepare, preparePackages } from '@pnpm/prepare'
import { execPnpmSync } from './utils'
test('exec with executionEnv', async () => {
prepare({
name: 'test',
version: '0.0.0',
pnpm: {
executionEnv: {
nodeVersion: '18.0.0',
},
},
})
const output = execPnpmSync(['exec', 'node', '--version']).stdout.toString().trim()
expect(output).toStrictEqual('v18.0.0')
})
test('recursive exec when some packages define different executionEnv', async () => {
preparePackages([
{
name: 'node-version-undefined',
version: '0.0.0',
},
{
name: 'node-version-18',
version: '0.0.0',
pnpm: {
executionEnv: {
nodeVersion: '18.0.0',
},
},
},
{
name: 'node-version-20',
version: '0.0.0',
pnpm: {
executionEnv: {
nodeVersion: '20.0.0',
},
},
},
])
const execNodePrintVersion = (extraOptions: string[]) =>
execPnpmSync([
...extraOptions,
'--recursive',
'--reporter-hide-prefix',
'exec',
'node',
'--print',
'">>> " + require("./package.json").name + ": " + process.version',
])
.stdout
.toString()
.trim()
.split('\n')
.filter(x => x.startsWith('>>> '))
.sort()
expect(execNodePrintVersion([])).toStrictEqual([
'>>> node-version-18: v18.0.0',
'>>> node-version-20: v20.0.0',
`>>> node-version-undefined: ${process.version}`,
])
expect(execNodePrintVersion(['--use-node-version=19.0.0'])).toStrictEqual([
'>>> node-version-18: v18.0.0',
'>>> node-version-20: v20.0.0',
'>>> node-version-undefined: v19.0.0',
])
})