Skip to content

Fix macOS CI: brew-installed danger-js embeds a Node <18.17, breaking undici's fetch() - #664

Merged
f-meloni merged 5 commits into
danger:masterfrom
DylanBettermannDD:db/macos-ci-node-fix
Aug 21, 2026
Merged

f-meloni merged 5 commits into
danger:masterfrom
DylanBettermannDD:db/macos-ci-node-fix

Conversation

@DylanBettermannDD

Copy link
Copy Markdown
Contributor

Problem

Every macOS CI leg on PRs to this repo fails, unrelated to what the PR actually changes — including on #662 and my own #663. Swift itself is fine (swift test passes 174/174 on macos-15/Xcode 16.1); the job dies in the danger-swift ci step, inside danger-js:

Failed to fetch GitHub pull request files: TypeError: terminated
    at Fetch.onAborted (/snapshot/danger-js/node_modules/undici/lib/web/fetch/index.js:2046:49)
  [cause]: TypeError [ERR_INVALID_ARG_TYPE]: The "stream" argument must be an instance of Stream.
           Received an instance of ReadableStream
      at eos (node:internal/streams/end-of-stream:65:11)
      at fetchFinale (…/undici/lib/web/fetch/index.js:1101:5)

Root cause

/snapshot/… is pkg's virtual filesystem — the crash is inside the brew-installed standalone danger-js binary, which embeds its own Node, not the runner's Node (which is fine — 22/24 on current images):

Fact Source
macOS jobs install via brew install danger/tap/danger-js .github/workflows/ci.yml
that formula ships a prebuilt pkg-built zip danger/homebrew-tap/danger-js.rb
built via pkg … --targets node18-macos-{x64,arm64} → embedded Node 18 danger-js package.json
pkg@^5.8.1pkg-fetch@3.4.2, whose newest Node 18 base is v18.15.0 vercel/pkg package.json; pkg-fetch patches tree
shipped danger-js 13.0.10 pins undici 6.21.1 exactly danger-js@13.0.10 package.json + yarn.lock
undici@6.x requires node >=18.17 its engines field

18.15 < 18.17, so undici's fetchFinale hands stream.finished() a web ReadableStream it doesn't support on that Node, and every fetch() throws. This started when danger-js switched from node-fetch to undici (commit c8b966ae, shipped in 13.0.10, 2026-06-25) — consistent with the last green macOS PR run being 2025-09-28.

The Linux jobs never hit this: they already install danger from npm via actions/setup-node + yarn global add danger instead of the brew binary, and pass.

Fix (4 commits)

  1. Install danger-js on macOS the way the Linux jobs already doactions/setup-node@v4 (Node 20.x) + yarn global add danger, in all three macOS jobs. This is a verbatim copy of the block test-on-linux/test-without-spm-on-linux have used successfully for a while, so it inherits their track record rather than being a new install path.
  2. Retire the macos-13 legs, add macos-26. Both macos-13 legs sat queued for an entire run and never complete — that runner image is gone from actions/runner-images. Also removes the now-dead matrix.runner == 'macos-13' conditional in test-without-spm-on-macos.
  3. Bump swift-snapshot-testing 1.17.5 → 1.17.7. Required for the new macos-26/Xcode 26.6 leg: 1.17.5's SnapshotsTestTrait.swift fails to compile under Swift 6.3 (cannot use conformance of 'Never' to 'TestScoping'... imported as implementation-only); 1.17.7 fixes it. Verified this doesn't silently re-resolve past 1.17.x despite Package.swift's from: "1.17.0"swift package update swift-snapshot-testing under Xcode 26.6 lands on exactly 1.17.7, not 1.19.x, so Package.resolved alone holds without a tighter manifest bound. Full, unfiltered swift test passes 165/165 with this pin.
  4. CHANGELOG entry.

