mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-12 16:12:02 -05:00
fix(deploy): inherit pnpm from the root manifest (#8991)
* fix(deploy): inherit `pnpm` from the root manifest * fix: eslint * refactor: share code * test: add * fix: eslint * fix: remove duplicate dep from package.json
This commit is contained in:
8
.changeset/funny-coins-applaud.md
Normal file
8
.changeset/funny-coins-applaud.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@pnpm/constants": minor
|
||||
"@pnpm/find-packages": patch
|
||||
"@pnpm/plugin-commands-deploy": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
`pnpm deploy` should inherit the `pnpm` object from the root `package.json` [#8991](https://github.com/pnpm/pnpm/pull/8991).
|
||||
@@ -16,3 +16,5 @@ export const WORKSPACE_MANIFEST_FILENAME = 'pnpm-workspace.yaml'
|
||||
export const ABBREVIATED_META_DIR = 'metadata-v1.3'
|
||||
export const FULL_META_DIR = 'metadata-full-v1.3' // This is currently not used at all
|
||||
export const FULL_FILTERED_META_DIR = 'metadata-v1.3'
|
||||
|
||||
export const USEFUL_NON_ROOT_PNPM_FIELDS = ['executionEnv'] as const
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -6181,6 +6181,9 @@ importers:
|
||||
'@pnpm/config':
|
||||
specifier: workspace:*
|
||||
version: link:../../config/config
|
||||
'@pnpm/constants':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/constants
|
||||
'@pnpm/dependency-path':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/dependency-path
|
||||
@@ -7918,6 +7921,9 @@ importers:
|
||||
'@pnpm/cli-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../cli/cli-utils
|
||||
'@pnpm/constants':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/constants
|
||||
'@pnpm/fs.find-packages':
|
||||
specifier: workspace:*
|
||||
version: link:../../fs/find-packages
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"@pnpm/cli-utils": "workspace:*",
|
||||
"@pnpm/common-cli-options-help": "workspace:*",
|
||||
"@pnpm/config": "workspace:*",
|
||||
"@pnpm/constants": "workspace:*",
|
||||
"@pnpm/dependency-path": "workspace:*",
|
||||
"@pnpm/directory-fetcher": "workspace:*",
|
||||
"@pnpm/error": "workspace:*",
|
||||
|
||||
@@ -2,6 +2,7 @@ import path from 'path'
|
||||
import url from 'url'
|
||||
import normalizePath from 'normalize-path'
|
||||
import pick from 'ramda/src/pick'
|
||||
import { USEFUL_NON_ROOT_PNPM_FIELDS } from '@pnpm/constants'
|
||||
import * as dp from '@pnpm/dependency-path'
|
||||
import {
|
||||
type DirectoryResolution,
|
||||
@@ -42,7 +43,8 @@ export interface CreateDeployFilesOptions {
|
||||
deployDir: string
|
||||
lockfile: LockfileObject
|
||||
lockfileDir: string
|
||||
manifest: DeployManifest
|
||||
rootProjectManifest?: Pick<ProjectManifest, 'pnpm'>
|
||||
selectedProjectManifest: DeployManifest
|
||||
projectId: ProjectId
|
||||
rootProjectManifestDir: string
|
||||
}
|
||||
@@ -57,7 +59,8 @@ export function createDeployFiles ({
|
||||
deployDir,
|
||||
lockfile,
|
||||
lockfileDir,
|
||||
manifest,
|
||||
rootProjectManifest,
|
||||
selectedProjectManifest,
|
||||
projectId,
|
||||
rootProjectManifestDir,
|
||||
}: CreateDeployFilesOptions): DeployFiles {
|
||||
@@ -141,12 +144,13 @@ export function createDeployFiles ({
|
||||
packages: targetPackageSnapshots,
|
||||
},
|
||||
manifest: {
|
||||
...pick(INHERITED_MANIFEST_KEYS, manifest),
|
||||
...pick(INHERITED_MANIFEST_KEYS, selectedProjectManifest),
|
||||
dependencies: targetSnapshot.dependencies,
|
||||
devDependencies: targetSnapshot.devDependencies,
|
||||
optionalDependencies: targetSnapshot.optionalDependencies,
|
||||
pnpm: {
|
||||
...manifest.pnpm,
|
||||
...rootProjectManifest?.pnpm,
|
||||
...pick(USEFUL_NON_ROOT_PNPM_FIELDS, selectedProjectManifest.pnpm ?? {}),
|
||||
overrides: undefined, // the effects of package overrides should already be part of the package snapshots
|
||||
patchedDependencies: undefined,
|
||||
packageExtensions: undefined, // the effects of the package extensions should already be part of the package snapshots
|
||||
|
||||
@@ -181,6 +181,7 @@ async function deployFromSharedLockfile (
|
||||
const {
|
||||
allProjects,
|
||||
lockfileDir,
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir,
|
||||
workspaceDir,
|
||||
} = opts
|
||||
@@ -202,7 +203,8 @@ async function deployFromSharedLockfile (
|
||||
deployDir,
|
||||
lockfile,
|
||||
lockfileDir,
|
||||
manifest: selectedProject.manifest,
|
||||
rootProjectManifest,
|
||||
selectedProjectManifest: selectedProject.manifest,
|
||||
projectId,
|
||||
rootProjectManifestDir,
|
||||
})
|
||||
|
||||
@@ -255,6 +255,103 @@ test('deploy with a shared lockfile after full install', async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('the deploy manifest should inherit the pnpm object from the root manifest and the manifest of the selected project', async () => {
|
||||
const preparedManifests: Record<'root' | 'project-0', ProjectManifest> = {
|
||||
root: {
|
||||
name: 'root',
|
||||
version: '0.0.0',
|
||||
private: true,
|
||||
pnpm: {
|
||||
onlyBuiltDependencies: ['from-root'],
|
||||
overrides: {
|
||||
'is-positive': '2.0.0',
|
||||
},
|
||||
executionEnv: {
|
||||
nodeVersion: '20.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
'project-0': {
|
||||
name: 'project-0',
|
||||
version: '0.0.0',
|
||||
private: true,
|
||||
dependencies: {
|
||||
'is-positive': '3.1.0',
|
||||
},
|
||||
pnpm: {
|
||||
onlyBuiltDependencies: ['from-project-0'],
|
||||
overrides: {
|
||||
'is-positive': '=1.0.0',
|
||||
},
|
||||
executionEnv: {
|
||||
nodeVersion: '18.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
preparePackages([
|
||||
{
|
||||
location: '.',
|
||||
package: preparedManifests.root,
|
||||
},
|
||||
preparedManifests['project-0'],
|
||||
])
|
||||
|
||||
const {
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
selectedProjectsGraph,
|
||||
} = await filterPackagesFromDir(process.cwd(), [{ namePattern: 'project-0' }])
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
allProjectsGraph,
|
||||
selectedProjectsGraph: allProjectsGraph,
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
lockfileDir: process.cwd(),
|
||||
workspaceDir: process.cwd(),
|
||||
})
|
||||
expect(fs.existsSync('pnpm-lock.yaml')).toBeTruthy()
|
||||
|
||||
await deploy.handler({
|
||||
...DEFAULT_OPTS,
|
||||
allProjects,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest: preparedManifests.root,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
recursive: true,
|
||||
selectedProjectsGraph,
|
||||
sharedWorkspaceLockfile: true,
|
||||
lockfileDir: process.cwd(),
|
||||
workspaceDir: process.cwd(),
|
||||
}, ['deploy'])
|
||||
|
||||
const project = assertProject(path.resolve('deploy'))
|
||||
project.has('is-positive')
|
||||
|
||||
const manifest = readPackageJson('deploy') as ProjectManifest
|
||||
expect(manifest.pnpm).toStrictEqual({
|
||||
onlyBuiltDependencies: preparedManifests.root.pnpm!.onlyBuiltDependencies,
|
||||
executionEnv: preparedManifests['project-0'].pnpm!.executionEnv,
|
||||
} as ProjectManifest['pnpm'])
|
||||
expect(manifest.pnpm?.overrides).toBeUndefined() // by design
|
||||
|
||||
expect(readPackageJson('deploy/node_modules/is-positive/')).toHaveProperty(['version'], preparedManifests.root.pnpm!.overrides!['is-positive'])
|
||||
expect(project.readLockfile().importers).toStrictEqual({
|
||||
'.': {
|
||||
dependencies: {
|
||||
'is-positive': {
|
||||
specifier: preparedManifests.root.pnpm!.overrides!['is-positive'],
|
||||
version: preparedManifests.root.pnpm!.overrides!['is-positive'],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as LockfileFile['importers'])
|
||||
})
|
||||
|
||||
test('deploy with a shared lockfile and --prod filter should not fail even if dev workspace package does not exist (#8778)', async () => {
|
||||
preparePackages([
|
||||
{
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
{
|
||||
"path": "../../lockfile/types"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/constants"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/dependency-path"
|
||||
},
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/workspace/find-packages#readme",
|
||||
"dependencies": {
|
||||
"@pnpm/cli-utils": "workspace:*",
|
||||
"@pnpm/constants": "workspace:*",
|
||||
"@pnpm/fs.find-packages": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"@pnpm/util.lex-comparator": "catalog:"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { packageIsInstallable } from '@pnpm/cli-utils'
|
||||
import { USEFUL_NON_ROOT_PNPM_FIELDS } from '@pnpm/constants'
|
||||
import { type ProjectManifest, type Project, type SupportedArchitectures } from '@pnpm/types'
|
||||
import { lexCompare } from '@pnpm/util.lex-comparator'
|
||||
import { findPackages } from '@pnpm/fs.find-packages'
|
||||
@@ -64,7 +65,7 @@ export async function findWorkspacePackagesNoCheck (workspaceRoot: string, opts?
|
||||
const uselessNonRootManifestFields: Array<keyof ProjectManifest> = ['resolutions']
|
||||
|
||||
type ProjectManifestPnpm = Required<ProjectManifest>['pnpm']
|
||||
const usefulNonRootPnpmFields: Array<keyof ProjectManifestPnpm> = ['executionEnv']
|
||||
const usefulNonRootPnpmFields: ReadonlyArray<keyof ProjectManifestPnpm> = USEFUL_NON_ROOT_PNPM_FIELDS
|
||||
|
||||
function checkNonRootProjectManifest ({ manifest, rootDir }: Project): void {
|
||||
const warn = printNonRootFieldWarning.bind(null, rootDir)
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
{
|
||||
"path": "../../fs/find-packages"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/constants"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/logger"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user