Skip to content

fix(core): unbreak pnpm 11 installs by acknowledging build-script deps from generators - #36302

Merged
FrozenPandaz merged 38 commits into
masterfrom
fix/pnpm11-generated-allow-builds
Jul 16, 2026
Merged

fix(core): unbreak pnpm 11 installs by acknowledging build-script deps from generators#36302
FrozenPandaz merged 38 commits into
masterfrom
fix/pnpm11-generated-allow-builds

Conversation

@FrozenPandaz

Copy link
Copy Markdown
Contributor

Current Behavior

pnpm 11 fails installs with ERR_PNPM_IGNORED_BUILDS when a dependency's build scripts are neither allowed nor denied. Workspaces generated by create-nx-workspace only allow nx, so any flow that pulls in a build-script dependency hard-fails: jest 30 pulls in unrs-resolver (via jest-resolve), vite pulls in esbuild, swc setups pull in @swc/core, etc. This breaks preset installs for real pnpm 11 users and is the dominant cause of the nightly E2E matrix failures (~70 of 139 jobs die in newProject()): https://github.com/nrwl/nx/actions/runs/28642151329

Three more nightly root causes ride along:

  • When a plugin throws a non-Error value, formatAggregateCreateNodesError crashes with Cannot read properties of undefined (reading 'split'), masking the real error (js-strip-types failures).
  • @angular/cli@22.0.5 raised its Node floor to ^22.22.3 || ^24.15.0, so ng new refuses to run on the matrix's pinned Node 22.13.0 / 24.0.0 (e2e-nx-init, e2e-angular).
  • e2e tests pnpm add plugins directly (no generator runs first), so they hit the strict build gate regardless of generator fixes.

