Skip to content

Guard node_modules cache against missing native optional-dep binaries#324064

Draft
Giuspepe wants to merge 2 commits into
mainfrom
harden-node-modules-cache
Draft

Guard node_modules cache against missing native optional-dep binaries#324064
Giuspepe wants to merge 2 commits into
mainfrom
harden-node-modules-cache

Conversation

@Giuspepe

@Giuspepe Giuspepe commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Why

Follow-up hardening for #323881. Some dependencies ship their native binary as a per-platform optional dependency of a small launcher package — e.g. @openai/codex is only a launcher shim, and the real binary lives in @openai/codex-<platform>-<arch>. npm install/npm ci do not fail when an optional dependency can't be installed, so a transient hiccup can leave the launcher present while the platform binary is missing. That broken tree then gets frozen into the shared node_modules cache and served to every consumer (this is exactly what poisoned the Linux cache and broke the Codex smoke test).

There is no npm flag to make an optional-dependency install failure fatal (and npm can't tell a legitimate platform-skip from a failed fetch), so the only reliable guard is an explicit post-install check.

What

  • Add build/azure-pipelines/common/checkNativeOptionalDeps.ts: after npm ci, verify the current platform's expected native binary exists. If the launcher package is present but its per-platform binary is missing, exit non-zero with an actionable message. If the launcher isn't installed at all, it's a no-op.
  • Run it in the linux, macOS and windows cache-build jobs of pr-node-modules.yml, after the root npm ci and before the cache is saved (gated on a cache miss, i.e. only when an install actually ran).

Result: a node_modules cache missing a required native binary can never be saved — the job fails loudly at build time instead of silently poisoning every downstream consumer.

The check is data-driven (a small list of native optional deps), so adding future ones (e.g. other bundled native SDKs) is a one-line change.

Notes

  • Currently covers @openai/codex. compile/copilot cache jobs are out of scope (their caches aren't consumed where the codex binary is required).

Some deps ship their native binary as a per-platform *optional* dependency of a
small launcher package (e.g. `@openai/codex` -> `@openai/codex-<platform>-<arch>`).
npm does not fail when an optional dependency can't be installed, so a transient
hiccup can leave the launcher present but the binary missing — and that broken
tree then gets frozen into the shared node_modules cache and served to every
consumer (see #323881).

Add build/azure-pipelines/common/checkNativeOptionalDeps.ts and run it after
`npm ci` in the linux, macOS and windows cache-build jobs (before the cache is
saved). It fails the job when a launcher package is present but its platform
binary is missing, so a poisoned cache is never saved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 2, 2026 14:36

Copilot AI 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.

Pull request overview

Hardens the node_modules cache build workflow by adding a post-npm ci guard that detects when a launcher package is present but its platform-specific native optional-dependency binary is missing, preventing poisoned caches from being saved and reused across jobs.

Changes:

  • Added a data-driven native optional-dependency verifier script (checkNativeOptionalDeps.ts) that checks for expected binaries under vendor/*/bin/ when the launcher package is installed.
  • Integrated the verification step into Linux, macOS, and Windows pr-node-modules cache-build jobs on cache misses, before saving the cache.
Show a summary per file
File Description
build/azure-pipelines/common/checkNativeOptionalDeps.ts Adds a post-install check that fails the cache build if required native optional-dependency binaries are missing.
.github/workflows/pr-node-modules.yml Runs the new verifier after npm ci (on cache misses) and before saving node_modules caches on Linux/macOS/Windows.

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Low

@Giuspepe Giuspepe force-pushed the harden-node-modules-cache branch from 16ff12e to 40dc39c Compare July 2, 2026 14:49
DO NOT MERGE — dropped before this PR is ready. Adds a branch trigger and bumps
build/.cachesalt to force a cache miss so npm ci + the verify step actually run;
no binary is removed, so the verify step should pass on all platforms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants