From ce2e396b3eba5905a137ee4527d548a6fe39abc9 Mon Sep 17 00:00:00 2001 From: whyour Date: Fri, 23 Oct 2026 14:04:42 +0800 Subject: [PATCH] fix: remove legacy SQLite compiler artifacts from migration bundles --- scripts/rebuild-migration-sqlite.cjs | 9 +++++--- test/back/migration-sqlite-armv6.test.cjs | 26 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/scripts/rebuild-migration-sqlite.cjs b/scripts/rebuild-migration-sqlite.cjs index 8be2a8a6..f3ebf947 100644 --- a/scripts/rebuild-migration-sqlite.cjs +++ b/scripts/rebuild-migration-sqlite.cjs @@ -53,9 +53,12 @@ async function rebuildMigrationSqlite(root, { assertArmv6Addon(stdout); if (!lock.equals(await fs.readFile(path.join(root, 'pnpm-lock.yaml')))) throw new Error('Migration SQLite rebuild changed the frozen lockfile'); - // node-pre-gyp copied the addon to lib/binding; compiler objects are not - // needed on the small target device or in the transition download. - await fs.rm(path.join(rebuilt, 'build'), { recursive: true, force: true }); + // node-pre-gyp copies the addon to lib/binding and then renames build to + // build-tmp-napi-v. Both layouts contain compiler objects and an absolute + // node_gyp_bins/python3 link; none belongs in a portable runtime archive. + for (const name of await fs.readdir(rebuilt)) + if (name === 'build' || /^build-tmp-napi-v\d+$/.test(name)) + await fs.rm(path.join(rebuilt, name), { recursive: true, force: true }); console.log('Legacy bridge SQLite rebuilt and verified for ARMv6 hard-float'); return true; } diff --git a/test/back/migration-sqlite-armv6.test.cjs b/test/back/migration-sqlite-armv6.test.cjs index 2f1674fd..a82f1aeb 100644 --- a/test/back/migration-sqlite-armv6.test.cjs +++ b/test/back/migration-sqlite-armv6.test.cjs @@ -62,6 +62,32 @@ test('uses frozen repair even when the legacy image has no optional node-gyp', a assert.equal(await fs.readFile(root + '/pnpm-lock.yaml', 'utf8'), 'fixed legacy lock'); }); +test('removes node-pre-gyp build directories and external compiler links while retaining the runtime addon', async (t) => { + const { root, runtime } = await fixture(t); + const sqlite = path.join(root, 'node_modules/sqlite3'); + const addon = path.join(sqlite, 'lib/binding/napi-v6-linux-arm/node_sqlite3.node'); + await fs.mkdir(path.dirname(addon), { recursive: true }); + await fs.writeFile(addon, 'compiled ARM1176 addon'); + const statics = path.join(root, 'static'); + await fs.mkdir(statics); + const { inventory } = require('../../cli/src/internal/maintenance/platformBundle.cjs'); + for (const name of ['build', 'build-tmp-napi-v3', 'build-tmp-napi-v6']) { + const directory = path.join(sqlite, name, 'node_gyp_bins'); + await fs.mkdir(directory, { recursive: true }); + await fs.symlink('/usr/bin/python3', path.join(directory, 'python3')); + } + await assert.rejects(inventory({ source: root, static: statics }), /Bundle link escapes/); + await rebuildMigrationSqlite(root, { + target, runtime, + repair: async () => {}, + run: async () => ({ stdout: armv6 }), + }); + assert.equal(await fs.readFile(addon, 'utf8'), 'compiled ARM1176 addon'); + for (const name of ['build', 'build-tmp-napi-v3', 'build-tmp-napi-v6']) + await assert.rejects(fs.access(path.join(sqlite, name)), { code: 'ENOENT' }); + await inventory({ source: root, static: statics }); +}); + for (const fault of ['runtime-package', 'headers', 'compiler', 'armv7-output', 'lock-change']) test('fails closed for bridge rebuild fault: ' + fault, async (t) => { const { root, runtime } = await fixture(t);