Expected Behavior

  • Generators that introduce build-script dependencies record the allowBuilds decision in pnpm-workspace.yaml before their install task runs, via a new comment-preserving acknowledgePnpmBuildScripts helper (exposed through @nx/devkit/internal): jest acknowledges unrs-resolver, vite/esbuild acknowledge esbuild, swc setups acknowledge @swc/core, nest acknowledges @nestjs/core (all false = skipped, matching pnpm 10 behavior since they ship prebuilt binaries or only print funding messages); cypress and detox set true because their install scripts are required to function. Entries the user already set are never overwritten; the helper no-ops for non-pnpm workspaces and pnpm < 11. Generated workspaces no longer preseed entries for dependencies they may never have.
  • Non-Error createNodes failures are coerced to Errors in the AggregateCreateNodesError constructor so the real failure always surfaces.
  • The e2e matrix pins Node 22.22.3 / 24.15.0, satisfying the Angular CLI floor.
  • e2e-created pnpm/lerna workspaces are seeded with strictDepBuilds: false (pnpm 10's warn-and-skip behavior) since tests install plugins without running generators first.

Known gap (documented in the commit): nx add <plugin> installs the plugin package before its init generator runs, so a plugin whose own dependency tree carries a build-script package (e.g. @nx/jestjest-resolveunrs-resolver) still surfaces pnpm's approve-builds error in that flow.

Related Issue(s)

Nightly E2E matrix failure: https://github.com/nrwl/nx/actions/runs/28642151329


View session information ↗

@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 2a46ca6
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/6a5823382929740008dda888
😎 Deploy Preview https://deploy-preview-36302--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 2a46ca6
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6a58233812403b00081f5da8
😎 Deploy Preview https://deploy-preview-36302--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@polygraph-app
polygraph-app Bot marked this pull request as ready for review July 10, 2026 19:52
@polygraph-app
polygraph-app Bot requested a review from a team as a code owner July 10, 2026 19:52
@polygraph-app
polygraph-app Bot requested a review from AgentEnder July 10, 2026 19:52
@nx-cloud

nx-cloud Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit b2b4148

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 8m 39s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 3s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 57s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 18s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 7s View ↗
nx affected -t e2e-macos-local --parallel=1 --b... ✅ Succeeded 1m 17s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-16 00:31:00 UTC

@AgentEnder
AgentEnder force-pushed the fix/pnpm11-generated-allow-builds branch 2 times, most recently from a2c39f5 to 025ae23 Compare July 13, 2026 14:06
nx-cloud[bot]

This comment was marked as outdated.

@FrozenPandaz
FrozenPandaz force-pushed the fix/pnpm11-generated-allow-builds branch 2 times, most recently from 4b6fff2 to 4eb02a1 Compare July 13, 2026 15:52
nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

@FrozenPandaz
FrozenPandaz force-pushed the fix/pnpm11-generated-allow-builds branch from 1e9180a to 180addf Compare July 15, 2026 15:50
nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

FrozenPandaz and others added 11 commits July 15, 2026 17:13
A plugin that throws a non-Error value (or an error that loses its
message crossing the plugin worker boundary) crashed
formatAggregateCreateNodesError with "Cannot read properties of
undefined (reading 'split')", masking the real failure. Coerce tuple
values to Errors in the AggregateCreateNodesError constructor and fall
back to the message when a deserialized error has no stack.
@angular/cli 22.0.5 requires node ^22.22.3 || ^24.15.0 || >=26, so ng new
refuses to run on the previously pinned 22.13.0 / 24.0.0 and every
e2e-nx-init and e2e-angular combo fails.
… add build-script deps

pnpm 11 fails installs with ERR_PNPM_IGNORED_BUILDS when a dependency's
build scripts are neither allowed nor denied, so generators that
introduce such dependencies now record the decision in
pnpm-workspace.yaml before their install task runs: jest acknowledges
unrs-resolver, vite and esbuild acknowledge esbuild, swc setups
acknowledge @swc/core, nest acknowledges @nestjs/core (all skipped,
matching pnpm 10 behavior since they ship prebuilt binaries or only
print funding messages), while cypress and detox allow their builds
because those scripts are required for the tools to function. The
comment-preserving helper never overwrites existing user entries and
no-ops for non-pnpm workspaces and pnpm < 11.

Note: 'nx add <plugin>' installs the plugin package before its init
generator runs, so a plugin whose own dependency tree carries a
build-script package (e.g. @nx/jest -> jest-resolve -> unrs-resolver)
still surfaces pnpm's approve-builds error in that flow.
e2e tests pnpm-add plugins without running a generator first, so pnpm
11's strict build gate fails those installs before any allowBuilds
entry can be recorded. Seed e2e-created pnpm and lerna workspaces with
strictDepBuilds: false to restore pnpm 10's warn-and-skip behavior in
the test environment.
'nx add <plugin>' and 'nx init' install packages before any plugin
generator can record allowBuilds decisions, so pnpm 11's strict build
gate failed them: the plugin's own dependency tree can carry
build-script packages (e.g. @nx/jest -> jest-resolve -> unrs-resolver),
and nx itself has a postinstall that existing repos have not
acknowledged.

- nx init records 'allowBuilds: nx: true' when it adds nx to an
  existing pnpm 11 workspace (acknowledgePnpmBuildScripts now accepts a
  filesystem root as well as a Tree).
- nx add and nx init run their bootstrap installs with
  --config.strictDepBuilds=false, restoring pnpm 10's warn-and-skip
  behavior for that one install; the plugin init generators that run
  right after record the durable allowBuilds entries.
Rename acknowledgePnpmBuildScripts to acknowledgeBuildScripts and require
callers to pass their PackageManager instead of inferring pnpm from the
presence of pnpm-workspace.yaml. The generic entry no-ops for package
managers other than pnpm (they run build scripts unconditionally) and
delegates to a pnpm-specific function that records allowBuilds entries.
Replace the strictDepBuilds: false seed in e2e-created pnpm workspaces
with --config.strictDepBuilds=false on the harness's raw install
commands (packageInstall, the post-copy reinstall, and the lerna
workspace bootstrap). Generator-driven installs inside tests stay
strict, so e2e still fails if a generator forgets to record its
allowBuilds entry.
runInstall and addDepsToPackageJson now take the PackageManager instead
of re-detecting it internally; each init/import flow detects once and
passes it down.
…s in repos without one

With the package manager passed in explicitly, the file's absence no
longer doubles as pnpm detection. Single-package pnpm repos without a
pnpm-workspace.yaml (e.g. nx init targets) now get the file created
with the allowBuilds entries, mirroring what pnpm approve-builds does.
…s in repos without one [Self-Healing CI Rerun]
…init flows

add-nx-to-monorepo, add-nx-to-nest, and the angular init now detect the
package manager once and pass it to addDepsToPackageJson and runInstall,
matching the other init flows.
- pnpm 11 ignores .npmrc prefer-frozen-lockfile, so set
  pnpm_config_frozen_lockfile=false at the env level
- npx strips protected _authToken env keys, so npm publish needs the
  local registry token in the workspace .npmrc
pnpm 11 no longer reads the pnpm field in package.json, so the override
forcing lerna to use the locally published nx was silently ignored and
the smoke test ran against the npmjs-published nx instead.
- ts-solution tarball snapshots: sorted contents now list dist/README.md
  before dist/index.* (path sort added in the release publish executor)
- lerna smoke: pnpm 11 no longer echoes the script command, so strip the
  echo line for every package manager instead of normalizing it
The nightly job env duplicated the pnpm_config_* settings that
global-setup already puts on process.env for everything jest spawns;
the outer pnpm handoff passes its implicit checks against the repo's
committed allowBuilds without softening.
…Json

Every call site passes it, and most passed undefined just to skip past
the optional additionalPackages param.
…ites

Slicing the field fed raw ranges like ^11 or latest into semver.gte,
which throws; parseVersionFromPackageManagerField returns null for
non-exact pins so the version is probed from pnpm itself instead.
AgentEnder added a commit that referenced this pull request Jul 15, 2026
#36359)

## Current Behavior

Name-ref sentinels (used to keep `dependsOn`/`inputs` project references
correct across renames) are written back through a pointer to the array
they were created in. Merges copy sentinels **by reference** into fresh
arrays — most visibly when a project.json pattern target (e.g.
`e2e-ci--**/**`) with a `"..."` spread is applied to every matching
atomized target. The copies never get resolved, leaving raw internal
objects (`RootRef { value, parent, targetPart }`) in the final project
configuration, and task graph creation crashes with:

```
NX   pattern is not iterable
```

## Expected Behavior

Every name ref resolves to its project name wherever it ends up.
`applySubstitutions` now sweeps the merged rootMap and resolves each
sentinel in place, covering arrays a sentinel was copied into. Since
write-back no longer depends on back-references, the `parent`/`key`
fields, the `allRefs` registry, and the parent-rebinding branches are
removed.

The new integration test reproduces the exact corruption on the previous
implementation (raw `RootRef` objects in the atomized targets'
`dependsOn`) and passes with the sweep.

## Related Issue(s)

Found while using `"..."` in the `dependsOn` of atomized e2e pattern
targets in this repo (see `e2e/gradle/project.json` /
`e2e/maven/project.json`); that cleanup was reverted from #36302 and can
be re-applied once this fix ships.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Qjm3xvLS2vLRsaxt4vv56d

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/PR-for-pnpm-11-ERR_PNPM_IGNORED_BUILDS-fix-f71af2eb)
<!-- polygraph-session-end -->

