fix(ci): repair the macOS Intel and Windows artifact builds - #61
Conversation
CI results (run 34031480058)
macOS: fixed, with structural proofA green tick alone would be weak evidence here, since the Intel job already passed ~90% of And the DMG is still produced, by the retry-capable script:
Previously Intel spent ~24m inside Windows: the pin worked, and uncovered the next bugnode-gyp and
This is not fixable from this branch. The failing package is the root dependency, which That is precisely one of the files #48 replaces ( So the Windows leg needs the runner pin and those source fixes. #48 has both; this branch Suggested sequencingMerge #48 first (pin + source fixes, already green on run 33819168800). This PR then reduces Assisted-by: AI |
The Windows release job has failed on every pull request since better-sqlite3 entered the dependency tree. node-gyp cannot parse the Visual Studio install path on the current windows-latest image, which is now a bare "\18\" (VS 2026 naming), and fails with unknown version "undefined". npm ci performs native rebuilds with npm's own bundled node-gyp and ignores npm_config_node_gyp, so pointing at a newer node-gyp does not help. Pin the job to windows-2022, whose image predates the rename, with a dated TODO recording when the pin can be lifted. The macOS jobs let Tauri run bundle_dmg.sh even though the DMG it produces is deleted and rebuilt by scripts/create-macos-dmg.mjs in "Finalize platform bundles". That duplicate work is not free: on run 33818382290 it hung on hdiutil for 24 minutes and failed the macos-15-intel job, leaving an orphaned diskimages-help process. Build only the app bundle on macOS so the redundant script never runs. Both macOS legs execute it, so both are covered. Restricting the bundle means Tauri no longer creates the dmg directory, so create it before the cleanup find, which would otherwise abort under set -euo pipefail. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
69ef1e9 to
923e4c8
Compare
…ipts With the runner pinned to windows-2022, npm ci gets past better-sqlite3 and now fails in the vendored read-core build script: npm error path ...\reference-implementation\vendor\read-core npm error Error: spawn npx ENOENT npm error spawnargs: [ 'tsc', '--project', 'tsconfig.build.json' ], execFile resolves a bare command name by PATH lookup alone. Without a shell there is no PATHEXT resolution, so on Windows it never finds the npx.cmd shim npm writes for bin entries. Both read-core and mcp-server run this script from a prepare hook, so npm ci executes them on every install; read-core failed first only because it is installed first. Pass shell: platform === "win32" so the lookup goes through cmd.exe there and stays a direct spawn everywhere else. This matches the existing cross-platform fix on main for these same scripts (068bc81, which stopped them shelling out to pnpm). Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
With npm ci fixed, the Windows Tauri build reaches rustc and fails: error[E0432]: unresolved import `super::server::kill_process_group` --> src\commands\ref_server.rs:35:5 note: found an item that was configured out --> src\commands\server.rs:13:8 kill_process_group is defined under #[cfg(unix)] in server.rs, and all four call sites in ref_server.rs are already inside #[cfg(unix)] blocks. Only the import was ungated, so the module failed to resolve on Windows and nowhere else. Verified by mutation on a reduced model of the same cfg structure: with the gate the non-unix configuration compiles; removing it reproduces E0432 exactly. Unix keeps the import in use, so no unused-import warning appears there. Signed-off-by: Tim Nunamaker <tnunamak@gmail.com> Assisted-by: AI
Round 2 — rebased onto #55; all four build jobs now pass
The useful finding: Windows was never one bug. It was a chain of four, each hidden
3 —
|
Summary
Repairs the Windows and macOS legs of
Release manual-install artifacts. All four buildjobs now pass (run 34038355147). Three commits.
Windows turned out not to be one bug but a chain of four, each hidden behind the previous
one in the same
npm ci→ build sequence:\18\path, sobetter-sqlite3won't buildwindows-2022(here)spawnSync patchright ENOENTmainvia #55spawn npx ENOENTin vendoredread-core/mcp-serverbuild scriptsshell: platform === "win32"(here)error[E0432]— Unix-onlykill_process_groupimport not#[cfg(unix)]-gatedmacOS is a separate, unrelated fix: the Intel job intermittently hung ~24m in Tauri's
bundle_dmg.shand died with an orphaneddiskimages-help. That DMG is deleted and rebuiltby
scripts/create-macos-dmg.mjs, which retries onhdiutilresource busy— so the jobwas dying inside discarded work using the fragile implementation.
--bundles appskips it.#48 is subsumed by this PR and can be closed — see the Round 2 comment. Detailed
evidence for every claim, including two corrected premises, is in the comments below.
Original PR description (written before #55 merged; superseded in places)
Summary
Two release-artifact build jobs were investigated:
build (windows-…)andbuild (macos-15-intel, …). They fail for unrelated reasons, and only one of them isactually broken on every run.
Windows — a hard break, red on 9 of the last 9 runs.
npm cifails while buildingbetter-sqlite3, this repo's only Windows-native dependency. Thewindows-latestimagenow installs Visual Studio under a bare
\18\path (VS 2026 naming). node-gyp 11.5.0expects a year — 2017/2019/2022 — reads the version as
undefined, and gives up eventhough a usable toolchain is present:
Pointing npm at a newer node-gyp does not fix this.
npm ciruns its automatic nativerebuilds through its own bundled copy and ignores
npm_config_node_gyp(npm/cli#2839);the stack trace confirms the failing binary is
…\node\22.23.1\x64\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js. The job ispinned to
windows-2022, whose image predates the rename, with a dated TODO for unpinningonce
actions/setup-node's Node 22 LTS ships npm ≥ 11.6.3 (node-gyp ≥ 12.1.0, which addedVS 2026 detection). Fixes #47.
macOS — an intermittent hang, not a constant failure. On run 33818382290 the Intel job
spent nearly 24 minutes inside Tauri's
bundle_dmg.shbefore failing, leaving an orphaneddiskimages-helpprocess — a wedgedhdiutil:The load-bearing detail is that this work is thrown away.
Finalize platform bundlesdeletes every DMG Tauri just produced and rebuilds it with
scripts/create-macos-dmg.mjs,which exists precisely because
hdiutilis flaky — it retries and detaches stale deviceson
resource busy. The job was dying inside a step whose output is discarded, using thefragile implementation, before ever reaching the robust one. Restricting the macOS build
to
--bundles appskipsbundle_dmg.shentirely.Both macOS legs run that script — the ARM job reached
Running bundle_dmg.shon the samerun and simply got lucky — so the flag is applied to both, not only Intel.
Two corrections to the original diagnosis
macos-15-intelis not retired. The starting assumption was that the label had beenretired and needed replacing. It has not: it schedules real runners and passed on
2026-09-04 (
{"conclusion":"success","labels":["macos-15-intel"],"runner":"GitHub Actions 1001845299"}).A retired label does not schedule, it queues until timeout. Replacing or dropping it would
have removed a working target and broken releases, since
publishrequiresmanual-install-macos-x64.The Intel job was not failing on every PR. It is green in 11 of the last 12 runs. It
is worth fixing because this removes the cause rather than the symptom, but it is a flake
fix. A green run here does not by itself prove it — the job passes ~90% of the time
anyway. The structural evidence is that
bundle_dmg.shno longer runs at all, so the stepthat hung cannot hang; confirm by checking the macOS logs no longer contain
Running bundle_dmg.sh.Overlap with #48 — please read before merging
The Windows change here is byte-for-byte identical to open PR #48, which is already
proven green (run 33819168800: all four build jobs pass, including
windows-2022andmacos-15-intel). What #48 does not contain is the macOS--bundles appchange; itsrelease.ymldiff touches only the Windows matrix entry.Reasonable options:
carries the Windows fix with green CI and its own written rationale.
Either is defensible, but both PRs currently edit the same matrix entry, so one of them
should give way rather than both merging.
Note on the third change
mkdir -p "$bundle_root/dmg"is not cosmetic. With--bundles app, Tauri no longercreates the
dmg/directory, so the cleanupfindthat follows would exit non-zero andabort the step under
set -euo pipefail.Verification
appwas confirmed to be a real bundle value rather than assumed. Intauri-cli-v2.11.4,--bundlestakesBundleFormat, a newtype overPackageTypewhoseFromStrdelegates toPackageType::from_short_name, which maps"app" => PackageType::MacOsBundle.ValueEnumexposes all of
PackageType::all()and only hidesNsis/Updaterfrom help outputwithout rejecting them — so the shorter list shown by
tauri build --helpon Linux is adisplay artifact, not a validation limit.
appis also the.appbundle the DMG stepalready depends on, so nothing the workflow consumes is lost.
Assisted-by: AI