From 43fb6120a544a5f2ee7f03fddab1c7ba1f6caa05 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 6 Jul 2026 21:25:55 +0200 Subject: [PATCH] fix: opt out of node-gyp on install via gypfile:false Dropping the no-op install script in #363 stopped Yarn Berry's YN0007 warning, but it let npm's publish-time normalization take over: with binding.gyp present in the dev tree (and excluded from the tarball) and no install/preinstall script, npm synthesizes "gypfile": true and "install": "node-gyp rebuild" into the published manifest. Consumers on npm then run node-gyp rebuild against a binding.gyp that isn't in the package and the install fails, which shipped broken in 5.16.0. Setting "gypfile": false suppresses that implicit hook while keeping the manifest free of lifecycle scripts, so both npm and Yarn Berry install the prebuilt binaries without a build step. The regression test now also pins gypfile:false alongside the no-lifecycle-scripts assertion. Fixes: https://github.com/DataDog/pprof-nodejs/pull/364#pullrequestreview-4638668974 --- package.json | 1 + ts/test/test-no-build-scripts.ts | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5d0fbe75..7e6f4f3f 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "main": "out/src/index.js", "types": "out/src/index.d.ts", + "gypfile": false, "scripts": { "build:asan": "node-gyp configure build --jobs=max --address_sanitizer", "build:tsan": "node-gyp configure build --jobs=max --thread_sanitizer", diff --git a/ts/test/test-no-build-scripts.ts b/ts/test/test-no-build-scripts.ts index 4aee2b12..cb7ba35f 100644 --- a/ts/test/test-no-build-scripts.ts +++ b/ts/test/test-no-build-scripts.ts @@ -3,12 +3,23 @@ import * as fs from 'fs'; import * as path from 'path'; describe('package manifest', () => { + const manifest = path.join(__dirname, '..', '..', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(manifest, 'utf8')); + it('declares no npm build lifecycle scripts (Yarn Berry YN0007)', () => { - const manifest = path.join(__dirname, '..', '..', 'package.json'); - const pkg = JSON.parse(fs.readFileSync(manifest, 'utf8')); const scripts = pkg.scripts || {}; const hooks = ['preinstall', 'install', 'postinstall']; const present = hooks.filter(name => scripts[name] !== undefined); assert.deepStrictEqual(present, []); }); + + it('opts out of node-gyp on install via gypfile:false (npm implicit rebuild)', () => { + // binding.gyp lives in the dev tree (excluded from the published tarball). + // Without gypfile:false, npm's publish-time normalization synthesizes + // "gypfile": true and "install": "node-gyp rebuild" into the registry + // manifest, so consumers run node-gyp rebuild against a missing + // binding.gyp and the install fails. Pinning gypfile:false suppresses + // that hook while keeping the manifest free of lifecycle scripts. + assert.strictEqual(pkg.gypfile, false); + }); });