---------

Co-authored-by: Craigory Coppola <craigorycoppola@gmail.com>
@FrozenPandaz
FrozenPandaz force-pushed the fix/pnpm11-generated-allow-builds branch from fecb261 to d3ab8e5 Compare July 15, 2026 21:16
nx-cloud[bot]

This comment was marked as outdated.

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a flaky task in your failed CI:

🔂 Since the failure was identified as flaky, we triggered a CI rerun by adding an empty commit to this branch.

Nx Cloud View detailed reasoning in Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

@FrozenPandaz
FrozenPandaz merged commit e380258 into master Jul 16, 2026
18 checks passed
@FrozenPandaz
FrozenPandaz deleted the fix/pnpm11-generated-allow-builds branch July 16, 2026 12:55
AgentEnder added a commit that referenced this pull request Jul 17, 2026
#36359)

## Current Behavior

Name-ref sentinels (used to keep `dependsOn`/`inputs` project references
correct across renames) are written back through a pointer to the array
they were created in. Merges copy sentinels **by reference** into fresh
arrays — most visibly when a project.json pattern target (e.g.
`e2e-ci--**/**`) with a `"..."` spread is applied to every matching
atomized target. The copies never get resolved, leaving raw internal
objects (`RootRef { value, parent, targetPart }`) in the final project
configuration, and task graph creation crashes with:

