From afdc1caa6c67d6fcaf0cae6bd1bdbc6ef5b2c41f Mon Sep 17 00:00:00 2001 From: Kyle McCleary Date: Tue, 4 Aug 2026 20:10:05 -0700 Subject: [PATCH] fix(ci): align native install smoke metadata --- scripts/install-tests/native-version.test.ts | 13 ++++++ scripts/install-tests/native-version.ts | 22 ++++++++++ scripts/install-tests/run-ci.sh | 42 +++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 scripts/install-tests/native-version.test.ts create mode 100644 scripts/install-tests/native-version.ts diff --git a/scripts/install-tests/native-version.test.ts b/scripts/install-tests/native-version.test.ts new file mode 100644 index 000000000..97718f1cb --- /dev/null +++ b/scripts/install-tests/native-version.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, it } from "bun:test"; +import { nativeVersionFromExports } from "./native-version"; + +describe("native addon release sentinel", () => { + it("normalizes the unique version sentinel", () => { + expect(nativeVersionFromExports(["load", "__piNativesV17_2_6", "other"])).toBe("17.2.6"); + }); + + it("rejects missing or ambiguous sentinels", () => { + expect(nativeVersionFromExports(["load"])).toBeUndefined(); + expect(nativeVersionFromExports(["__piNativesV17_2_6", "__piNativesV17_2_7"])).toBeUndefined(); + }); +}); diff --git a/scripts/install-tests/native-version.ts b/scripts/install-tests/native-version.ts new file mode 100644 index 000000000..d00f8535c --- /dev/null +++ b/scripts/install-tests/native-version.ts @@ -0,0 +1,22 @@ +import { createRequire } from "node:module"; + +const VERSION_SENTINEL_RE = /^__piNativesV(\d+)_(\d+)_(\d+)$/; + +/** Return the sole release version advertised by a native addon's exports. */ +export function nativeVersionFromExports(exports: readonly string[]): string | undefined { + const versions = exports + .map(name => VERSION_SENTINEL_RE.exec(name)) + .filter((match): match is RegExpExecArray => match !== null) + .map(match => `${match[1]}.${match[2]}.${match[3]}`); + return versions.length === 1 ? versions[0] : undefined; +} + +if (import.meta.main) { + const addonPath = process.argv[2]; + if (!addonPath) throw new Error("Usage: bun scripts/install-tests/native-version.ts "); + const require = createRequire(import.meta.url); + const bindings = require(addonPath) as Record; + const version = nativeVersionFromExports(Object.keys(bindings)); + if (!version) throw new Error(`Native addon has no unique release version sentinel: ${addonPath}`); + process.stdout.write(version); +} diff --git a/scripts/install-tests/run-ci.sh b/scripts/install-tests/run-ci.sh index 31ee8eee2..8621d25e5 100755 --- a/scripts/install-tests/run-ci.sh +++ b/scripts/install-tests/run-ci.sh @@ -7,7 +7,15 @@ WORK_DIR="$(mktemp -d)" TMP_WORK_DIR="$WORK_DIR/tmp" mkdir -p "$TMP_WORK_DIR" export TMPDIR="$TMP_WORK_DIR" -trap 'rm -rf "$WORK_DIR"' EXIT + +NATIVES_PACKAGE="$ROOT_DIR/packages/natives/package.json" +NATIVES_PACKAGE_INITIAL="$WORK_DIR/natives-package.initial.json" +cp "$NATIVES_PACKAGE" "$NATIVES_PACKAGE_INITIAL" +restore_workspace() { + cp "$NATIVES_PACKAGE_INITIAL" "$NATIVES_PACKAGE" + rm -rf "$WORK_DIR" +} +trap restore_workspace EXIT section() { echo "" @@ -42,10 +50,42 @@ find_tarball() { echo "${matches[0]}" } +align_native_manifest() { + local addon_version="" + local addon + local candidate_version + local candidates=() + shopt -s nullglob + candidates=("$ROOT_DIR"/packages/natives/native/pi_natives.*.node) + shopt -u nullglob + + if [ "${#candidates[@]}" -eq 0 ]; then + echo "No native addon found for install smoke" >&2 + exit 1 + fi + for addon in "${candidates[@]}"; do + candidate_version="$(bun "$ROOT_DIR/scripts/install-tests/native-version.ts" "$addon")" || exit 1 + if [ -z "$addon_version" ]; then + addon_version="$candidate_version" + elif [ "$addon_version" != "$candidate_version" ]; then + echo "Native addon version mismatch: $addon_version vs $candidate_version ($addon)" >&2 + exit 1 + fi + done + + local declared_version + declared_version="$(jq -r '.version' "$NATIVES_PACKAGE")" + if [ "$declared_version" = "$addon_version" ]; then return; fi + + echo "Aligning install smoke native manifest $declared_version → $addon_version" + jq --arg version "$addon_version" '.version = $version' "$NATIVES_PACKAGE" > "$WORK_DIR/natives-package.aligned.json" + mv "$WORK_DIR/natives-package.aligned.json" "$NATIVES_PACKAGE" +} section "Binary install smoke" if [ "${OMP_INSTALL_TEST_SKIP_NATIVE_BUILD:-0}" != "1" ]; then bun --cwd=packages/natives run build fi +align_native_manifest bun --cwd=packages/coding-agent run build BINARY_DIR="$WORK_DIR/binary-bin"