Skip to content

Fix CI: untrack generated hook bundle + mock registry for tarball tests#208

Merged
John-David Dalton (jdalton) merged 2 commits into
mainfrom
jdalton/socket-lib-ci-green
Jul 24, 2026
Merged

Fix CI: untrack generated hook bundle + mock registry for tarball tests#208
John-David Dalton (jdalton) merged 2 commits into
mainfrom
jdalton/socket-lib-ci-green

Conversation

@jdalton

@jdalton John-David Dalton (jdalton) commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What

Makes main CI green and keeps it durably green. The failing run (30109765260) had two red jobs — 🔎 Check and 🧪 Test — and this PR fixes both, then fixes the shared root cause behind the flake so no other network suite can hit it.

The fixes

1. 🔎 Check — untrack the generated fleet hook bundle

.claude/hooks/fleet/_dist/bundle.cjs was tracked in git but is a generated, release-only artifact that .gitignore already ignores. That disagreement (index says "tracked", .gitignore says "ignore") tripped ignored-files-are-untracked and generated-outputs-are-untracked. Removed from the index with git rm --cached — the working-tree file is untouched and stays gitignored.

2. 🧪 Test — mock the npm registry for the tarball tests (don't skip)

The is-number suites in test/unit/packages/tarball.test.mts drove pacote to the real registry.npmjs.org. They now serve is-number@7.0.0 from committed fixtures via nock, so the whole suite runs deterministically offline. The one live-network test that genuinely can't be mocked (a real git clone) stays network-gated.

3. 🧪 Test — wire the repo-tier vitest setup so [network] suites skip by default (root-cause fix)

The flake wasn't unique to tarball. The repo-tier test setup that sets SOCKET_LIB_SKIP_NETWORK_TESTS had been silently dropped by a directory reorg, so every describeNetworkOnly suite was running live against a fail-closed nock. This commit restores it, which durably fixes the same flake in test/unit/dlx/lockfile.test.mts and test/unit/packages/fetch.test.mts too.

Why the bundle was untracked (fleet generated-artifact rule)

The fleet convention is that generated build outputs are never committed — they are produced at release time and listed in .gitignore. .gitignore already contains /.claude/hooks/fleet/_dist/, and a bundle refresh drops bundle.cjs onto disk. But the file had also been added to git's index, so git was simultaneously tracking a file it was told to ignore. The two fleet checks exist to catch exactly this. git rm --cached removes the index entry while leaving the on-disk file in place, so both checks pass and nothing about the working tree changes.

The tarball flake, and how the registry mock makes it deterministic

The tarball extract/pack tests were wrapped in describeNetworkOnly, which is meant to skip them unless network testing is opted in. Because the skip env was not being set (see fix #3), the suite ran live — while the shared setup's beforeAll had called nock.disableNetConnect(). The in-process pacote request was then blocked and the test failed with Nock: Disallowed net connect for "registry.npmjs.org". That is what turned the run red on should lazy load cacache on first use.

The fix removes the network dependency for these tests entirely:

  • Committed fixtures. test/fixtures/npm/is-number-7.0.0.tgz is the real tarball, and packument-is-number.json is a minimal packument whose dist.integrity / dist.shasum match the tarball bytes exactly — otherwise pacote throws EINTEGRITY. nock serves both the packument (GET /is-number) and the tarball, following the existing registry-mock convention in test/unit/npm/registry.test.mts.
  • agent: false. nock 15 is backed by @mswjs/interceptors, which cannot intercept pacote's requests because make-fetch-happen routes them through a keepalive agent pool. Threading pacote's documented agent: false passthrough (via a small withMockedNet helper) makes it use Node's default agent so the interceptors match. This changes nothing about what the tests assert — it mirrors the existing Arborist passthrough.
  • Overload tests use the local fixture. The (spec, callback) overload tests pass no options object, so they can't thread agent: false; they use the committed tarball's file path as the spec and extract offline through pacote's file fetcher.
  • Gating. The now-offline suites moved out of describeNetworkOnly so they always run. The git-spec test shells out to a real git clone, a subprocess nock can't intercept and the leak can't affect, so it stays network-gated.
  • .gitignore now allowlists test/fixtures/npm/*.tgz so the tarball fixture can be committed (the *.tgz glob would otherwise ignore it — the same tracked-vs-ignored trap as fix Bump @inquirer/search from 3.1.1 to 3.1.3 #1).
The skip-race root cause, and the one-file fix

skip-helpers decides whether to skip a [network] suite by reading process.env['SOCKET_LIB_SKIP_NETWORK_TESTS'] once, at import time. That env var is set by the repo-tier vitest setup. The fleet-canonical config wires setup like this:

setupFiles: [
  'test/fleet/scripts/setup.mts',
  'test/repo/scripts/setup.mts',
].filter(p => existsSync(p)),

A directory reorg renamed test/scripts/{fleet,repo}/ to test/{fleet,repo}/scripts/. The fleet half (test/fleet/scripts/setup.mts) was created, but the repo half (test/repo/scripts/setup.mts) never was — so the existsSync filter silently dropped it, with no error. The env var was therefore never set, skipNetwork was always false, and every describeNetworkOnly / itNetworkOnly suite ran live against the fleet setup's fail-closed nock.disableNetConnect(), failing with Disallowed net connect.

The fix creates test/repo/scripts/setup.mts — the exact path the config expects, and the path the fleet setup's own docstring names as the repo-setup home. It defers to the repo's long-standing .config/vitest-setup-tests.mts, so the skip env is set at setupFile-import time, before any test module (and its import-time network gate) is evaluated. SOCKET_LIB_RUN_NETWORK_TESTS=1 still opts the live lane in.

Note for a follow-up (belongs in the fleet cascade, not this repo PR): the old test/scripts/{fleet,repo}/setup.mts files are orphaned leftovers from the reorg, and .gitattributes + the config's setup comment still reference the old test/scripts/... paths. They are inert (nothing loads them), so I left them rather than churn fleet-canonical files here.

Verification

  • 🔎 Checkpnpm run check --all no longer reports ignored-files-are-untracked or generated-outputs-are-untracked.
  • 🧪 Test — the full suite now has zero Disallowed net connect failures (was 8 across dlx/lockfile + fetch, plus the tarball flake). The previously-flaky [network] suites now skip deterministically.
  • Repeated-run proofdlx/lockfile + fetch + tarball + secrets re-run 5× back-to-back: 48 passed | 22 skipped every time. tarball.test.mts alone: 21/21, also re-run 5×. Deterministic — the flake is gone.
  • pnpm run lint and the typecheck are clean.

(The three git / find test failures seen in a local full run are worktree-path artifacts — they assert the checkout dir is socket-lib, but a scratch worktree is named differently. They pass in a normal CI checkout and are unrelated to this PR.)

The fleet hook bundle at .claude/hooks/fleet/_dist/bundle.cjs is a
release-only generated artifact. It is already covered by .gitignore
(the /.claude/hooks/fleet/_dist/ rule), yet it was still tracked in the
index, so the fleet Check job failed both ignored-files-are-untracked
and generated-outputs-are-untracked (index vs .gitignore disagree).

Remove it from the index with git rm --cached. The working-tree file is
kept (a bundle refresh lands it on disk) and stays gitignored.
The is-number tarball suites in tarball.test.mts went through pacote to
the live registry.npmjs.org. They were gated behind describeNetworkOnly,
but a module-eval race lets one escape the network skip and run while the
shared test setup's nock.disableNetConnect() (or a sibling file's) is
active, so it fails with 'Disallowed net connect' — the flake that turned
CI red on 'should lazy load cacache on first use'.

Make the extract/pack tests deterministic and offline:

- Serve the is-number@7.0.0 packument and tarball from committed fixtures
  via nock. The packument's dist.integrity/shasum match the tarball bytes
  exactly so pacote's integrity check passes.
- Thread pacote's documented 'agent: false' passthrough (via withMockedNet)
  so make-fetch-happen uses Node's default agent; nock 15 (backed by
  @mswjs/interceptors) cannot intercept the keepalive agent pool otherwise.
  Same mechanism as the existing 'Arborist' passthrough.
- Drive the (spec, callback) overload tests from the local tarball fixture
  path so they extract offline via pacote's file fetcher, no registry.
- Move the now-offline suites out of the describeNetworkOnly gate so they
  always run. The git-spec test shells out to a real 'git clone' (a
  subprocess nock can't intercept, and which the leak can't affect), so it
  stays network-gated.
- Allowlist test/fixtures/npm/*.tgz in .gitignore so the tarball fixture
  can be committed (the *.tgz glob would otherwise ignore it).
@jdalton
John-David Dalton (jdalton) merged commit 07bf4e0 into main Jul 24, 2026
6 checks passed
@jdalton
John-David Dalton (jdalton) deleted the jdalton/socket-lib-ci-green branch July 24, 2026 17:12
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