Skip to content

Fix Visual Studio 2026 native installs with node-gyp 12 - #1142

Open
Bill Schnurr (bschnurr) wants to merge 3 commits into
microsoft:mainfrom
bschnurr:fix/signing-native-install
Open

Bill Schnurr (bschnurr) wants to merge 3 commits into
microsoft:mainfrom
bschnurr:fix/signing-native-install

Conversation

@bschnurr

@bschnurr Bill Schnurr (bschnurr) commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Fix DevDiv build 15947122: the shared Pylance-Eng signing template runs this repository's npm ci, and @vscode/windows-process-tree fails to rebuild because npm's bundled node-gyp 11.2.0 cannot detect Visual Studio 18.
  • Add node-gyp: ^12.4.0 as a development dependency, so lifecycle scripts use a project-local version supporting Visual Studio 2026 and the pipeline's Node 22.21.1.
  • Regenerate and normalize the lockfile through the Microsoft package proxy, preserving existing locked dependency versions.
  • Remove the earlier unused signing-template workaround. The final diff changes only package.json and package-lock.json; shared signing behavior is unchanged.

Validation

  • npm run ci:msft and npm run normalize-lockfile.
  • Explicit npm rebuild @vscode/windows-process-tree --foreground-scripts: node-gyp 12.4.0 detected Visual Studio 2026 and successfully compiled the native module.
  • Native process-tree smoke test passed.
  • npm run lint and npm run compile-tests passed.
  • Package JSON/lockfile Prettier and whitespace checks passed.
  • Executable assertions verify existing locked dependency versions are preserved and the signing template matches upstream.

Local validation used Node 26.13.0 and Visual Studio 2026. Azure CI under Node 22.21.1 and end-to-end signing remain to be verified.

Skip dependency lifecycle scripts when installing tooling for prebuilt VSIX signing, then initialize only the vsce signing binary. This avoids rebuilding windows-process-tree with an unsupported Visual Studio toolchain.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35aea860-84b7-4f12-88da-cff7120df961
@bschnurr Bill Schnurr (bschnurr) added the bug Issue identified by VS Code Team member as probable bug label Nov 6, 2026
@bschnurr
Bill Schnurr (bschnurr) enabled auto-merge (squash) November 6, 2026 23:10
@bschnurr

Copy link
Copy Markdown
Member Author

Follow-up investigation found this PR targets an unused local signing template. The pre-release pipeline imports azure-pipelines/extension/templates/jobs/publish-extension.yml from DevDiv/Pylance-Eng, which invokes ../steps/sign.yml in that shared repository. This change therefore does not fix build 15947122. Auto-merge has been disabled; do not merge this PR as the build fix. The native-install correction belongs in the active shared Pylance-Eng signing template.

Add project-local node-gyp 12.4.0 so windows-process-tree lifecycle scripts can detect Visual Studio 18 on the signing agents. Regenerate the lockfile without upgrading existing dependencies and remove the unused local signing-template workaround.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35aea860-84b7-4f12-88da-cff7120df961
@bschnurr Bill Schnurr (bschnurr) changed the title Fix native dependency installation in signing jobs Fix Visual Studio 2026 native installs with node-gyp 12 Nov 6, 2026
@bschnurr

Copy link
Copy Markdown
Member Author

The earlier warning about this PR targeting an unused template is now superseded. The branch has been updated to current main, the template workaround has been removed, and the final diff changes only package.json and package-lock.json to add project-local node-gyp 12.4.0. An explicit windows-process-tree rebuild successfully detected Visual Studio 2026 and compiled the native module; a process-tree smoke test, lint, and TypeScript checking passed. Azure CI still needs to validate Node 22 and signing.

@rchiodo

Rich Chiodo (rchiodo) commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR.

@rchiodo

Copy link
Copy Markdown
Contributor

Reviewed commit: d6f7fce6a9a9af7345492d98768443eb40714fb5

Result: ⚠️ partially-verified

Verification details

Verification: Automated verification is best effort. The PR author remains responsible for testing.

Summary: Offline dependency installation succeeded in the Linux container, and all 39 setup/registry/lockfile tests passed. Test compilation, lint, JSON formatting, lockfile normalization, and project-local node-gyp lifecycle resolution checks also passed; the dependency graph accepts Node 22.21.1 according to its engine constraints. No tests were added by the PR, and no PR-caused failures were observed. Visual Studio 2026 native compilation, Windows process-tree smoke testing, and end-to-end signing remain unverified; baseline-version comparison was unavailable because the container lacks Git metadata. **Reviewer dependency follow-up (nonblocking):** Suggest a separate PR adding `eslint: ^8.50.0`, `node-gyp: ^12.4.0`, `prettier: ^3.0.3`, `typescript: ^5.5.4` to the official reviewer dependency declarations, using `package.json` as the dependency/version evidence. Do not automatically create that PR. This is reviewer environment maintenance, not a required change to the reviewed PR.