```
NX   pattern is not iterable
```

## Expected Behavior

Every name ref resolves to its project name wherever it ends up.
`applySubstitutions` now sweeps the merged rootMap and resolves each
sentinel in place, covering arrays a sentinel was copied into. Since
write-back no longer depends on back-references, the `parent`/`key`
fields, the `allRefs` registry, and the parent-rebinding branches are
removed.

The new integration test reproduces the exact corruption on the previous
implementation (raw `RootRef` objects in the atomized targets'
`dependsOn`) and passes with the sweep.

## Related Issue(s)

Found while using `"..."` in the `dependsOn` of atomized e2e pattern
targets in this repo (see `e2e/gradle/project.json` /
`e2e/maven/project.json`); that cleanup was reverted from #36302 and can
be re-applied once this fix ships.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Qjm3xvLS2vLRsaxt4vv56d

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/PR-for-pnpm-11-ERR_PNPM_IGNORED_BUILDS-fix-f71af2eb)
<!-- polygraph-session-end -->

---------

Co-authored-by: Craigory Coppola <craigorycoppola@gmail.com>
FrozenPandaz added a commit that referenced this pull request Jul 20, 2026
#36359)

## Current Behavior

Name-ref sentinels (used to keep `dependsOn`/`inputs` project references
correct across renames) are written back through a pointer to the array
they were created in. Merges copy sentinels **by reference** into fresh
arrays — most visibly when a project.json pattern target (e.g.
`e2e-ci--**/**`) with a `"..."` spread is applied to every matching
atomized target. The copies never get resolved, leaving raw internal
objects (`RootRef { value, parent, targetPart }`) in the final project
configuration, and task graph creation crashes with:

```
NX   pattern is not iterable
```

## Expected Behavior

Every name ref resolves to its project name wherever it ends up.
`applySubstitutions` now sweeps the merged rootMap and resolves each
sentinel in place, covering arrays a sentinel was copied into. Since
write-back no longer depends on back-references, the `parent`/`key`
fields, the `allRefs` registry, and the parent-rebinding branches are
removed.

The new integration test reproduces the exact corruption on the previous
implementation (raw `RootRef` objects in the atomized targets'
`dependsOn`) and passes with the sweep.

## Related Issue(s)

Found while using `"..."` in the `dependsOn` of atomized e2e pattern
targets in this repo (see `e2e/gradle/project.json` /
`e2e/maven/project.json`); that cleanup was reverted from #36302 and can
be re-applied once this fix ships.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Qjm3xvLS2vLRsaxt4vv56d

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/PR-for-pnpm-11-ERR_PNPM_IGNORED_BUILDS-fix-f71af2eb)
<!-- polygraph-session-end -->

---------

