diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 742b874..7ac2569 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -105,6 +105,12 @@ jobs: - name: Install dependencies (skip build — we have prebuilts) run: npm install --ignore-scripts + - name: Restore bundled CLI permissions + run: chmod 755 prebuilds/linux-x64/doltlite prebuilds/darwin-arm64/doltlite + + - name: Smoke test npm archive + run: node scripts/test-package.js + - name: Verify npm publish identity run: | npm config get registry diff --git a/scripts/build-amalgamation.js b/scripts/build-amalgamation.js index 9cca418..b8fc66a 100644 --- a/scripts/build-amalgamation.js +++ b/scripts/build-amalgamation.js @@ -32,6 +32,22 @@ console.log("Preparing released doltlite amalgamation...") fs.mkdirSync(outDir, { recursive: true }) let amalgamation = fs.readFileSync(inC, "utf8") +const lockPathVla = ' char zLock[nDir + (nPath - nDir) + sizeof(".-lock") + 1];' +if (amalgamation.includes(lockPathVla)) { + amalgamation = `/* DOLTLITE_NODE_MSVC_LOCK_PATH_FALLBACK */ +#ifdef _MSC_VER +# include +#endif + +${amalgamation.replace(lockPathVla, [ + "#ifdef _MSC_VER", + ' char *zLock = (char*)_alloca(nPath + sizeof(".-lock"));', + "#else", + lockPathVla, + "#endif", + ].join("\n"))}` +} + // DoltLite releases before v0.11.37 emitted the Winsock 2 headers after // SQLite's Windows VFS had already included windows.h. Keep those releases // buildable while newer release amalgamations carry the ordering fix directly. diff --git a/scripts/test-package.js b/scripts/test-package.js new file mode 100644 index 0000000..09c3de1 --- /dev/null +++ b/scripts/test-package.js @@ -0,0 +1,37 @@ +"use strict" + +const assert = require("node:assert/strict") +const fs = require("node:fs") +const os = require("node:os") +const path = require("node:path") +const { execFileSync } = require("node:child_process") + +const root = path.resolve(__dirname, "..") +const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "doltlite-package-")) + +try { + const packed = JSON.parse(execFileSync("npm", [ + "pack", "--ignore-scripts", "--json", "--pack-destination", tmp, + ], { cwd: root, encoding: "utf8" })) + execFileSync("tar", ["xzf", path.join(tmp, packed[0].filename), "-C", tmp]) + const packageRoot = path.join(tmp, "package") + for (const platform of ["linux-x64", "darwin-arm64"]) { + const cli = path.join(packageRoot, "prebuilds", platform, "doltlite") + assert.notEqual(fs.statSync(cli).mode & 0o111, 0, `${platform} CLI is not executable`) + } + const { DatabaseSync, binPath } = require(packageRoot) + const db = new DatabaseSync(":memory:") + try { + assert.equal(db.prepare("SELECT doltlite_engine() AS engine").get().engine, "prolly") + db.exec("CREATE TABLE t(id INTEGER PRIMARY KEY); INSERT INTO t VALUES(1)") + assert.equal(db.prepare("SELECT count(*) AS n FROM t").get().n, 1) + } finally { + db.close() + } + assert.equal(execFileSync(binPath(), [":memory:", "SELECT doltlite_engine();"], { + encoding: "utf8", + }).trim(), "prolly") + console.log("npm archive: native addon and executable bundled CLIs PASS") +} finally { + fs.rmSync(tmp, { recursive: true, force: true }) +} diff --git a/test/amalgamation.test.ts b/test/amalgamation.test.ts index 79b2caa..1c01a70 100644 --- a/test/amalgamation.test.ts +++ b/test/amalgamation.test.ts @@ -27,14 +27,15 @@ describe("released amalgamation preparation", () => { expect(winsock).toBeLessThan(windows) }) - test("uses an unmodified fixed release amalgamation", () => { + test("preserves release source outside compiler compatibility fixes", () => { const source = readFileSync(sourcePath, "utf8") const output = readFileSync(outputPath, "utf8") + const vla = ' char zLock[nDir + (nPath - nDir) + sizeof(".-lock") + 1];' + const restored = output + .replace(/^\/\* DOLTLITE_NODE_WINSOCK2_EARLY_FALLBACK \*\/\n#ifdef _WIN32\n# include \n# include \n#endif\n\n/, "") + .replace(/^\/\* DOLTLITE_NODE_MSVC_LOCK_PATH_FALLBACK \*\/\n#ifdef _MSC_VER\n# include \n#endif\n\n/, "") + .replace(`#ifdef _MSC_VER\n char *zLock = (char*)_alloca(nPath + sizeof(".-lock"));\n#else\n${vla}\n#endif`, vla) - if (source.includes("DOLTLITE_AMALGAMATION_WINSOCK2_EARLY")) { - expect(output).toBe(source) - } else { - expect(output).toContain("DOLTLITE_NODE_WINSOCK2_EARLY_FALLBACK") - } + expect(restored).toBe(source) }) })