Skip to content

chore(security): cool down npm installs and freeze the dev lockfile - #8629

Closed
BridgeAR wants to merge 41 commits into
BridgeAR/2026-05-09-remove-yarnfrom
BridgeAR/2026-05-25-supply-chain-cooldown
Closed

chore(security): cool down npm installs and freeze the dev lockfile#8629
BridgeAR wants to merge 41 commits into
BridgeAR/2026-05-09-remove-yarnfrom
BridgeAR/2026-05-25-supply-chain-cooldown

Conversation

@BridgeAR

Copy link
Copy Markdown
Member

What

Tightens the npm supply-chain attack surface on top of #8386:

  1. bunfig.toml + versions/bunfig.toml set minimumReleaseAge = 259200 (three days). Mirrors the existing cooldown.exclude: ["@datadog/*"] policy in .github/dependabot.yml.
  2. .github/actions/install/action.yml and benchmark/sirun/runall.sh use bun install --frozen-lockfile, so CI fails when bun.lock and package.json disagree.
  3. The four @datadog/native-* packages plus bun move out of the CLI's --trust flag into a declarative trustedDependencies in package.json (bun refuses --trust and --frozen-lockfile together).
  4. CONTRIBUTING.md documents the policy and the escape valve for urgent advisories.

Why

The npm supply-chain pattern that keeps repeating lands a compromised version on the registry, takes effect on the next CI install, and gets yanked once detection catches up — usually within hours, sometimes a day or two. Three days is enough lead time that most flagged releases get pulled before they reach our installs, and --frozen-lockfile makes the policy actually stick on every CI run (without it, a contributor who edits package.json without re-running bun install would silently resolve fresh against the registry and bypass the cooldown).

Escape valve

For an advisory whose patch is still inside the three-day window, a maintainer runs bun update <pkg>@<exact> --minimum-release-age=0 locally, commits the regenerated bun.lock, and calls out the override in the PR description. The override stays out of bunfig.toml so every bypass shows up in a reviewable diff.

Stacking

Based on #8386 (BridgeAR/2026-05-09-remove-yarn). The bunfig / lockfile / trustedDependencies changes only make sense once that PR's bun migration lands, so the base will move to master once #8386 merges.

Test plan

  • bun install --frozen-lockfile --linker=hoisted --network-concurrency 8 runs clean from a fresh node_modules/vendor (619 packages, 0 untrusted).
  • bun pm untrusted reports zero blocked lifecycle scripts after the install.
  • --frozen-lockfile errors on a genuinely new dep (verified locally with a throwaway addition).
  • scripts/test/no-yarn-dev-references.spec.js and scripts/test/install-plugin-modules.spec.js still pass.
  • CI on this branch.

BridgeAR added 30 commits May 25, 2026 00:43
Yarn 1.x is unmaintained. The root install in CI already runs bun
(`.github/actions/install/action.yml`); audit, size-report, flakiness,
release, and a few helper actions still shelled out to yarn. Make the
contract explicit so contributor installs match what CI runs: a root
`bunfig.toml` that forces the text lockfile and hoisted linker, the
lockfile committed (removed from `.gitignore`), and the install
action's cache step renamed (`yarn-cache` -> `install-cache`) and
keyed on `bun.lock`.

`audit.yml` swaps both `yarn audit` calls (root and vendor/) to
`bun audit`. The advisory set may differ; review and pin a baseline
if anything trips.
The per-plugin sandbox install relied on `workspaces.nohoist: ['**/**']`
(yarn 1) plus `installConfig.hoistingLimits = 'workspaces'` (yarn 2/3
for aerospike) to keep each `versions/<plugin>@<ver>/` sandbox isolated
from the others. Bun's `--linker=isolated` is the structural equivalent
and is now pinned in `versions/bunfig.toml` instead of re-declared in
every synthesized `package.json`.

Pre-resolving each declared range to its highest published version
before writing the synthesized `package.json` keeps matrix coverage
equivalent to yarn 1's prior behaviour. Yarn 1 picked the highest
matching version on each install; bun picks the lowest. Without
pre-resolution the raw-suffix sandboxes (`pino@4`, `mongodb@5`,
`pino@>=6.8.0`, ...) collapse onto the same versions as the coerced
ones (`pino@4.0.0`, `mongodb@5.0.0`, ...). The helper calls
`bun pm view <pkg>@<range> version --json`, caches per process, and
falls back to install-time resolution with a warning on registry
failure.

`scripts/test/install-plugin-modules.spec.js` spawns the install
script with yarn removed from `$PATH` and deep-equals each pino
sandbox's resolved version against its declared range.
`.github/workflows/install-smoke.yml` runs that test plus a cheap
pino plugin spec on every PR.
Three coordinated pieces:

1. 17 workflow/action files swap every `yarn run <script>` for
   `npm run <script>`, and `integration-tests/esbuild/package.json`'s
   `link` script swaps `yarn link` for `npm link`. The
   `yarn config set ignore-engines true` steps and per-line
   `--ignore-engines` flags go with them — yarn 1 enforced
   `engines.node` strictly, bun does not.
2. `scripts/check_licenses.js` walks `bun.lock` and
   `vendor/package-lock.json` directly instead of shelling out to
   `yarn list` + `npm list`. The lockfiles record the union of
   installed packages across platforms; `npm ls --omit=dev` only
   lists the optionals installed on the current host, so on
   Darwin/arm64 the cross-platform `@oxc-parser/binding-*` and its
   native helper transitives would report extraneous against the
   CSV.
3. `scripts/verify-exercised-tests.js` drops its yarn-detection
   paths now that workflows reference scripts only via `npm run`.

`platform.yml`'s `yarn` and `yarn-berry` matrix entries stay
untouched — they cover the user-PM contract, not the dev tooling.
Yarn 1.x is unmaintained. The docs build was the last install path
still on yarn. `docs/yarn.lock` is replaced with `docs/bun.lock` (text
format); TypeDoc and tsc still drive the build, so generated docs are
unchanged.
Yarn 1.x is unmaintained. The lockfile, the dedupe-bot jobs, the husky
hook, and the `yarn-deduplicate` devDep all exist only to keep yarn 1
healthy; with installs, run-scripts, and docs already on bun and npm,
they are accommodations to nothing. A cleanup without a regression
guard rots — yarn slips back in the next time a workflow or
contributor PR is reviewed without the migration in mind.

Three coordinated pieces:

1. Delete the dead yarn machinery: `yarn.lock`, `.yarnrc`, the
   `yarn-dedupe`/`yarn-dedupe-push` jobs in `project.yml` and their
   STS policy file under `.github/chainguard/`, the husky pre-commit
   hook, the `dependencies:dedupe` script and `yarn-deduplicate`
   devDep, the matching entry in the sirun startup require-preload
   list, and the `yarn-cache-` prefix on the install-action cache
   key (already keyed off `bun.lock`).
2. Update `.gitignore` (drop `yarn-debug.log*`, `yarn-error.log*`,
   `.yarn-integrity`; keep the `**/yarn.lock` entries the `next`
   plugin and appsec next fixtures still emit), the contributor
   docs (`CONTRIBUTING.md`, `AGENTS.md`), and the apm-integrations
   agent skill files.
3. Add `scripts/test/no-yarn-dev-references.spec.js`. Walks
   `git ls-files`, allowlists the four intentional yarn-reference
   categories (product-code user-PM detection, user-PM test
   fixtures, user-facing docs, and the regression-test specs that
   name yarn literally), and `assert.deepStrictEqual`s the
   offending list against `[]`. The `test:scripts` glob in
   `package.json` already covers it.

Drive-by fix:

