fix: use native Windows ARM64 binary for Bun >= 1.3.10 (#165)

Bun v1.3.10 ships native Windows ARM64 binaries. Update
getArchitecture() and getAvx2() to be version-aware so that
windows-11-arm runners download bun-windows-aarch64.zip instead of
falling back to bun-windows-x64-baseline.zip. The x64 fallback is
preserved for older versions that lack ARM64 assets.

Closes #164

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dariel Dato-on
2026-02-26 15:21:29 -06:00
committed by GitHub
parent ab8cb4e8f8
commit 0ff83bfc51
6 changed files with 263 additions and 97 deletions
+85 -2
View File
@@ -7,6 +7,9 @@ const MOCK_TAGS = [
{ ref: "refs/tags/bun-v1.0.0" },
{ ref: "refs/tags/bun-v1.0.1" },
{ ref: "refs/tags/bun-v1.1.0" },
{ ref: "refs/tags/bun-v1.3.9" },
{ ref: "refs/tags/bun-v1.3.10" },
{ ref: "refs/tags/bun-v1.4.0" },
{ ref: "refs/tags/canary" },
];
@@ -98,7 +101,7 @@ describe("getDownloadUrl", () => {
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.1.0/bun-linux-x64.zip",
"https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(1);
});
@@ -111,7 +114,7 @@ describe("getDownloadUrl", () => {
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.1.0/bun-linux-x64.zip",
"https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(1);
});
@@ -141,6 +144,86 @@ describe("getDownloadUrl", () => {
});
});
describe("Windows ARM64", () => {
it("should use native aarch64 binary for Bun >= 1.3.10", async () => {
const url = await getDownloadUrl({
version: "1.3.10",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-windows-aarch64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(0);
});
it("should use native aarch64 binary for Bun 1.4.0", async () => {
const url = await getDownloadUrl({
version: "1.4.0",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-windows-aarch64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(0);
});
it("should fall back to x64-baseline for Bun < 1.3.10", async () => {
const url = await getDownloadUrl({
version: "1.1.0",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.1.0/bun-windows-x64-baseline.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(0);
});
it("should fall back to x64-baseline for Bun 1.3.9", async () => {
const url = await getDownloadUrl({
version: "1.3.9",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.9/bun-windows-x64-baseline.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(0);
});
it("should use native aarch64 for dynamic version resolving to >= 1.3.10", async () => {
const url = await getDownloadUrl({
version: "^1.3.0",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-windows-aarch64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(1);
});
it("should use native aarch64 for canary on Windows ARM64", async () => {
const url = await getDownloadUrl({
version: "canary",
os: "windows",
arch: "arm64",
});
expect(url).toBe(
"https://github.com/oven-sh/bun/releases/download/canary/bun-windows-aarch64.zip",
);
expect(requestSpy).toHaveBeenCalledTimes(1);
});
});
describe("Token Handling", () => {
it("should pass token to API request when resolving dynamic versions", async () => {
await getDownloadUrl({
+85 -32
View File
@@ -1,7 +1,32 @@
import { afterEach, describe, expect, it, spyOn } from "bun:test";
import { getArchitecture, getAvx2 } from "../src/utils";
import { getArchitecture, getAvx2, hasNativeWindowsArm64 } from "../src/utils";
import * as core from "@actions/core";
describe("hasNativeWindowsArm64", () => {
it("should return true for version >= 1.3.10", () => {
expect(hasNativeWindowsArm64("bun-v1.3.10")).toBe(true);
expect(hasNativeWindowsArm64("bun-v1.3.11")).toBe(true);
expect(hasNativeWindowsArm64("bun-v1.4.0")).toBe(true);
expect(hasNativeWindowsArm64("bun-v2.0.0")).toBe(true);
});
it("should return false for version < 1.3.10", () => {
expect(hasNativeWindowsArm64("bun-v1.3.9")).toBe(false);
expect(hasNativeWindowsArm64("bun-v1.2.0")).toBe(false);
expect(hasNativeWindowsArm64("bun-v1.0.0")).toBe(false);
expect(hasNativeWindowsArm64("bun-v0.5.0")).toBe(false);
});
it("should return true for non-semver versions like canary", () => {
expect(hasNativeWindowsArm64("canary")).toBe(true);
expect(hasNativeWindowsArm64("latest")).toBe(true);
});
it("should return false for undefined version", () => {
expect(hasNativeWindowsArm64(undefined)).toBe(false);
});
});
describe("getArchitecture", () => {
let warningSpy: ReturnType<typeof spyOn>;
@@ -9,30 +34,54 @@ describe("getArchitecture", () => {
warningSpy?.mockRestore();
});
it("should return x64 for Windows with arm64 architecture", () => {
it("should return aarch64 for Windows arm64 with Bun >= 1.3.10", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "arm64", "bun-v1.3.10");
expect(result).toBe("aarch64");
expect(warningSpy).not.toHaveBeenCalled();
});
it("should return aarch64 for Windows aarch64 with Bun >= 1.3.10", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "aarch64", "bun-v1.4.0");
expect(result).toBe("aarch64");
expect(warningSpy).not.toHaveBeenCalled();
});
it("should return x64 for Windows arm64 with Bun < 1.3.10", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "arm64", "bun-v1.2.0");
expect(result).toBe("x64");
expect(warningSpy).toHaveBeenCalledTimes(1);
expect(warningSpy).toHaveBeenCalledWith(
expect.stringContaining(
"⚠️ This version of Bun does not provide native arm64 builds for Windows."
)
);
});
it("should return x64 for Windows aarch64 with Bun < 1.3.10", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "aarch64", "bun-v1.0.0");
expect(result).toBe("x64");
expect(warningSpy).toHaveBeenCalledTimes(1);
expect(warningSpy).toHaveBeenCalledWith(
expect.stringContaining(
"⚠️ This version of Bun does not provide native arm64 builds for Windows."
)
);
});
it("should return x64 for Windows arm64 with no version (fallback)", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "arm64");
expect(result).toBe("x64");
expect(warningSpy).toHaveBeenCalledTimes(1);
expect(warningSpy).toHaveBeenCalledWith(
expect.stringContaining(
"⚠️ Bun does not provide native arm64 builds for Windows."
)
);
});
it("should return x64 for Windows with aarch64 architecture", () => {
warningSpy = spyOn(core, "warning");
const result = getArchitecture("windows", "aarch64");
expect(result).toBe("x64");
expect(warningSpy).toHaveBeenCalledTimes(1);
expect(warningSpy).toHaveBeenCalledWith(
expect.stringContaining(
"⚠️ Bun does not provide native arm64 builds for Windows."
)
);
});
it("should return aarch64 for non-Windows platforms with arm64", () => {
@@ -77,24 +126,28 @@ describe("getArchitecture", () => {
});
describe("getAvx2", () => {
it("should return false when called with os: 'windows' and arch: 'arm64'", () => {
const result = getAvx2("windows", "arm64");
expect(result).toBe(false);
it("should return false for Windows arm64 with Bun < 1.3.10", () => {
expect(getAvx2("windows", "arm64", undefined, "bun-v1.2.0")).toBe(false);
});
it("should return false when called with os: 'windows' and arch: 'aarch64'", () => {
const result = getAvx2("windows", "aarch64");
expect(result).toBe(false);
it("should return false for Windows aarch64 with Bun < 1.3.10", () => {
expect(getAvx2("windows", "aarch64", undefined, "bun-v1.0.0")).toBe(false);
});
it("should return false when called with os: 'windows', arch: 'arm64', and avx2: true", () => {
const result = getAvx2("windows", "arm64", true);
expect(result).toBe(false);
it("should return false for Windows arm64 with no version (fallback)", () => {
expect(getAvx2("windows", "arm64")).toBe(false);
});
it("should return false when called with os: 'windows', arch: 'aarch64', and avx2: false", () => {
const result = getAvx2("windows", "aarch64", false);
expect(result).toBe(false);
it("should return false for Windows aarch64 with no version (fallback)", () => {
expect(getAvx2("windows", "aarch64")).toBe(false);
});
it("should return true for Windows arm64 with Bun >= 1.3.10", () => {
expect(getAvx2("windows", "arm64", undefined, "bun-v1.3.10")).toBe(true);
});
it("should return true for Windows aarch64 with Bun >= 1.3.10", () => {
expect(getAvx2("windows", "aarch64", undefined, "bun-v1.4.0")).toBe(true);
});
it("should return the provided avx2 value (true) when specified and not on Windows ARM64", () => {