fix(setup): used portable native install artifacts

- Built the generic Windows release binary with Bun's baseline x64 runtime so older Windows 10 CPUs do not hit the AVX2-only modern executable.

- Forced pi-natives release builds to link PCRE2 statically so macOS installs do not depend on Homebrew's libpcre2 dylib.

- Added release dry-run and native-build regression coverage for the portable artifact contracts.

Fixes #5172
This commit is contained in:
roboomp
2026-07-11 09:09:59 +00:00
parent 6328671d1d
commit bc7a143c1e
10 changed files with 116 additions and 19 deletions
+36
View File
@@ -0,0 +1,36 @@
import { describe, expect, it } from "bun:test";
import * as path from "node:path";
import { $ } from "bun";
const repoRoot = path.join(import.meta.dir, "..");
async function runCiNativeDryRun(env: Record<string, string | undefined> = {}): Promise<string> {
const result = await $`bun scripts/ci-build-native.ts --dry-run`
.cwd(repoRoot)
.quiet()
.env({
...process.env,
PCRE2_SYS_STATIC: "0",
RUSTFLAGS: "",
TARGET_VARIANT: "",
TARGET_VARIANTS: "",
...env,
})
.nothrow();
expect(result.exitCode).toBe(0);
return result.text();
}
describe("ci native build environment", () => {
it("prints static PCRE2 env for the default native build dry run", async () => {
await expect(runCiNativeDryRun()).resolves.toBe(
"DRY RUN bun --cwd=packages/natives run build [default] PCRE2_SYS_STATIC=1\n",
);
});
it("prints static PCRE2 env without dropping x64 variant settings", async () => {
await expect(runCiNativeDryRun({ TARGET_VARIANTS: "baseline" })).resolves.toBe(
'DRY RUN bun --cwd=packages/natives run build [baseline] PCRE2_SYS_STATIC=1 TARGET_VARIANT=baseline RUSTFLAGS="-C target-cpu=x86-64-v2"\n',
);
});
});
+14 -5
View File
@@ -21,6 +21,13 @@ const variantConfigs: Record<NativeBuildVariant["name"], NativeBuildVariant> = {
},
};
/** Adds release-portability env required by native addon builds. */
export function withPortableNativeBuildEnv(
env: Record<string, string | undefined>,
): Record<string, string | undefined> {
return { ...env, PCRE2_SYS_STATIC: "1" };
}
function parseTargetVariants(): NativeBuildVariant[] {
const rawVariants = (Bun.env.TARGET_VARIANTS ?? "").trim();
if (!rawVariants) return [];
@@ -35,15 +42,17 @@ function parseTargetVariants(): NativeBuildVariant[] {
}
async function runNativeBuild(env: Record<string, string | undefined>, label: string): Promise<void> {
const buildEnv = withPortableNativeBuildEnv(env);
if (isDryRun) {
const variant = env.TARGET_VARIANT ? ` TARGET_VARIANT=${env.TARGET_VARIANT}` : "";
const rustflags = env.RUSTFLAGS ? ` RUSTFLAGS=${JSON.stringify(env.RUSTFLAGS)}` : "";
console.log(`DRY RUN bun --cwd=packages/natives run build [${label}]${variant}${rustflags}`);
const staticPcre = ` PCRE2_SYS_STATIC=${buildEnv.PCRE2_SYS_STATIC}`;
const variant = buildEnv.TARGET_VARIANT ? ` TARGET_VARIANT=${buildEnv.TARGET_VARIANT}` : "";
const rustflags = buildEnv.RUSTFLAGS ? ` RUSTFLAGS=${JSON.stringify(buildEnv.RUSTFLAGS)}` : "";
console.log(`DRY RUN bun --cwd=packages/natives run build [${label}]${staticPcre}${variant}${rustflags}`);
return;
}
console.log(`Building natives [${label}]...`);
await $`bun --cwd=packages/natives run build`.cwd(repoRoot).env(env);
await $`bun --cwd=packages/natives run build`.cwd(repoRoot).env(buildEnv);
}
async function main(): Promise<void> {
@@ -65,4 +74,4 @@ async function main(): Promise<void> {
}
}
await main();
if (import.meta.main) await main();
+38
View File
@@ -0,0 +1,38 @@
import { describe, expect, it } from "bun:test";
import * as path from "node:path";
import { $ } from "bun";
import { resolveCrossBuild } from "../packages/coding-agent/scripts/build-binary";
const repoRoot = path.join(import.meta.dir, "..");
describe("Windows release binary target", () => {
it("builds the generic Windows release asset with the baseline runtime", async () => {
const result = await $`bun scripts/ci-release-build-binaries.ts --dry-run --targets win32-x64`
.cwd(repoRoot)
.quiet()
.nothrow();
expect(result.exitCode).toBe(0);
const output = result.text();
expect(output).toContain("Building packages/coding-agent/binaries/omp-windows-x64.exe...");
expect(output).toContain(
"DRY RUN Bun.build target=bun-windows-x64-baseline outfile=packages/coding-agent/binaries/omp-windows-x64.exe",
);
expect(output).not.toContain("bun-windows-x64-modern");
});
it("uses the baseline runtime for local Windows cross-build aliases", () => {
expect(resolveCrossBuild("win32-x64")).toEqual({
id: "win32-x64",
platform: "win32",
arch: "x64",
target: "bun-windows-x64-baseline",
});
expect(resolveCrossBuild("windows-x64")).toEqual({
id: "windows-x64",
platform: "win32",
arch: "x64",
target: "bun-windows-x64-baseline",
});
});
});
+1 -1
View File
@@ -63,7 +63,7 @@ const targets: BinaryTarget[] = [
id: "win32-x64",
platform: "win32",
arch: "x64",
target: "bun-windows-x64-modern",
target: "bun-windows-x64-baseline",
outfile: "packages/coding-agent/binaries/omp-windows-x64.exe",
},
];
+2
View File
@@ -111,6 +111,7 @@ const localOnlyWorkspacePackages = ["packages/mnemopi", "python/robomp/web"];
// silently ignores unmatched filters when at least one other filter matches.)
const repoScriptTests = [
"scripts/ci-concurrency.test.ts",
"scripts/ci-build-native.test.ts",
"scripts/ci-release-notes.test.ts",
"scripts/fix-dts-extensions.test.ts",
"scripts/link-omp.test.ts",
@@ -345,6 +346,7 @@ async function commandsForMode(mode: Mode): Promise<TestCommand[]> {
"--parallel=4",
...onlyFailuresArgs,
"scripts/ci-concurrency.test.ts",
"scripts/ci-build-native.test.ts",
"scripts/fix-dts-extensions.test.ts",
],
},