Skip to content

Fix Windows CI against Visual Studio 2026 and Node 26 - #1001

Open
X-Guardian wants to merge 1 commit into
mapbox:masterfrom
X-Guardian:chore/fix-vs2026
Open

X-Guardian wants to merge 1 commit into
mapbox:masterfrom
X-Guardian:chore/fix-vs2026

Conversation

@X-Guardian

@X-Guardian X-Guardian commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Closes #998, which has the diagnosis: windows-latest now ships Visual Studio 2026, the tests hardcode --msvs_version=2022, and node-gyp only recognises VS 18 from v12 onwards.

Changes

Drop the hardcoded --msvs_version=2022 from test/run.util.js and let node-gyp detect the toolchain. Each runner image carries exactly one Visual Studio, so there is nothing to disambiguate: the flag only ever asserted a year that happened to match. It was not deliberate either. It began as --msvs_version=2015 with the comment "since that is more edge case than 2013", and the 2022 value arrived via a mechanical bump in #707, needing an edit on every image change since.

Add windows-2022 to both matrices. VS 2022 remains widely used and is the image GitHub directs users to when they need it, so it is worth covering alongside VS 2026 rather than testing only the newest toolchain.

Add scripts/upgrade-node-gyp.js, run on Windows via npm run upgrade-node-gyp. It reads the version of the node-gyp that node-pre-gyp would invoke and installs a newer one only when that version predates VS 2026 support. Keying off the resolved node-gyp rather than the Node version matters because the matrix uses floating aliases: lts/-1 is Node 22 today and becomes Node 24 when Node 26 enters LTS, at which point the script finds node-gyp 12 and does nothing.

Skip one test where npm's own node-gyp is too old. npm runs install hooks against the copy it bundles, ignoring npm_config_node_gyp whether set by environment variable, .npmrc, or --node-gyp. Where that copy cannot detect the installed Visual Studio, app1 passes --nodedir down to node-gyp via npm fails at VS detection before --nodedir is read, so the assertion cannot be made. The sibling test covers the same forwarding via node-pre-gyp directly.

Regenerate abi_crosswalk.json through Node 26.10.0. The latest matrix entry now resolves to Node 26, which failed with Unsupported target version: 26.9.0 on every platform.

node-gyp resolution in the tests

npm resets npm_config_node_gyp to its bundled copy whenever it runs a script, so a value exported by the upgrade step does not survive npm test. The script therefore exports NPG_TEST_NODE_GYP, a name npm leaves alone, and test/run.util.js passes it to each child as npm_config_node_gyp, which node-pre-gyp already reads.

This keeps the change out of the published package: lib/util/compile.js gains one line exporting which_node_gyp, so the upgrade script resolves node-gyp exactly as the build does. No resolution behaviour changes for consumers.

Result

15 jobs in ci.yml and 12 in s3-bucket.yml, with Windows covered on both toolchains:

Node Currently windows-latest (VS 2026) windows-2022 (VS 2022)
lts/-1 22.23.2 node-gyp upgraded bundled node-gyp
lts/* 24.21.0 bundled node-gyp bundled node-gyp
latest 26.9.0 bundled node-gyp bundled node-gyp

Non-Windows jobs are unaffected. The upgrade step is guarded by runner.os == 'Windows', and --msvs_version was only ever passed under a win32 check.

Notes for reviewers

  • The node-gyp version installed by the upgrade is pinned in the script as INSTALL_VERSION rather than tracking @latest, so CI does not silently follow new node-gyp releases.
  • The install is local and --no-save. A global install is not picked up: which_node_gyp resolves through npm_config_node_gyp, then require.resolve, then npm's bundled copy, none of which see the global prefix. Verified by installing node-gyp 13.0.2 globally and confirming resolution still returned npm's bundled copy.
  • s3-bucket.yml also picks up a fix for ${{ matrix.node }} references left behind by the matrix key rename in chore: replace the end-of-life Node 20 in the CI test matrices #999. Its tests are skipped when S3_BUCKET is unset, so the Windows changes there are untested in forks.
  • npm run update-crosswalk remains commented out in ci.yml, so the crosswalk will go stale again on the next Node release.

@X-Guardian
X-Guardian requested a review from a team as a code owner September 17, 2026 11:48
@ox-security

ox-security Bot commented Sep 17, 2026

Copy link
Copy Markdown

OX Security Logo

OX Security reviewed this pull request — nothing to fix.

No issues found

Branch chore/fix-vs2026master

View scan in OX Security →

@X-Guardian X-Guardian changed the title Fix Windows CI against Visual Studio 2026 Fix Windows CI against Visual Studio 2026 and Node 26 Sep 23, 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.

All Windows CI jobs fail: due to windows-latest now shipping Visual Studio 2026

1 participant