Co-authored-by: Craigory Coppola <craigorycoppola@gmail.com>
(cherry picked from commit 4a05b10)
FrozenPandaz added a commit that referenced this pull request Jul 20, 2026
…s from generators (#36302)

## Current Behavior

pnpm 11 fails installs with `ERR_PNPM_IGNORED_BUILDS` when a
dependency's build scripts are neither allowed nor denied. Workspaces
generated by `create-nx-workspace` only allow `nx`, so any flow that
pulls in a build-script dependency hard-fails: jest 30 pulls in
`unrs-resolver` (via `jest-resolve`), vite pulls in `esbuild`, swc
setups pull in `@swc/core`, etc. This breaks preset installs for real
pnpm 11 users and is the dominant cause of the nightly E2E matrix
failures (~70 of 139 jobs die in `newProject()`):
https://github.com/nrwl/nx/actions/runs/28642151329

Three more nightly root causes ride along:

- When a plugin throws a non-Error value,
`formatAggregateCreateNodesError` crashes with `Cannot read properties
of undefined (reading 'split')`, masking the real error (js-strip-types
failures).
- `@angular/cli@22.0.5` raised its Node floor to `^22.22.3 || ^24.15.0`,
so `ng new` refuses to run on the matrix's pinned Node 22.13.0 / 24.0.0
(e2e-nx-init, e2e-angular).
- e2e tests `pnpm add` plugins directly (no generator runs first), so
they hit the strict build gate regardless of generator fixes.

## Expected Behavior

- Generators that introduce build-script dependencies record the
`allowBuilds` decision in `pnpm-workspace.yaml` before their install
task runs, via a new comment-preserving `acknowledgePnpmBuildScripts`
helper (exposed through `@nx/devkit/internal`): jest acknowledges
`unrs-resolver`, vite/esbuild acknowledge `esbuild`, swc setups
acknowledge `@swc/core`, nest acknowledges `@nestjs/core` (all `false` =
skipped, matching pnpm 10 behavior since they ship prebuilt binaries or
only print funding messages); cypress and detox set `true` because their
install scripts are required to function. Entries the user already set
are never overwritten; the helper no-ops for non-pnpm workspaces and
pnpm < 11. Generated workspaces no longer preseed entries for
dependencies they may never have.
- Non-Error `createNodes` failures are coerced to Errors in the
`AggregateCreateNodesError` constructor so the real failure always
surfaces.
- The e2e matrix pins Node 22.22.3 / 24.15.0, satisfying the Angular CLI
floor.
- e2e-created pnpm/lerna workspaces are seeded with `strictDepBuilds:
false` (pnpm 10's warn-and-skip behavior) since tests install plugins
without running generators first.

Known gap (documented in the commit): `nx add <plugin>` installs the
plugin package before its init generator runs, so a plugin whose own
dependency tree carries a build-script package (e.g. `@nx/jest` →
`jest-resolve` → `unrs-resolver`) still surfaces pnpm's `approve-builds`
error in that flow.

## Related Issue(s)

Nightly E2E matrix failure:
https://github.com/nrwl/nx/actions/runs/28642151329

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/PR-for-pnpm-11-ERR_PNPM_IGNORED_BUILDS-fix-f71af2eb)
<!-- polygraph-session-end -->

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
(cherry picked from commit e380258)
FrozenPandaz pushed a commit that referenced this pull request Jul 20, 2026
## Current Behavior

The `e2e-docker` project depends on the `local-registry` target, while
its `populate-local-registry-storage` dependency pulls in
`local-registry-e2e`. Both serve verdaccio on port 4873, so the two
tasks start milliseconds apart and race for the port. Verdaccio's
busy-port fallback does not save this: both probe the port before either
has bound, and the loser then fails at bind time with `EADDRINUSE`,
which fails the run before any test executes. The nightly docker npm and
pnpm jobs have failed this way on every run since #36302 landed.

## Expected Behavior

`e2e-docker` depends on `local-registry-e2e`, the same target every
other e2e project uses, so only one verdaccio server starts.

## Implementation Details

#36302 introduced `local-registry-e2e` and migrated `nx.json`,
`e2e/gradle/project.json` and `e2e/maven/project.json`, but left
`e2e/docker/project.json` on the old target.

Verified against the task graph (`nx run e2e-docker:e2e-local
--graph=<file>`): `@nx/nx-source:local-registry` is gone from both the
task list and `continuousDependencies`, and
`@nx/nx-source:local-registry-e2e` remains. A full e2e-docker run was
not executed locally.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/fix-e2e-docker-local-registry-target-ecd65894)
<!-- polygraph-session-end -->
FrozenPandaz pushed a commit that referenced this pull request Jul 20, 2026
…ollup (#36412)

## Current Behavior

Configuring rollup with the swc compiler adds `@swc/core` to
`package.json` without recording a build-script decision for it. pnpm 11
refuses to install a dependency whose build scripts are neither allowed
nor denied, so the install that follows the generator fails.

#36302 added these acknowledgements across the generators that pull in
`@swc/core`, including `@nx/js`, but missed this call site.

## Expected Behavior

The generator records the decision alongside the dependency, matching
what `@nx/js` already does, so the install succeeds.

The build script is denied rather than allowed: `@swc/core`'s
postinstall only fetches a wasm fallback for platforms its prebuilt
optional dependencies do not cover, so there is nothing to run on a
supported platform. Existing decisions in `pnpm-workspace.yaml` are
never overwritten, and this is a no-op for npm, yarn, bun, and for pnpm
below 11.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/fix-jest-swc-core-peer-1fe697de)
<!-- polygraph-session-end -->
FrozenPandaz added a commit that referenced this pull request Jul 28, 2026
…istry (#36482)

## Current Behavior

Four e2e targets declare their own per-test-file `dependsOn` in
`project.json`:

```json
"e2e-macos-ci--src/detox.test.ts": {
  "dependsOn": ["nx:build-native", "@nx/nx-source:populate-local-registry-storage"],
  "inputs": ["e2eInputs", "^production"]
}
```

These date back to #23429 (May 2024), when no e2e `targetDefault`
declared a `dependsOn` at all and every test file spelled out its own.
`@nx/nx-source:local-registry-e2e` did not exist then — it was added in
#36302, renamed from `local-registry`.

Because `dependsOn` replaces rather than merges, these overrides
silently drop the registry once it moved into `targetDefaults`:

```
nx.json  e2e-macos-ci--**/*  ->  [populate-local-registry-storage, local-registry-e2e]
resolved e2e-macos-ci--src/detox.test.ts  ->  [nx:build-native, populate-local-registry-storage]
```

For the two `e2e/detox` targets that is a real hang.
`populate-local-registry-storage` is the only thing anchoring the
continuous registry task, and `cleanUpUnneededContinuousTasks` keeps a
continuous task alive only while some *incomplete* task lists it in
`continuousDependencies`. The detox targets don't, so verdaccio is
killed the moment `populate` completes — before the detox task even
starts. Its Jest `globalSetup` then polls `http://localhost:4873` in a
`while (true)` loop with no timeout, so the agent spins until the job's
`timeout-minutes` fires with no diagnostic.

The `e2e/node` and `e2e/js` entries name test files that no longer exist
(`src/webpack.test.ts` → `node-webpack.test.ts`,
`src/js-generators.test.ts` → `js-generators.ts`), so they materialize
as unreachable ghost targets.

The sibling e2e projects that need an extra dependency get this right by
appending to the full list rather than replacing it:

```
e2e/gradle -> [populate, local-registry-e2e, :gradle-project-graph:gradle:publishToMavenLocal]
e2e/maven  -> [populate, local-registry-e2e, nx-maven-plugin:install]
e2e/docker -> [populate, local-registry-e2e, start-docker-registry]
```

## Expected Behavior

All four overrides are removed, so every per-file e2e target inherits
the `targetDefaults` and gets the registry back.

`nx:build-native` is not lost — it is already covered transitively:

```
populate-local-registry-storage
  -> dependsOn { target: build, projects: [tag:npm:public] }     project.json
  -> nx:build -> build-base                                      packages/nx/project.json
  -> build-base dependsOn ['^build-base', 'build-native', ...]   nx.json targetDefaults
```

`nx` carries the `npm:public` tag from nx's own package-json plugin, so
it is in that set — and publishing to the local registry has to build nx
regardless.

Verified with `nx show project` before and after:

| target | before | after |
| --- | --- | --- |
| `e2e-detox:e2e-macos-ci--src/detox.test.ts` | `[build-native,
populate]` — no registry | `[populate, local-registry-e2e]` |
| `e2e-detox:e2e-macos-ci--src/detox-legacy.test.ts` | `[build-native,
populate]` — no registry | `[populate, local-registry-e2e]` |
| `e2e-node:e2e-ci--src/webpack.test.ts` | ghost target | removed |
| `e2e-js:e2e-ci--src/js-generators.test.ts` | ghost target | removed |

Every per-file e2e target across the three projects now resolves with
`local-registry-e2e`, and no ghost targets remain. `inputs` were already
identical to the defaults (`["e2eInputs", "^production"]`) for the detox
targets, so nothing else changes.

## Related Issue(s)

N/A — internal CI configuration fix, no linked issue.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Restore-local-registry-dependency-for-e2e-target-overrides-88ebe0ee)
<!-- polygraph-session-end -->

Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
FrozenPandaz pushed a commit that referenced this pull request Jul 29, 2026
## Current Behavior