Test runs: 5 passed, 1 failed, 2 not run

  • ⚠️ Not run | Attach Quick Pick provider extension tests
  • ❌ Failed | unrelated to this PR | Dependency and test discovery | printf 'profile=%s\n' "$AUTOMATION_SANDBOX_PROFILE"; uname -s; node --version; npm --version; git remote -v; git log -3 --oneline; git diff HEAD^ HEAD --stat; node -e 'const fs=require("fs"); const p=require("./package.json"); console.log(JSON.stringify({scripts:p.scripts,nodeGyp:p.devDependencies["node-gyp"],native:p.dependencies["@vscode/windows-process-tree"]},null,2)); for (const x of ["node-gyp","typescript","eslint","prettier"]) { try { console.log(x+": "+require.resolve(x+"/package.json")); } catch { console.log(x+": MISSING"); } } console.log("node_modules exists: "+fs.existsSync("node_modules"));'; git ls-files 'build/test' 'src/test/*'
  • ⚠️ Not run | Visual Studio 2026 native rebuild and process-tree smoke test
  • ✅ Passed | Setup, registry, and lockfile tests | npm run test:setup
  • ✅ Passed | Test compilation and lint | npm run compile-tests && npm run lint
  • ✅ Passed | Changed JSON formatting and lockfile normalization | node ./node_modules/prettier/bin/prettier.cjs --check package.json package-lock.json && npm run normalize-lockfile
  • ✅ Passed | Offline dependency preparation | npm ci --offline
  • ✅ Passed | Lock consistency, Node 22 engine compatibility, and nested lifecycle resolution | node <<'NODE'
    const assert = require('node:assert/strict');
    const fs = require('node:fs');
    const path = require('node:path');
    const { spawnSync } = require('node:child_process');
    const semver = require('semver');
    const manifest = require('./package.json');
    const lock = require('./package-lock.json');
    for (const section of ['dependencies', 'devDependencies']) assert.deepEqual(lock.packages[''][section], manifest[section]);
    assert.equal(lock.packages['node_modules/node-gyp'].version, '12.4.0');
    assert.equal(lock.dependencies['node-gyp'].version, '12.4.0');
    const visited = new Set();
    function visit(key) {
    if (visited.has(key)) return;
    visited.add(key);
    const entry = lock.packages[key];
    const installed = JSON.parse(fs.readFileSync(path.join(key, 'package.json'), 'utf8'));
    assert.equal(installed.version, entry.version, key);
    for (const nodeVersion of ['22.17.0', '22.21.1']) if (entry.engines?.node) assert(semver.satisfies(nodeVersion, entry.engines.node), ${key} rejects ${nodeVersion});
    for (const [name, range] of Object.entries(entry.dependencies || {})) {
    let directory = key;
    let dependency;
    for (;;) {
    const candidate = path.posix.join(directory, 'node_modules', name);
    if (lock.packages[candidate]) { dependency = candidate; break; }
    if (!directory) break;
    directory = path.posix.dirname(directory);
    if (directory === '.') directory = '';
    }
    assert(dependency, ${key}: missing ${name});
    assert(semver.satisfies(lock.packages[dependency].version, range), ${dependency}: ${range});
    visit(dependency);
    }
    }
    visit('node_modules/node-gyp');
    console.log(PASS: manifest/lock agree; ${visited.size} installed node-gyp dependency entries satisfy locked ranges and Node 22.17.0/22.21.1 engines.);
    const fixture = fs.mkdtempSync(path.join(process.cwd(), 'node_modules', '.verification-node-gyp-'));
    try {
    fs.writeFileSync(path.join(fixture, 'package.json'), JSON.stringify({ name: 'verification-node-gyp', version: '1.0.0', private: true, scripts: { install: 'node-gyp --version' } }));
    const result = spawnSync('npm', ['--offline', 'run', 'install', '--prefix', fixture], { encoding: 'utf8', timeout: 20000 });
    process.stdout.write(result.stdout || '');
    process.stderr.write(result.stderr || '');
    assert.ifError(result.error);
    assert.equal(result.status, 0);
    assert.match(result.stdout, /^v12.4.0\s*$/m);
    console.log('PASS: nested npm install lifecycle resolves project-local node-gyp 12.4.0. Native Windows compilation was not exercised.');
    } finally { fs.rmSync(fixture, { recursive: true, force: true }); }
    NODE
⚠️ Attach Quick Pick provider extension tests diagnostic output
src/test/unittest/attachQuickPick/provider.unit.test.ts covers loading windows-process-tree through stubs. The extension runner in src/test/runTest.ts downloads VS Code and installs extensions; that execution is unsupported in the offline container. Compilation passed, but these tests were not executed.
❌ Dependency and test discovery diagnostic output
[container exit=128]
profile=generic
Linux
v24.19.0
11.17.0
fatal: not a git repository (or any parent up to mount point /)
node-gyp: MISSING
typescript: MISSING
eslint: MISSING
prettier: MISSING
node_modules exists: false
Selected runtime: container Node v24.19.0. package.json declares these development dependencies. Authorized offline preparation subsequently succeeded with `npm ci --offline`, restoring dependencies; Git metadata remained unavailable. The command's failure came from the absent repository metadata, not changed product code.
⚠️ Visual Studio 2026 native rebuild and process-tree smoke test diagnostic output
The PR's primary validation requires Windows with Visual Studio 2026 to rebuild @vscode/windows-process-tree and exercise its native API. Discovery reported Linux in the generic container, so this platform-specific verification was not attempted.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) added the review-auto:approved Automated review: no blocking findings (approval posted). label Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issue identified by VS Code Team member as probable bug review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants