fix: selectively revert changes to allProjectsGraph for legacy deploy

This commit is contained in:
Brandon Cheng
2025-03-26 02:04:29 -04:00
parent 46f10165ed
commit 190a2ec21a
2 changed files with 49 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-deploy": patch
pnpm: patch
---
A [change in pnpm v10.6.3](https://github.com/pnpm/pnpm/pull/9259) introduced new bugs in `pnpm deploy` running in legacy mode. (Legacy deploys are performed when `force-legacy-deploy=true` or the `--legacy` flag is used.) This change is now reverted for `pnpm deploy` in legacy mode.

View File

@@ -14,7 +14,7 @@ import rimraf from '@zkochan/rimraf'
import renderHelp from 'render-help'
import { deployHook } from './deployHook.js'
import { logger, globalWarn } from '@pnpm/logger'
import { type Project } from '@pnpm/types'
import { type ProjectsGraph, type Project } from '@pnpm/types'
import { createDeployFiles } from './createDeployFiles.js'
const FORCE_LEGACY_DEPLOY = 'force-legacy-deploy' satisfies keyof typeof configTypes
@@ -130,8 +130,44 @@ export async function handler (opts: DeployOptions, params: string[]): Promise<v
if (deployedProject) {
deployedProject.modulesDir = path.relative(selectedProject.rootDir, path.join(deployDir, 'node_modules'))
}
let allProjectsGraph: ProjectsGraph | undefined
// If inject-workspace-packages=false, this is considered a "legacy" deploy.
// Legacy deploy currently requires allProjectsGraph to only contain the
// deployed project and the root workspace project.
//
// For historical context, before pnpm v10.6.3, the allProjectsGraph always
// contained just the deployed project (and the root) for a pnpm deploy.
// Changes to how allProjectsGraph was computed in v10.6.3 caused the "pnpm
// deploy --legacy" command to break in some edge cases.
//
// - https://github.com/pnpm/pnpm/issues/9284
// - https://github.com/pnpm/pnpm/issues/9302
//
// This is a selective revert of https://github.com/pnpm/pnpm/pull/9259. It
// makes "pnpm deploy --legacy" behave more like it did before v10.6.3 to fix
// the bugs above.
//
// If the allProjectsGraph contains all projects, the legacy deploy process
// becomes confused in terms of which packages should be symlinked vs copied
// into the deploy directory. When inject-workspace-packages=true, this is not
// a problem since pnpm will know to always inject (i.e. copy) workspace
// packages into the deploy dir.
//
// When legacy deploy is removed, this special case should be removed. It may
// be possible to remove legacy deploy after no longer requiring users to set
// inject-workspace-packages=true in .npmrc.
if (!opts.injectWorkspacePackages && deployedProject != null) {
allProjectsGraph = {
[deployedProject.rootDir]: { dependencies: [], package: deployedProject },
...selectProjectByDir(opts.allProjects ?? [], opts.workspaceDir),
}
}
await install.handler({
...opts,
allProjectsGraph,
confirmModulesPurge: false,
// Deploy doesn't work with dedupePeerDependents=true currently as for deploy
// we need to select a single project for install, while dedupePeerDependents
@@ -289,3 +325,9 @@ As a workaround, add the following to pnpm-workspace.yaml:
return undefined
}
function selectProjectByDir (projects: Project[], searchedDir: string): ProjectsGraph | undefined {
const project = projects.find(({ rootDir }) => path.relative(rootDir, searchedDir) === '')
if (project == null) return undefined
return { [searchedDir]: { dependencies: [], package: project } }
}