The `e2e-docker` project depends on the `local-registry` target, while
its `populate-local-registry-storage` dependency pulls in
`local-registry-e2e`. Both serve verdaccio on port 4873, so the two
tasks start milliseconds apart and race for the port. Verdaccio's
busy-port fallback does not save this: both probe the port before either
has bound, and the loser then fails at bind time with `EADDRINUSE`,
which fails the run before any test executes. The nightly docker npm and
pnpm jobs have failed this way on every run since #36302 landed.

## Expected Behavior

`e2e-docker` depends on `local-registry-e2e`, the same target every
other e2e project uses, so only one verdaccio server starts.

## Implementation Details

#36302 introduced `local-registry-e2e` and migrated `nx.json`,
`e2e/gradle/project.json` and `e2e/maven/project.json`, but left
`e2e/docker/project.json` on the old target.

Verified against the task graph (`nx run e2e-docker:e2e-local
--graph=<file>`): `@nx/nx-source:local-registry` is gone from both the
task list and `continuousDependencies`, and
`@nx/nx-source:local-registry-e2e` remains. A full e2e-docker run was
not executed locally.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/fix-e2e-docker-local-registry-target-ecd65894)
<!-- polygraph-session-end -->

(cherry picked from commit d196355)
FrozenPandaz pushed a commit that referenced this pull request Jul 29, 2026
…ollup (#36412)

## Current Behavior

Configuring rollup with the swc compiler adds `@swc/core` to
`package.json` without recording a build-script decision for it. pnpm 11
refuses to install a dependency whose build scripts are neither allowed
nor denied, so the install that follows the generator fails.

#36302 added these acknowledgements across the generators that pull in
`@swc/core`, including `@nx/js`, but missed this call site.

## Expected Behavior

The generator records the decision alongside the dependency, matching
what `@nx/js` already does, so the install succeeds.

The build script is denied rather than allowed: `@swc/core`'s
postinstall only fetches a wasm fallback for platforms its prebuilt
optional dependencies do not cover, so there is nothing to run on a
supported platform. Existing decisions in `pnpm-workspace.yaml` are
never overwritten, and this is a no-op for npm, yarn, bun, and for pnpm
below 11.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/fix-jest-swc-core-peer-1fe697de)
<!-- polygraph-session-end -->