* Drop the `bluebird@3.7.2` transitive entry from
  `packages/dd-trace/test/plugins/externals.js` under `moleculer`.
  Moleculer 0.14 (the fixture's pinned line) dropped its bluebird
  dep, so the entry installs an unused package.
* Tighten `release.yml`'s two docs-job `bun install` calls to
  `--frozen-lockfile`; both lockfiles are committed.
The packed `dd-trace.tgz` does not include `vendor/package-lock.json`
(the `files` field ships pre-built `vendor/dist/**` artifacts only),
so the `prepare` script (`cd vendor && npm ci --include=dev`) cannot
re-bootstrap vendor in a consumer install context. Yarn 1's `--prod`
mode skipped lifecycle scripts altogether; bun runs them by default.
`--ignore-scripts` matches the prior behaviour, and the script is not
needed for measuring the published package's install size.
Three coordinated fixes for the per-plugin sandbox install:

1. `--linker=isolated` placed every dependency under
   `versions/node_modules/.bun/<pkg>@<ver>/` and only symlinked the
   declared dep into each sandbox. Cross-workspace `require()` walks
   from inside one sandbox could not reach a sibling's package, so
   moleculer's runtime `require('bluebird')` fallback returned
   `Cannot find module`. Switching to `linker = "hoisted"` lifts
   shared deps to `versions/node_modules/<pkg>` while still nesting
   different versions under their owning sandbox; matrix isolation
   holds and the cross-workspace lookups resolve.
2. Bun runs `install` / `postinstall` only for packages listed in
   the workspace root's `trustedDependencies`. Native plugins
   (`aerospike`, `@confluentinc/kafka-javascript`, `pg-native`, ...)
   installed without their `.node` files compiled, so `bindings`
   threw `Could not locate the bindings file` at test time. The
   script now collects every package name it installs (workspaces
   plus peer-dep injections) and writes them to
   `versions/package.json:trustedDependencies`.
3. `assertPeerDependencies` was writing the raw range from the
   parent's `peerDependencies`/`devDependencies` straight into the
   sandbox `package.json`. Bun resolves ranges to the lowest
   matching version where yarn 1 picked the highest, so peer deps
   like `@smithy/node-http-handler` (only present in newer
   `@aws-sdk` releases) landed on an older sibling that did not
   ship them. Pre-resolving each range via `bun pm view` matches
   the prior coverage.

`versions/bunfig.toml` moves from a committed file (with a
`.gitignore` exception) to a script-generated one — single source of
truth alongside the workspace `package.json`. The regression test
walks Node's resolution from inside each sandbox via `createRequire`
so it passes against both hoisted and isolated layouts.
Moleculer's transit/util layer falls back to `require('bluebird')`
at runtime even in 0.14.x. Dropping the externals fixture entry on
the strength of moleculer's manifest alone (which does not list
bluebird) broke the plugin's tests with `Cannot find module
'bluebird'` across seven test cases.

Restored as a sibling sandbox; bun's hoisted linker lifts it into
`versions/node_modules/bluebird` where moleculer's `require()` walk
finds it.
`--linker=hoisted` lifts a single copy of each package to
`versions/node_modules/<pkg>`, which broke five plugin spec files
(`next`, `kafkajs`, `rhea`, `memcached`, `apollo`) that hard-code
paths like `versions/<plugin>@<ver>/node_modules/<plugin>/<internal>`:
the highest-version sandbox loses its nested copy under hoisted, so
the require fails with `Cannot find module`. Bun's `--linker=isolated`
keeps a per-sandbox symlink at exactly that path and resolves it
through the central `.bun/` store; the hard paths work again.

Cross-workspace `require()` lookups (moleculer's runtime
`require('bluebird')` fallback was the canary) now go through the
externals fixture's `dep: true, forced: true` shape: bluebird is
injected as a direct dep of each moleculer sandbox, so bun's
isolated layout symlinks it into
`versions/moleculer@<ver>/node_modules/bluebird` where moleculer's
require walk from the central store finds it.
This fixes the `Channel credentials must be a ChannelCredentials object`
failure across all 22 `@google-cloud/pubsub@1.2.0` plugin specs under bun's
isolated linker.

`pubsub@1.2.0`'s `pubsub.js` source-requires `@grpc/grpc-js` when
`PUBSUB_EMULATOR_HOST` (or `apiEndpoint`) is set, but the manifest does not
declare it. The parent walk lands on whatever bun hoists at the workspace
root — currently the 1.8+ tree shared with `google-gax@3.5.7` — and the
credentials produced there fail the `instanceof ChannelCredentials` check
inside 1.3.x's Channel constructor, the version pubsub@1.2.0's nested
`google-gax@1.15.4` uses (`@grpc/grpc-js: ~1.3.6`). yarn 1 hoisted 1.3.x
at the right place; bun does not.

`assertPeerDependencies` already injects forced direct deps into every
sandbox of a named package — moleculer's bluebird is the precedent. The
existing `latests[name]` source ships `@grpc/grpc-js@1.14.3`, too new for
`google-gax@1.15.4`; add an entry-level `version` override and inject
`@grpc/grpc-js: ~1.3.6` for every `@google-cloud/pubsub` sandbox so bun
hoists 1.3.x at the workspace root.
This fixes the langchain plugin tests under bun's isolated linker. The
`langchain@>=0.1` sandbox cannot resolve `@langchain/openai` at all -
bun isolated does not hoist transitive deps to the workspace root - and
the only other source for the require, the `latests` pin in
`packages/dd-trace/test/plugins/versions/package.json` (`1.2.2`), throws
`Cannot use 'in' operator to search for 'output_version' in undefined`
in the chat-model converter when paired with a `@langchain/core@0.1.0`
BaseMessage, and otherwise sends a 1.x request shape that misses every
recorded cassette and 401s on the proxy fallback.

Yarn classic happened to hoist `@langchain/openai@0.0.34` (the transitive
dep of `langchain@0.1.0`) to the workspace root, so every
`langchain@<version>` sandbox resolved to that version via NODE_PATH
walking and the recorded cassettes match its `OpenAI/JS 4.x` request
shape. Pinning the same version explicitly in the generated
`versions/package.json` puts bun's isolated layout on that version too.
Recording cassettes against the newer `@langchain/openai` is a
follow-up that earns its own change.
Both fixup commits added inline comments explaining the bun-vs-yarn
hoisting difference; the no-yarn-dev-references guardrail flagged them
because cross-PM contrast prose belongs in the commit body, not in
code (per the comment-skip rule for "accuracy depends on code outside
this file"). The structural why — bun's isolated linker does not hoist
transitives, so we pin the missing transitive directly — is what stays
in the comments; the historical contrast is gone.
Three holes in the yarn → bun migration of `versions/` surfaced in CI:

1. `pg-native` is in `trustedDependencies` so its install script
   runs, but the actual `node-gyp` build sits in `libpq` (a
   transitive). Bun's `trustedDependencies` does not cascade, so
   `libpq`'s `addon.node` never builds and the `bindings` package
   rejects the load at test time. Add `libpq` directly to the
   trusted set.

2. `pkgJsonPath()` in the generated sandbox `index.js` resolved
   `<name>/package.json`, which throws `ERR_PACKAGE_PATH_NOT_EXPORTED`
   for packages that ship an `exports` map without a `./package.json`
   entry (moleculer, react, ...). Walk `module.paths` directly so
   the lookup stays exports-blind, mirroring `requirePackageJson`.

3. The bedrock-runtime LLMObs spec reaches into the workspace's own
   `@smithy/node-http-handler` via `.get('@smithy/node-http-handler')`.
   Under the isolated linker that transitive sits only inside
   aws-sdk's private store and is not reachable from the workspace
   root, so inject it as a direct dep of every
   `@aws-sdk/client-bedrock-runtime` sandbox via the existing
   `dep: true, forced: true` channel.
`dd-license-attribution` only enumerates root deps from `yarn.lock`
or `package-lock.json`; the migration ships only `bun.lock`, so the
upstream tool drops every root runtime/optional row on each run and
the auto-update workflow fails on every PR.

Until bun.lock support lands upstream
(https://github.com/watson/dd-license-attribution),
`scripts/check_licenses.js` (run via `npm run lint`) is the source of
truth for CSV completeness against `bun.lock`,
`vendor/package-lock.json`, and `vendored-dependencies.csv`. The
workflow now does the bare minimum needed to keep the required check
name green — assert that `LICENSE-3rdparty.csv` is present and
non-empty on the PR head. The trigger no longer fires on `bun.lock`
changes since we have no way to act on them; it stays on the vendor
and vendored-deps paths so future tooling work has somewhere to plug
back in.
Bun's isolated linker keeps a single shared copy of every package
under `versions/node_modules/.bun/<name>@<ver>/`, so a native
binding compiled by `pg-native` → `libpq`'s install hook under one
Node major is reused verbatim on the second `npm run services`
invocation under a different Node major. The Plugin and
Instrumentation actions install once with the oldest LTS, then
switch to the latest Node and run the same sandbox a second time —
the cached `addon.node` then crashes on load with
`undefined symbol: _ZN2v86Object16SetInternalFieldEiNS_5LocalINS_5ValueEEE`.

Yarn 1's per-workspace layout rebuilt every binding on every
install pass and never hit this. Wipe the central store (and the
matching `bun.lock`) when the recorded Node ABI does not match the
current process so the next `bun install --trust` reruns lifecycle
scripts and rebuilds against the live runtime.
The workflow header ran afoul of the new `no-yarn-dev-references`
spec that scans tracked files for `\byarn\b`. Reword the comment to
explain the same constraint without using the word.
Same fix as 891c25a: the new spec scans tracked files for the
literal word and the rebuild comment was the only stray reference
introduced in 27890d8.
Two unrelated yarn → bun differences hide the same way: the test
process deadlocks for hours in `should not alter the default behavior
with pretty print` for pino@5/6/7, and the langchain `JSON message
input` regression rejects every plain `{role, content}` payload with
`messageLike is not iterable`. Both come down to bun installing a
different transitive than yarn classic did.

1. `bun pm view <pkg>@<range> version` returns the lowest matching
   version, not the highest. `resolveLatestSatisfying` now pulls the
   full version list and runs `semver.maxSatisfying` to mirror yarn
   classic's choice. Same effect across the matrix: every cap that
   yarn pinned to its highest under-cap version pins to that version
   again under bun. Concretely, `@langchain/core@>0.1.56 <0.3.0`
   resolves to `0.2.36` instead of `0.1.63`, where
   `coerceMessageLikeToMessage` accepts JSON messages.

2. Bun's isolated linker keeps a central
   `versions/node_modules/.bun/node_modules/` directory of one
   symlink per package, picking the highest installed version
   across every workspace. From inside `.bun/pino@5.0.0/.../pino/lib/tools.js`,
   Node's resolution walks up into that directory and finds the
   central `pino-pretty@13.1.3` symlink before falling through to
   `NODE_PATH`'s per-workspace `pino-pretty@1.0.1`. Pino@5's pretty
   integration then crashes with `pretty is not a function`, the
   throw happens inside an internal pino write loop and never
   surfaces a mocha failure — the runner just sits forever. Wipe
   the central directory after every `bun install --trust` so
   per-workspace resolution wins.
The benchmarking-platform image is rebuilt from `master` and does
not yet ship bun, so every dev-tooling install path the benchmark
exercises (`bun install` at the repo root, `npm run services` ↦
`scripts/install_plugin_modules.js` ↦ `bun install --trust`,
`benchmark/sirun/runall.sh`'s own bootstrap) fails the moment bun
is invoked. Add a `before_script` to `.benchmarks` that installs bun
once per job and exports `$HOME/.bun/bin` on `PATH`, and move the
runall.sh bootstrap out of its subshell so `PATH` stays set for the
sirun loop instead of leaking with the subshell exit. Drop the
benchmarks.yml `before_script` once the image bakes bun in.
`devflow/mergegate` rejects PRs that introduce a tracked file with
no `CODEOWNERS` entry. `.github/workflows/install-smoke.yml` was
added in this PR and exercises the lang-platform-js sandbox-install
path, so route it to the same team that owns `/scripts/**`.
…to-sts

`dd-license-attribution` does not yet read `bun.lock`, so the
auto-update workflow had been disabled while the migration landed.
Replace the upstream tool with `scripts/generate-3rdparty-licenses.js`,
which walks the same locks and CSV the lint check already trusts
(`bun.lock`, `vendor/package-lock.json`,
`.github/vendored-dependencies.csv`) and fetches license + origin
metadata from the npm registry. The script preserves rows that already
exist in `LICENSE-3rdparty.csv` to keep the diff tight on re-runs and
records the project itself from `package.json` so the self-row stays
stable across registry hiccups.

The workflow restores the original two-stage shape: `check-licenses`
regenerates the CSV and uploads it as an artifact when the bot owns
the PR; `auto-commit-licenses` mints a token via
`DataDog/dd-octo-sts-action` (governed by the existing
`update-3rdparty-licenses.sts.yaml` chainguard policy) and pushes the
file via the GitHub API. Human PRs that drift the CSV continue to
fail with the regen instructions, same shape as before.

The matching CSV update sorts the two vendored entries
(`aws-lambda-nodejs-runtime-interface-client`, `is-git-url`) into
their alphabetical position so the regen and the committed file
match byte-for-byte going forward.
The plugin smoke test is a real test surface; it should show up in
Datadog Test Optimization the same way the full plugin matrix does.
Mint a Datadog API key via `dd-sts-api-key` and call the shared
`push_to_test_optimization` action under `if: !cancelled()`, so a
failed install or smoke run still uploads its junit artifact for
triage.
The previous fix wiped `versions/node_modules/.bun/node_modules/`
wholesale, which silenced the `pino-pretty` shadow but also
removed the central symlinks every other sandbox relied on for
transitive resolution. `q@2`'s `collections`,
`@grpc/grpc-js`'s `@grpc/proto-loader`, and `knex@0.8`'s
`sqlite3` lookups all walk through that central store, and the
sandbox install jobs for them broke as a side effect.

Tighten the pruner to remove central symlinks only for packages
that have more than one major installed in the `.bun/` store.
That keeps hoisted resolution intact for single-version
transitives (`@grpc/proto-loader@0.x`, `sqlite3@5.x`,
`libpq@1.x`, ...) while still forcing per-workspace resolution
for packages whose central pin shadows an incompatible major
that a specific sandbox needs (`pino-pretty@13.x` shadowing
`pino@5`'s `pino-pretty@1.0.1`).

Drop the leftover yarn references from the regen script's
JSDoc so the `no-yarn-dev-references` regression test stays
green.
`q@2.0.0`'s manifest declares `collections: ^2.0.0`, but `q.js` does
`require('collections/shim')` and `shim.js` only exists in
`collections@>=5`. The previous package manager's flat hoist always
served `collections@5` from the workspace root, so q's resolution
walked up to it. Bun's isolated linker honours the `^2.0.0` range
and lands `collections@2.0.3` in q's per-package store, where the
require throws `Cannot find module 'collections/shim'`.

Pin `collections` to `^5.0.0` via the workspace `overrides` field so
every q sandbox lands on the same version the previous tooling
served. Other consumers in the workspace already declare or transit
via 5.x, so the override does not regress anything else.
CodeQL flagged the `author.replace(/\s*<[^>]+>\s*/, '')` regex as a
potential HTML-injection sink because the npm-registry-supplied
`author` / `contributors` strings are technically untrusted input.
Split on the first `<` or `(` instead — npm's `Name <email> (url)`
shape is well-defined enough that a literal slice gives the same
result without the regex pattern that CodeQL warns about. Same
output for every package in the current CSV, so the regen produces
byte-identical rows.
The vertex-ai plugin spec stubs `GoogleAuth.getAccessToken` via
`require('versions/@google-cloud/vertexai@<ver>').get('google-auth-library/...')`.
`google-auth-library` is a regular transitive of `@google-cloud/vertexai`,
so under bun's isolated linker it lives only inside vertexai's private
store and isn't reachable from the workspace root. The previous package
manager's flat hoist masked this; bun didn't, and the spec hung at the
first `before` hook because `require.resolve` walks until it gives up.

Inject it as a direct dep of every `@google-cloud/vertexai` sandbox via
the same `dep: true, forced: true` channel that fixes the bedrock spec
right above it.
The `bun.sh/install` script unzips the release archive, so the install
fails with `error: unzip is required to install bun` on the
benchmarking-platform image because `ubuntu:22.04` does not ship
`unzip`. Install it via `apt-get` only when missing — keeps the
fast path on hosts that already have it (sirun's `runall.sh`
bootstrap, eventually the image once it bakes bun in).
`docs/bun.lock` was added in this PR (replacing `docs/yarn.lock`)
and devflow/mergegate flags any tracked file with no owner. The
`type:doc:build` / `type:doc:test` scripts use the same toolchain
as the rest of `/scripts/**`, so route the directory to the same
team.
`@langchain/openai@0.0.34`'s manifest declares
`@langchain/core: >0.1.56 <0.3.0`. The langchain regression spec
(`instruments a langchain openai chat model call for a JSON message
input`) only works against a `0.2.x` core — the older
`coerceMessageLikeToMessage` in `0.1.x` only knows the
`[role, content]` tuple shape and crashes on the spec's
`{role, content}` object input.

Bun's isolated linker resolves that range deterministically per
host, but the chosen version varies: it lands `0.2.36` on the local
macOS dev machine and `0.1.63` on the github-hosted runner image.
The previous package manager always served the highest workspace
copy via flat hoist, so this never surfaced. Pin the floor for the
`@langchain/openai@0.0.34/@langchain/core` pair to `^0.2.0` so both
hosts agree, without affecting the `@langchain/openai@1.x.x` peer
constraint resolved elsewhere in the workspace.
`ai@4.0.2` declares `zod` as an optional peer (`^3.0.0`); `@ai-sdk/openai`
@1.3.23+ as a required peer. Yarn 1's flat hoist served the standalone
`zod` workspace's copy from the workspace root to both sandboxes; bun's
isolated linker honours each package's own manifest and skips optional
peers, so `versions/ai@4.0.2` lands without `zod` and the first
`ai.generateText` invocation throws `Cannot find module 'zod'` from
inside the SDK's response-parsing path.

Inject `zod` as a direct dep of every `ai` sandbox via the existing
`dep: true` channel so bun materialises it alongside `ai` in the
isolated store.
BridgeAR added 11 commits May 25, 2026 02:31
Three coordinated fix-ups:

1. actionlint: the install action grew a `cache` input on master but the
   declaration didn't follow, so every workflow that passed `cache: 'true'`
   tripped `input "cache" is not defined`; and `integration-esbuild` still
   gated its steps on `matrix.bundler`, which no longer exists in that job's
   matrix (only `version` and `esbuild_version`).
2. verify-exercised-tests: `test:plugins:ci`, `test:integration:crashtracking`,
   `test:integration:electron`, and `test:integration:webpack` were still
   invoked via `yarn` in four workflows. The verifier matches workflow calls
   to package.json scripts and saw zero coverage for those entries.
3. integration-playwright: the datadog-ci composite reached for
   `oven-sh/setup-bun`, which extracts its archive through `unzip`. The
   Playwright runner image doesn't ship unzip, so the action failed before
   `datadog-ci` ever landed on PATH. Install via `npm install --no-save
   --ignore-scripts` instead and drop the orphaned `yarn.lock` / `.yarnrc`
   that lived next to it.
The lockfile drifted from the workspace `package.json` during the rebase
(devDep bumps in `axios`, `bun`, `eslint-plugin-cypress`, `eslint-plugin-n`,
`nock`, `semver`, `sinon`, `yaml`, plus the `@datadog/*` and `oxc-parser`
runtime deps). `supported-integrations` regenerates the supported-versions
files and asserts that only those two CSVs changed in the job's worktree;
the stale lockfile let `bun install` rewrite the workspace dep table mid-
job and tripped the integrity check.

`generate-3rdparty-licenses.js` reads the same lockfile, so `check-licenses`
was reporting one stale row against the current CSV. Regenerating
synchronises both jobs against the post-rebase dep tree.
Two failures the previous yarn flat-hoist masked:

1. vertex-ai: `version: '*'` resolves to `google-auth-library@10`, but
   every published `@google-cloud/vertexai` declares its transitive at
   `^9.0.0`. Bun's isolated linker keeps both physical copies — the test
   stubs `GoogleAuth.prototype.getAccessToken` on the @10 copy, the SDK
   loads the @9 copy at run-time, the stub never applies, and the real
   credential lookup throws `GoogleAuthError`. Pin the direct dep to
   `^9.0.0` so bun dedupes to a single `.bun/google-auth-library@9.x.y`
   entry and the prototype stub propagates to the SDK.
2. ai: `@ai-sdk/ui-utils` ranges `zod-to-json-schema` at `^3.0.0` and
   `ai@4.0.2` ranges `zod` at `^3.0.0`; bun picks `zod-to-json-schema@3.25.2`
   next to `zod@3.23.8`. `3.25.x` switched its zod imports to the `zod/v3`
   subpath, which only exists in `zod@>=3.25.32` and `zod@4`, so the sandbox
   crashes at load time with `ERR_PACKAGE_PATH_NOT_EXPORTED`. Bun does
   not honour nested overrides (oven-sh/bun#6608), so a flat
   `zod-to-json-schema: <3.25.0` override is the only shape that works;
   the only other consumer (`langchain` / `langgraph`) declares
   `>=3.0.0` and the constraint still holds.
The `installs every pino sandbox ...` regression guard forwards a
constrained `PATH` to the spawned `install_plugin_modules.js` so a
re-introduced `yarn` invocation fails closed. The PATH it built started
with `~/.bun/bin`, but the node composite action installs bun through
`npm install -g bun@<ver>`; the binary lands under `npm prefix -g`,
not under `~/.bun`. Every `spawn('bun', …)` in the child returned
`ENOENT`, the install script exited with an empty stderr that hid the
cause, and `Sandbox install (pino)` failed on the assert. Resolve bun's
actual location via `command -v bun`, with a `BUN_BIN` override for
unusual layouts.

Drive-by fix:

* Rewrite the `patch-istanbul-lib-coverage.js` doc comment to drop a
  stray `yarn upgrade` mention (no yarn invocation, purely cosmetic) and
  allowlist `scripts/verify-exercised-tests.js` in the no-yarn spec —
  its `indexOf('yarn ')` is structural workflow-string parsing, not a
  yarn invocation.
`b4912ad7eb` removed the repo-root `.yarnrc` (`ignore-engines true`).
`openfeature.spec.js` still shells out to yarn after `bun add` pulls in
`@hono/node-server@2.x` (`engines.node >= 20`), so on the node-oldest
matrix entry yarn errors before the build step and the integration-esbuild
job hangs past 30 minutes against ~160s on master.

`iast-stack-traces-with-sourcemaps` follows the same shape with deps that
happen to be Node-18-clean today; pass the flag inline there too to keep
the contract explicit so a future dep bump can't silently break the same
matrix entry again.
The Windows install action enables the bun-output cache via the
`cache: "true"` input added in `46d98c9756`. On a cache hit it
`tar -xf`s the saved archive and skips `bun install`, but the original
archive only contained `node_modules`. `bun install`'s `prepare` step
runs `cd vendor && npm ci --include=dev`, whose `node rspack`
postinstall lands `vendor/dist/{limiter, ...}` outside that path, so
every cache-hit Windows job now fails at first require with
`Cannot find module '../../../vendor/dist/limiter'`.

Capture `vendor/node_modules` and `vendor/dist` in the archive, fold
`vendor/package-lock.json` into the cache key so a transitive bump
invalidates the entry, and rename the archive plus bump the key
suffix to `-v3` so already-poisoned entries miss.
The bun matrix entry in `package-manager` stalls indefinitely at
`Resolving dependencies` after the install action's `bun install`
primes the cache. Without a cap it has held the job for 45+ minutes
on each PR push, while the four other package managers complete the
same step against the same dd-trace.tgz in 3-5s.

Wrap the consumer install in `nick-fields/retry` with a 2-minute
per-attempt cap so a stalled bun fails fast and retries (warm cache
on the second attempt) instead of pinning the runner. The other PMs
finish well inside the cap, so they pay nothing for the wrapper.
The symptom matches the bun resolver-stall reports collected under
oven-sh/bun#5831.
The sandbox is already populated by `useSandbox` (which `bun add`s the
declared deps and the dd-trace tarball), so the follow-up `yarn` pass in
the `before` block ran the same resolution a second time with a
different package manager and produced no test-specific signal. The
spec doesn't exercise any yarn behaviour the way `openfeature.spec.js`
(rm -rf node_modules + install yarn globally + yarn) or
`test-optimization-startup.spec.js` (PM-detection matrix) do. Drop the
call and the matching `no-yarn-dev-references` allowlist entry.
…ructural

The isolation contract for plugin sandboxes lived only in the writer
inside `scripts/install_plugin_modules.js`, and the resulting
`versions/bunfig.toml` was caught by `/versions/*` in `.gitignore`. A
fresh checkout had no bunfig until `npm run services` ran once, and a
direct `bun install` invoked from `versions/` (manual debugging,
sandbox repair) would pick up the host bun config instead of
`linker = "isolated"` — the exact silent regression the original plan
flagged.

Negate the path in `.gitignore`, commit the three-line bunfig, and drop
the now-redundant writer. The explanatory comment about isolated bun's
symlink layout moves to the `bun install --trust` call site, which is
the operative consumer.
The composite action ran \`npm install --no-save\`, so every CI run let
the install resolve fresh against the npm registry. \`package.json\`
pinned the top-level \`@datadog/datadog-ci\` version, but a republished
tarball at the same version number would have been picked up silently;
\`yarn.lock\` (deleted earlier in this PR) used to carry that integrity
hash and the rewrite lost it.

Add a committed \`package-lock.json\` for the action and switch the
install to \`npm ci\`. The lockfile holds the tarball integrity hash,
so a tampered or republished tarball at \`5.16.0\` is rejected before
the binary lands on PATH.
The npm supply-chain pattern that keeps repeating lands a compromised
version on the registry, takes effect on the next CI install, and gets
yanked once detection catches up — usually within hours, sometimes a
day or two. Three days is enough lead time that most flagged releases
get pulled before they reach our installs, and the lockfile freeze
makes the policy actually stick on every CI run.

1. bunfig.toml and versions/bunfig.toml set
   minimumReleaseAge = 259200 (three days). @datadog/* bypasses the
   wait — our publishing pipeline is the trust boundary for those —
   and the value mirrors .github/dependabot.yml's cooldown.exclude so
   the two policies stay aligned.

2. .github/actions/install/action.yml and benchmark/sirun/runall.sh
   pass --frozen-lockfile to bun install. CI fails the install step
   when bun.lock no longer matches package.json, so a contributor who
   edits package.json (or a Dependabot bump) has to ship the
   regenerated lock alongside. Without the freeze, the install would
   silently resolve fresh against the registry and the
   minimumReleaseAge filter would be the only thing left protecting
   that run.

3. The four @datadog/native-* packages plus bun move from the CLI's
   --trust flag into trustedDependencies in package.json. Bun refuses
   --trust and --frozen-lockfile together, so the trust list has to
   be declarative; this is the same pattern the plugin sandboxes
   already use via scripts/install_plugin_modules.js.

CONTRIBUTING.md documents the policy and the escape valve for an
advisory whose patch is still inside the three-day window: a
maintainer runs `bun update <pkg>@<exact> --minimum-release-age=0`
locally, commits the regenerated lock, and calls out the override in
the PR description. The override stays out of bunfig.toml so every
bypass shows up in a reviewable diff.

Signed-off-by: Ruben Bridgewater <ruben.bridgewater@datadoghq.com>
@dd-octo-sts

dd-octo-sts Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 5.63 MB
Deduped: 6.67 MB
No deduping: 6.67 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.0.1 | 82.56 kB | 817.39 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.60%. Comparing base (0925615) to head (c201603).

Additional details and impacted files
@@                         Coverage Diff                         @@
##           BridgeAR/2026-05-09-remove-yarn    #8629      +/-   ##
===================================================================
+ Coverage                            92.58%   92.60%   +0.01%     
===================================================================
  Files                                  843      847       +4     
  Lines                                47115    47193      +78     
  Branches                              8519     8519              
===================================================================
+ Hits                                 43622    43701      +79     
+ Misses                                3493     3492       -1     
Flag Coverage Δ
aiguard-integration-active 41.25% <ø> (ø)
aiguard-integration-latest 41.20% <ø> (ø)
aiguard-integration-maintenance 41.25% <ø> (ø)
aiguard-macos 33.56% <ø> (ø)
aiguard-ubuntu 33.65% <ø> (ø)
aiguard-windows 33.37% <ø> (ø)
apm-capabilities-tracing-macos 47.98% <ø> (ø)
apm-capabilities-tracing-ubuntu-active 48.00% <ø> (ø)
apm-capabilities-tracing-ubuntu-latest 47.98% <ø> (-0.19%) ⬇️
apm-capabilities-tracing-ubuntu-maintenance ?
apm-capabilities-tracing-ubuntu-oldest 48.19% <ø> (+0.18%) ⬆️
apm-capabilities-tracing-windows 47.79% <ø> (-0.19%) ⬇️
apm-integrations-aerospike-18-gte.5.2.0 33.26% <ø> (ø)
apm-integrations-aerospike-20-gte.5.5.0 33.29% <ø> (ø)
apm-integrations-aerospike-22-gte.5.12.1 33.29% <ø> (ø)
apm-integrations-aerospike-22-gte.6.0.0 33.29% <ø> (ø)
apm-integrations-aerospike-eol- 33.19% <ø> (ø)
apm-integrations-child-process 34.13% <ø> (ø)
apm-integrations-confluentinc-kafka-javascript-18 40.36% <ø> (ø)
apm-integrations-confluentinc-kafka-javascript-20 40.37% <ø> (ø)
apm-integrations-confluentinc-kafka-javascript-22 40.38% <ø> (ø)
apm-integrations-couchbase-18 33.45% <ø> (+0.17%) ⬆️
apm-integrations-couchbase-eol 33.29% <ø> (ø)
apm-integrations-dns 32.99% <ø> (ø)
apm-integrations-elasticsearch 34.20% <ø> (ø)
apm-integrations-http-latest 41.47% <ø> (ø)
apm-integrations-http-maintenance 41.51% <ø> (ø)
apm-integrations-http-oldest 41.52% <ø> (ø)
apm-integrations-http2 38.57% <ø> (ø)
apm-integrations-kafkajs-latest 40.23% <ø> (ø)
apm-integrations-kafkajs-oldest 40.17% <ø> (-0.10%) ⬇️
apm-integrations-net 33.90% <ø> (ø)
apm-integrations-next-11.1.4 27.90% <ø> (ø)
apm-integrations-next-12.3.7 29.46% <ø> (ø)
apm-integrations-next-13.0.0 29.46% <ø> (ø)
apm-integrations-next-13.2.0 29.46% <ø> (ø)
apm-integrations-next-13.5.11 29.60% <ø> (ø)
apm-integrations-next-14.0.0 29.57% <ø> (+0.04%) ⬆️
apm-integrations-next-14.2.35 29.53% <ø> (ø)
apm-integrations-next-14.2.6 29.57% <ø> (+0.04%) ⬆️
apm-integrations-next-14.2.7 29.53% <ø> (-0.05%) ⬇️
apm-integrations-next-15.0.0 29.53% <ø> (ø)
apm-integrations-next-15.4.0 29.64% <ø> (ø)
apm-integrations-oracledb 33.67% <ø> (ø)
apm-integrations-prisma-18-gte.6.16.0.and.lt.7.0.0 ?
apm-integrations-prisma-latest-all 34.55% <ø> (ø)
apm-integrations-restify 35.59% <ø> (ø)
apm-integrations-sharedb 32.66% <ø> (ø)
apm-integrations-tedious 33.48% <ø> (ø)
appsec-express 51.60% <ø> (?)
appsec-fastify 48.23% <ø> (ø)
appsec-graphql 48.23% <ø> (ø)
appsec-integration-active 37.08% <ø> (?)
appsec-integration-latest 37.05% <ø> (ø)
appsec-integration-maintenance 37.09% <ø> (ø)
appsec-integration-oldest 37.08% <ø> (ø)
appsec-kafka 40.90% <ø> (ø)
appsec-ldapjs 40.03% <ø> (ø)
appsec-lodash 40.13% <ø> (ø)
appsec-macos 57.70% <ø> (-0.08%) ⬇️
appsec-mongodb-core 44.74% <ø> (ø)
appsec-mongoose 45.60% <ø> (+0.01%) ⬆️
appsec-mysql 47.53% <ø> (ø)
appsec-next-latest-11.1.4 27.96% <ø> (ø)
appsec-next-latest-12.3.7 29.51% <ø> (ø)
appsec-next-latest-13.0.0 29.51% <ø> (ø)
appsec-next-latest-13.2.0 29.53% <ø> (ø)
appsec-next-latest-13.5.11 29.64% <ø> (ø)
appsec-next-latest-14.0.0 29.56% <ø> (ø)
appsec-next-latest-14.2.35 29.56% <ø> (ø)
appsec-next-latest-14.2.6 29.56% <ø> (ø)
appsec-next-latest-14.2.7 29.56% <ø> (ø)
appsec-next-latest-15.0.0 29.56% <ø> (ø)
appsec-next-latest-latest 29.56% <ø> (ø)
appsec-next-oldest-11.1.4 27.95% <ø> (ø)
appsec-next-oldest-12.3.7 29.51% <ø> (-0.01%) ⬇️
appsec-next-oldest-13.0.0 29.51% <ø> (ø)
appsec-next-oldest-13.2.0 29.78% <ø> (ø)
appsec-next-oldest-13.5.11 29.89% <ø> (ø)
appsec-next-oldest-14.0.0 29.82% <ø> (ø)
appsec-next-oldest-14.2.35 29.82% <ø> (ø)
appsec-next-oldest-14.2.6 29.82% <ø> (ø)
appsec-next-oldest-14.2.7 29.82% <ø> (-0.02%) ⬇️
appsec-next-oldest-15.0.0 29.82% <ø> (ø)
appsec-next-oldest-latest 27.78% <ø> (ø)
appsec-node-serialize 39.35% <ø> (ø)
appsec-passport 43.08% <ø> (ø)
appsec-postgres 47.20% <ø> (ø)
appsec-sourcing 38.74% <ø> (ø)
appsec-stripe 40.80% <ø> (ø)
appsec-template 39.59% <ø> (ø)
appsec-ubuntu 57.77% <ø> (ø)
appsec-windows 57.62% <ø> (ø)
debugger-ubuntu-active 43.93% <ø> (ø)
debugger-ubuntu-latest 43.88% <ø> (ø)
debugger-ubuntu-maintenance 43.95% <ø> (ø)
debugger-ubuntu-oldest 44.39% <ø> (ø)
instrumentations-instrumentation-ai 36.24% <ø> (ø)
instrumentations-instrumentation-aws-sdk 35.20% <ø> (ø)
instrumentations-instrumentation-bluebird 27.82% <ø> (ø)
instrumentations-instrumentation-body-parser 36.02% <ø> (ø)
instrumentations-instrumentation-child_process 33.52% <ø> (ø)
instrumentations-instrumentation-cookie-parser 29.82% <ø> (ø)
instrumentations-instrumentation-couchbase-18 36.41% <ø> (ø)
instrumentations-instrumentation-couchbase-eol 36.41% <ø> (ø)
instrumentations-instrumentation-crypto 27.90% <ø> (ø)
instrumentations-instrumentation-express 30.01% <ø> (ø)
instrumentations-instrumentation-express-mongo-sanitize 29.93% <ø> (ø)
instrumentations-instrumentation-express-multi-version 21.17% <ø> (ø)
instrumentations-instrumentation-express-session 35.73% <ø> (ø)
instrumentations-instrumentation-fetch 33.27% <ø> (ø)
instrumentations-instrumentation-fs 27.54% <ø> (ø)
instrumentations-instrumentation-generic-pool 27.44% <ø> (ø)
instrumentations-instrumentation-hono 28.96% <ø> (ø)
instrumentations-instrumentation-http 35.25% <ø> (ø)
instrumentations-instrumentation-http-client-options 37.75% <ø> (ø)
instrumentations-instrumentation-knex 27.81% <ø> (ø)
instrumentations-instrumentation-light-my-request 35.55% <ø> (ø)
instrumentations-instrumentation-mongoose 29.17% <ø> (?)
instrumentations-instrumentation-multer 35.68% <ø> (ø)
instrumentations-instrumentation-mysql2 33.58% <ø> (ø)
instrumentations-instrumentation-otel-sdk-trace 25.35% <ø> (ø)
instrumentations-instrumentation-passport 39.48% <ø> (ø)
instrumentations-instrumentation-passport-http 39.17% <ø> (ø)
instrumentations-instrumentation-passport-local 39.64% <ø> (ø)
instrumentations-instrumentation-pg 33.17% <ø> (ø)
instrumentations-instrumentation-promise 27.77% <ø> (ø)
instrumentations-instrumentation-promise-js 27.77% <ø> (ø)
instrumentations-instrumentation-q 27.80% <ø> (ø)
instrumentations-instrumentation-stripe 28.31% <ø> (ø)
instrumentations-instrumentation-url 27.73% <ø> (ø)
instrumentations-instrumentation-when 27.78% <ø> (ø)
instrumentations-instrumentation-zlib 27.78% <ø> (ø)
instrumentations-integration-esbuild-0.16.12-active 19.24% <ø> (ø)
instrumentations-integration-esbuild-0.16.12-latest 19.23% <ø> (ø)
instrumentations-integration-esbuild-0.16.12-maintenance 19.24% <ø> (ø)
instrumentations-integration-esbuild-0.16.12-oldest 19.23% <ø> (ø)
instrumentations-integration-esbuild-latest-active 19.24% <ø> (?)
instrumentations-integration-esbuild-latest-latest 19.23% <ø> (?)
instrumentations-integration-esbuild-latest-maintenance 19.24% <ø> (ø)
instrumentations-integration-esbuild-latest-oldest 19.23% <ø> (ø)
llmobs-ai 36.51% <ø> (ø)
llmobs-anthropic 36.70% <ø> (ø)
llmobs-bedrock 35.43% <ø> (ø)
llmobs-google-genai 35.77% <ø> (ø)
llmobs-langchain 36.75% <ø> (ø)
llmobs-openai-latest 39.67% <ø> (ø)
llmobs-openai-oldest 39.70% <ø> (ø)
llmobs-sdk-active 43.77% <ø> (ø)
llmobs-sdk-latest 43.71% <ø> (ø)
llmobs-sdk-maintenance 43.76% <ø> (ø)
llmobs-sdk-oldest 43.75% <ø> (ø)
llmobs-vertex-ai 35.77% <ø> (ø)
master-coverage ?
openfeature-macos 38.09% <ø> (ø)
openfeature-ubuntu 38.17% <ø> (ø)
openfeature-unit-active 47.81% <ø> (ø)
openfeature-unit-latest 47.68% <ø> (ø)
openfeature-unit-maintenance 47.81% <ø> (ø)
openfeature-unit-oldest 47.81% <ø> (ø)
openfeature-windows 37.96% <ø> (ø)
platform-core 32.21% <ø> (ø)
platform-esbuild 36.77% <ø> (ø)
platform-instrumentations-misc 30.17% <ø> (ø)
platform-integration-active 47.25% <ø> (+0.04%) ⬆️
platform-integration-latest 47.21% <ø> (+0.04%) ⬆️
platform-integration-maintenance 47.26% <ø> (ø)
platform-integration-oldest 47.43% <ø> (+0.04%) ⬆️
platform-shimmer 39.58% <ø> (ø)
platform-unit-guardrails 32.99% <ø> (ø)
platform-webpack 18.74% <ø> (ø)
plugins-axios 35.54% <ø> (ø)
plugins-azure-cosmos 35.95% <ø> (ø)
plugins-azure-event-hubs 34.88% <ø> (ø)
plugins-azure-service-bus 35.37% <ø> (ø)
plugins-body-parser 36.71% <ø> (ø)
plugins-bullmq 39.19% <ø> (ø)
plugins-cassandra 33.70% <ø> (ø)
plugins-cookie 25.20% <ø> (ø)
plugins-cookie-parser 24.95% <ø> (ø)
plugins-crypto 24.94% <ø> (ø)
plugins-dd-trace-api 33.54% <ø> (ø)
plugins-express-mongo-sanitize 25.20% <ø> (ø)
plugins-express-session 24.87% <ø> (ø)
plugins-fastify 37.83% <ø> (ø)
plugins-fetch 34.18% <ø> (ø)
plugins-fs 33.52% <ø> (?)
plugins-generic-pool 23.89% <ø> (ø)
plugins-google-cloud-pubsub 41.49% <ø> (ø)
plugins-grpc 36.70% <ø> (ø)
plugins-handlebars 25.16% <ø> (ø)
plugins-hapi 35.70% <ø> (?)
plugins-hono 35.98% <ø> (ø)
plugins-ioredis 34.27% <ø> (ø)
plugins-jest 28.09% <ø> (ø)
plugins-knex 24.88% <ø> (ø)
plugins-langgraph 33.11% <ø> (ø)
plugins-ldapjs 22.48% <ø> (ø)
plugins-light-my-request 24.60% <ø> (ø)
plugins-limitd-client 28.14% <ø> (ø)
plugins-lodash 24.08% <ø> (ø)
plugins-mariadb 35.17% <ø> (ø)
plugins-memcached 33.77% <ø> (ø)
plugins-microgateway-core 34.80% <ø> (ø)
plugins-modelcontextprotocol-sdk 32.44% <ø> (ø)
plugins-moleculer 36.73% <ø> (ø)
plugins-mongodb 35.18% <ø> (-0.10%) ⬇️
plugins-mongodb-core 34.84% <ø> (ø)
plugins-mongoose 34.61% <ø> (-0.09%) ⬇️
plugins-multer 24.91% <ø> (ø)
plugins-mysql 34.66% <ø> (ø)
plugins-mysql2 34.90% <ø> (ø)
plugins-node-serialize 25.25% <ø> (ø)
plugins-opensearch 33.63% <ø> (ø)
plugins-passport-http 24.83% <ø> (ø)
plugins-pino 30.07% <ø> (ø)
plugins-postgres 34.48% <ø> (ø)
plugins-process 24.94% <ø> (ø)
plugins-pug 25.20% <ø> (ø)
plugins-redis 34.27% <ø> (ø)
plugins-router 38.35% <ø> (ø)
plugins-sequelize 23.77% <ø> (ø)
plugins-test-and-upstream-amqp10 33.92% <ø> (+0.17%) ⬆️
plugins-test-and-upstream-amqplib 39.21% <ø> (ø)
plugins-test-and-upstream-apollo 34.95% <ø> (ø)
plugins-test-and-upstream-avsc 33.97% <ø> (ø)
plugins-test-and-upstream-bunyan 29.39% <ø> (ø)
plugins-test-and-upstream-connect 36.37% <ø> (ø)
plugins-test-and-upstream-graphql 35.98% <ø> (ø)
plugins-test-and-upstream-koa 35.93% <ø> (ø)
plugins-test-and-upstream-protobufjs 34.18% <ø> (ø)
plugins-test-and-upstream-rhea 39.31% <ø> (ø)
plugins-undici 34.69% <ø> (ø)
plugins-url 24.94% <ø> (ø)
plugins-valkey 33.74% <ø> (ø)
plugins-vm 24.94% <ø> (ø)
plugins-winston 29.94% <ø> (ø)
plugins-ws 37.21% <ø> (ø)
profiling-macos 43.41% <ø> (?)
profiling-ubuntu 43.80% <ø> (ø)
profiling-windows 41.17% <ø> (ø)
serverless-aws-sdk-latest-aws-sdk 33.54% <ø> (?)
serverless-aws-sdk-latest-bedrockruntime 31.80% <ø> (ø)
serverless-aws-sdk-latest-client 20.21% <ø> (ø)
serverless-aws-sdk-latest-dynamodb 34.35% <ø> (?)
serverless-aws-sdk-latest-eventbridge 27.43% <ø> (ø)
serverless-aws-sdk-latest-kinesis 37.53% <ø> (ø)
serverless-aws-sdk-latest-lambda 34.93% <ø> (ø)
serverless-aws-sdk-latest-s3 32.74% <ø> (?)
serverless-aws-sdk-latest-serverless-peer-service 39.78% <ø> (ø)
serverless-aws-sdk-latest-sns 38.68% <ø> (ø)
serverless-aws-sdk-latest-sqs 38.22% <ø> (?)
serverless-aws-sdk-latest-stepfunctions 33.48% <ø> (ø)
serverless-aws-sdk-latest-util 47.12% <ø> (?)
serverless-aws-sdk-oldest-aws-sdk 33.62% <ø> (+0.01%) ⬆️
serverless-aws-sdk-oldest-bedrockruntime 32.07% <ø> (ø)
serverless-aws-sdk-oldest-client 20.61% <ø> (ø)
serverless-aws-sdk-oldest-dynamodb 34.35% <ø> (ø)
serverless-aws-sdk-oldest-eventbridge 27.46% <ø> (ø)
serverless-aws-sdk-oldest-kinesis 37.66% <ø> (ø)
serverless-aws-sdk-oldest-lambda 34.99% <ø> (ø)
serverless-aws-sdk-oldest-s3 32.79% <ø> (ø)
serverless-aws-sdk-oldest-serverless-peer-service 39.82% <ø> (ø)
serverless-aws-sdk-oldest-sns 38.74% <ø> (ø)
serverless-aws-sdk-oldest-sqs 38.06% <ø> (ø)
serverless-aws-sdk-oldest-stepfunctions 33.54% <ø> (?)
serverless-aws-sdk-oldest-util 47.38% <ø> (ø)
serverless-azure-durable-functions 37.05% <ø> (+0.16%) ⬆️
serverless-azure-functions-eventhubs 38.52% <ø> (ø)
serverless-azure-functions-servicebus 38.58% <ø> (?)
serverless-lambda 34.83% <ø> (?)
test-optimization-cucumber-latest-7.0.0 50.32% <ø> (ø)
test-optimization-cucumber-latest-latest ?
test-optimization-cucumber-oldest-7.0.0 50.36% <ø> (ø)
test-optimization-cypress-latest-12.0.0-commonJS 48.26% <ø> (-0.53%) ⬇️
test-optimization-cypress-latest-12.0.0-esm 48.82% <ø> (ø)
test-optimization-cypress-latest-14.5.4-commonJS 48.64% <ø> (-0.12%) ⬇️
test-optimization-cypress-latest-14.5.4-esm 48.67% <ø> (+0.52%) ⬆️
test-optimization-cypress-latest-latest-commonJS 49.07% <ø> (-0.07%) ⬇️
test-optimization-cypress-latest-latest-esm 49.16% <ø> (ø)
test-optimization-cypress-oldest-12.0.0-commonJS 48.83% <ø> (ø)
test-optimization-cypress-oldest-12.0.0-esm 48.86% <ø> (ø)
test-optimization-cypress-oldest-14.5.4-commonJS 48.67% <ø> (ø)
test-optimization-cypress-oldest-14.5.4-esm 48.71% <ø> (ø)
test-optimization-jest-latest-latest 54.87% <ø> (ø)
test-optimization-jest-latest-oldest 51.34% <ø> (-2.27%) ⬇️
test-optimization-jest-oldest-latest 54.77% <ø> (ø)
test-optimization-jest-oldest-oldest 51.37% <ø> (-2.21%) ⬇️
test-optimization-mocha-latest-latest 53.59% <ø> (-0.03%) ⬇️
test-optimization-mocha-latest-oldest 51.28% <ø> (+0.02%) ⬆️
test-optimization-mocha-oldest-latest 53.68% <ø> (ø)
test-optimization-mocha-oldest-oldest 51.24% <ø> (ø)
test-optimization-playwright-latest-latest-playwright-active-test-span 44.29% <ø> (-0.05%) ⬇️
test-optimization-playwright-latest-latest-playwright-atr ?
test-optimization-playwright-latest-latest-playwright-efd 43.54% <ø> (ø)
test-optimization-playwright-latest-latest-playwright-final-status 43.61% <ø> (ø)
test-optimization-playwright-latest-latest-playwright-impacted-tests 43.05% <ø> (ø)
test-optimization-playwright-latest-latest-playwright-reporting 43.02% <ø> (ø)
test-optimization-playwright-latest-latest-playwright-test-management 44.78% <ø> (ø)
test-optimization-playwright-latest-oldest-playwright-active-test-span 44.35% <ø> (-0.05%) ⬇️
test-optimization-playwright-latest-oldest-playwright-atr 43.33% <ø> (ø)
test-optimization-playwright-latest-oldest-playwright-efd 43.59% <ø> (ø)
test-optimization-playwright-latest-oldest-playwright-final-status 43.64% <ø> (-0.03%) ⬇️
test-optimization-playwright-latest-oldest-playwright-impacted-tests 43.10% <ø> (ø)
test-optimization-playwright-latest-oldest-playwright-reporting 43.09% <ø> (ø)
test-optimization-playwright-latest-oldest-playwright-test-management 44.86% <ø> (ø)
test-optimization-playwright-oldest-latest-playwright-active-test-span 44.33% <ø> (-0.05%) ⬇️
test-optimization-playwright-oldest-latest-playwright-atr 43.15% <ø> (ø)
test-optimization-playwright-oldest-latest-playwright-efd 43.55% <ø> (ø)
test-optimization-playwright-oldest-latest-playwright-final-status 43.62% <ø> (ø)
test-optimization-playwright-oldest-latest-playwright-impacted-tests ?
test-optimization-playwright-oldest-latest-playwright-reporting ?
test-optimization-playwright-oldest-latest-playwright-test-management 44.80% <ø> (?)
test-optimization-playwright-oldest-oldest-playwright-active-test-span 44.39% <ø> (-0.05%) ⬇️
test-optimization-playwright-oldest-oldest-playwright-atr 43.37% <ø> (ø)
test-optimization-playwright-oldest-oldest-playwright-efd 43.61% <ø> (-0.03%) ⬇️
test-optimization-playwright-oldest-oldest-playwright-final-status 43.68% <ø> (ø)
test-optimization-playwright-oldest-oldest-playwright-impacted-tests 43.14% <ø> (ø)
test-optimization-playwright-oldest-oldest-playwright-reporting 43.10% <ø> (ø)
test-optimization-playwright-oldest-oldest-playwright-test-management 44.87% <ø> (ø)
test-optimization-selenium-latest 45.54% <ø> (ø)
test-optimization-selenium-oldest 45.10% <ø> (?)
test-optimization-testopt-active 46.94% <ø> (ø)
test-optimization-testopt-latest 46.90% <ø> (ø)
test-optimization-testopt-maintenance 46.94% <ø> (ø)
test-optimization-testopt-oldest 47.81% <ø> (ø)
test-optimization-vitest-latest 51.19% <ø> (ø)
test-optimization-vitest-oldest 48.28% <ø> (+0.69%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-official

datadog-official Bot commented May 25, 2026

Copy link
Copy Markdown

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 30 Pipeline jobs failed

Project | lint   View in Datadog   GitHub Actions

🔧 Fix in code (Fix with Cursor). Linting error: Wrapping single-element array with `Promise.all()` is unnecessary at line 354.

Test Optimization | integration-playwright (oldest, node-oldest, playwright-atr)   View in Datadog   GitHub Actions

🔧 Fix in code (Fix with Cursor). npm ci command failed. No package-lock.json present and lockfileVersion is less than 1.

Test Optimization | integration-playwright (latest, node-latest, playwright-active-test-span)   View in Datadog   GitHub Actions

🛟 This job is unlikely to succeed on retry. Please review your pipeline configuration. npm ci command failed. 'package-lock.json' or 'npm-shrinkwrap.json' not found or invalid lockfileVersion.

View all 30 failed jobs.

🧪 2 Tests failed in 1 job

LLMObs | langchain   GitHub Actions

Plugin langchain with @langchain/core &gt;=0.1 (0.1.0) chat model instruments a langchain openai chat model call for a JSON message input from chat model   View in Datadog (Fix with Cursor)
messageLike is not iterable

TypeError: messageLike is not iterable
    at coerceMessageLikeToMessage (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/messages/utils.cjs:18:29)
    at Array.map (&lt;anonymous&gt;)
    at BaseChatModel._convertInputToPromptValue (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/language_models/base.cjs:208:65)
    at ChatOpenAI.invoke (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/language_models/chat_models.cjs:41:39)
    at Context.&lt;anonymous&gt; (packages/datadog-plugin-langchain/test/index.spec.js:298:42)
    at process.processImmediate (node:internal/timers:483:21)
    at process.callbackTrampoline (node:internal/async_hooks:130:17)
Plugin langchain with @langchain/core &gt;=0.1 (1.1.47) chat model instruments a langchain openai chat model call for a JSON message input from chat model   View in Datadog (Fix with Cursor)
messageLike is not iterable

TypeError: messageLike is not iterable
    at coerceMessageLikeToMessage (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/messages/utils.cjs:18:29)
    at Array.map (&lt;anonymous&gt;)
    at BaseChatModel._convertInputToPromptValue (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/language_models/base.cjs:208:65)
    at ChatOpenAI.invoke (versions/node_modules/.bun/@langchain&#43;core@0.1.63&#43;5bc255f858ee32fa/node_modules/@langchain/core/dist/language_models/chat_models.cjs:41:39)
    at Context.&lt;anonymous&gt; (packages/datadog-plugin-langchain/test/index.spec.js:298:42)
    at process.processImmediate (node:internal/timers:483:21)
    at process.callbackTrampoline (node:internal/async_hooks:130:17)

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 86.37% (+0.00%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c201603 | Docs | Datadog PR Page | Give us feedback!

@pr-commenter

pr-commenter Bot commented May 25, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-05-25 12:27:55

Comparing candidate commit c201603 in PR branch BridgeAR/2026-05-25-supply-chain-cooldown with baseline commit 0925615 in branch BridgeAR/2026-05-09-remove-yarn.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 1496 metrics, 97 unstable metrics.

@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-05-09-remove-yarn branch 6 times, most recently from 17970e4 to b74badb Compare July 15, 2026 15:16
@BridgeAR

Copy link
Copy Markdown
Member Author

Closing, as superseded by the original PR

@BridgeAR BridgeAR closed this Jul 15, 2026
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.

1 participant