Notes for review

  • Deliberately left unpinned/mutable, matching the existing Linux jobs exactly rather than unilaterally hardening only the macOS side: danger is installed at latest (Linux does the same today), actions/setup-node@v4 is a mutable major tag (so is every other action in this file), and yarn global add/yarn global bin are Yarn Classic commands (also already relied on by the Linux jobs, which have no package.json/Corepack in this repo to conflict with). Happy to pin any of these repo-wide in a follow-up if you'd like, but didn't want to make that call unilaterally in a CI-unblocking PR.
  • macos-26 uses Xcode 26.6 under the native SwiftPM build system (Swift 6.3), the same module layout as the already-passing macos-14/macos-15 legs — not swiftbuild (Xcode 27's new default, the layout Probe for the actual Danger.swiftmodule instead of trusting the compiler that built danger-swift #663 is about), so this PR doesn't touch that code path.
  • Dropping macos-13 removes the last Intel-macOS leg (macos-14/-15/-26 are all arm64) and the only remaining Swift 5.8 toolchain in CI (the stated minimum in Package.swift/README) — Linux starts at 5.9. Flagging both in case either matters to you; happy to add back an older-toolchain leg if so.
  • I'd posted on Probe for the actual Danger.swiftmodule instead of trusting the compiler that built danger-swift #663 assuming the runner's own Node/undici was the issue — that was wrong (the runner's Node is fine; the embedded Node in the brew binary is what's broken). I've corrected that there.

Testing

  • Unfiltered swift test: 165/165 passing, Xcode 26.6, with the 1.17.7 pin.
  • swift build -c release --product danger-swift: succeeds, Xcode 26.6.
  • swift package update swift-snapshot-testing under Xcode 26.6 resolves to 1.17.7, confirming the Package.resolved pin holds.
  • YAML validated with yaml.safe_load.
  • CI on this PR is the real end-to-end proof — will report back once it runs.

…g Linux legs

The brew-installed danger-js on macOS is a pkg-built standalone binary with
its own embedded Node 18 (pkg --targets node18-macos-*; pkg 5.8.1 ->
pkg-fetch 3.4.2, whose newest Node 18 base is v18.15.0). danger-js 13.0.10
pins undici 6.21.1, which requires node >=18.17 per its engines field.
Below that floor, undici's fetchFinale hands stream.finished() a web
ReadableStream it doesn't support, so every fetch() in danger-swift ci
throws ERR_INVALID_ARG_TYPE and the step fails before Danger can post
anything -- unrelated to the runner's own Node (22/24), which is fine.

danger-js switched from node-fetch to undici in 13.0.10 (2026-06-25),
which is why every macOS PR run since has failed identically, including
on PRs unrelated to this change (danger#662, danger#663).

The Linux jobs already avoid this by installing danger from npm via
actions/setup-node + yarn instead of the brew binary. Do the same on
macOS.
Both macos-13 legs sat permanently 'queued' -- that image is retired and
absent from actions/runner-images/images/macos/ (only macos-14, -15, -26
remain), so those checks can never complete. Drop them, and add a
macos-26 / Xcode 26.6 leg to all three macOS jobs, including
test-dependencies-resolver -- the only job exercising the inline
'package:' / Script.artifactsPath path.
Required by the new macos-26 leg: under Swift 6.3 (Xcode 26.6) and 6.4
(Xcode 27), swift test fails on 1.17.5 with

  error: cannot use conformance of 'Never' to 'TestScoping' here;
  'Testing' has been imported as implementation-only

from SnapshotsTestTrait.swift. 1.17.7 fixes it.

1.17.7 is the ceiling: all 1.17.x releases are swift-tools-version:5.7,
compatible with every remaining leg. 1.18.0+ raise to tools-version 6.0,
which the Swift 5.9/5.10 Linux legs and macos-14/Xcode 15.4 cannot use.

Verified this doesn't silently re-resolve past 1.17.x despite
Package.swift's 'from: "1.17.0"': 'swift package update
swift-snapshot-testing' under Xcode 26.6 lands on exactly 1.17.7, not
1.19.x, so the Package.resolved pin holds without needing a tighter
manifest constraint.

Full, unfiltered 'swift test' passes (165/165) under Xcode 26.6 with
this pin.
@DylanBettermannDD
DylanBettermannDD marked this pull request as ready for review August 2, 2026 00:15
@DylanBettermannDD

Copy link
Copy Markdown
Contributor Author

@f-meloni this is ready for review — root cause and fix are described above, and CI is green (15/15, including the new macos-26 legs). I couldn't assign or request review directly (no write access as an outside contributor), so flagging here instead. Also left context on #663 since it's blocked on this same CI issue.

@renfrenkel

Copy link
Copy Markdown

@f-meloni pinging to make sure this is still on your radar

@f-meloni

Copy link
Copy Markdown
Member

Thank you!

@f-meloni
f-meloni merged commit 3c86f5e into danger:master Aug 21, 2026
15 checks passed
@DylanBettermannDD
DylanBettermannDD deleted the db/macos-ci-node-fix branch August 21, 2026 16:22
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.

3 participants