(cherry picked from commit 866a107)
FrozenPandaz added a commit that referenced this pull request Jul 29, 2026
…istry (#36482)

## Current Behavior

Four e2e targets declare their own per-test-file `dependsOn` in
`project.json`:

```json
"e2e-macos-ci--src/detox.test.ts": {
  "dependsOn": ["nx:build-native", "@nx/nx-source:populate-local-registry-storage"],
  "inputs": ["e2eInputs", "^production"]
}
```

These date back to #23429 (May 2024), when no e2e `targetDefault`
declared a `dependsOn` at all and every test file spelled out its own.
`@nx/nx-source:local-registry-e2e` did not exist then — it was added in
#36302, renamed from `local-registry`.

Because `dependsOn` replaces rather than merges, these overrides
silently drop the registry once it moved into `targetDefaults`:

```
nx.json  e2e-macos-ci--**/*  ->  [populate-local-registry-storage, local-registry-e2e]
resolved e2e-macos-ci--src/detox.test.ts  ->  [nx:build-native, populate-local-registry-storage]
```

For the two `e2e/detox` targets that is a real hang.
`populate-local-registry-storage` is the only thing anchoring the
continuous registry task, and `cleanUpUnneededContinuousTasks` keeps a
continuous task alive only while some *incomplete* task lists it in
`continuousDependencies`. The detox targets don't, so verdaccio is
killed the moment `populate` completes — before the detox task even
starts. Its Jest `globalSetup` then polls `http://localhost:4873` in a
`while (true)` loop with no timeout, so the agent spins until the job's
`timeout-minutes` fires with no diagnostic.

The `e2e/node` and `e2e/js` entries name test files that no longer exist
(`src/webpack.test.ts` → `node-webpack.test.ts`,
`src/js-generators.test.ts` → `js-generators.ts`), so they materialize
as unreachable ghost targets.

The sibling e2e projects that need an extra dependency get this right by
appending to the full list rather than replacing it:

```
e2e/gradle -> [populate, local-registry-e2e, :gradle-project-graph:gradle:publishToMavenLocal]
e2e/maven  -> [populate, local-registry-e2e, nx-maven-plugin:install]
e2e/docker -> [populate, local-registry-e2e, start-docker-registry]
```

## Expected Behavior

All four overrides are removed, so every per-file e2e target inherits
the `targetDefaults` and gets the registry back.

`nx:build-native` is not lost — it is already covered transitively:

```
populate-local-registry-storage
  -> dependsOn { target: build, projects: [tag:npm:public] }     project.json
  -> nx:build -> build-base                                      packages/nx/project.json
  -> build-base dependsOn ['^build-base', 'build-native', ...]   nx.json targetDefaults
```

`nx` carries the `npm:public` tag from nx's own package-json plugin, so
it is in that set — and publishing to the local registry has to build nx
regardless.

Verified with `nx show project` before and after:

| target | before | after |
| --- | --- | --- |
| `e2e-detox:e2e-macos-ci--src/detox.test.ts` | `[build-native,
populate]` — no registry | `[populate, local-registry-e2e]` |
| `e2e-detox:e2e-macos-ci--src/detox-legacy.test.ts` | `[build-native,
populate]` — no registry | `[populate, local-registry-e2e]` |
| `e2e-node:e2e-ci--src/webpack.test.ts` | ghost target | removed |
| `e2e-js:e2e-ci--src/js-generators.test.ts` | ghost target | removed |

Every per-file e2e target across the three projects now resolves with
`local-registry-e2e`, and no ghost targets remain. `inputs` were already
identical to the defaults (`["e2eInputs", "^production"]`) for the detox
targets, so nothing else changes.

## Related Issue(s)

N/A — internal CI configuration fix, no linked issue.

<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Restore-local-registry-dependency-for-e2e-target-overrides-88ebe0ee)
<!-- polygraph-session-end -->

Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
(cherry picked from commit 4894978)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants