Skip to content

Commit b02f8a8

Browse files
xhyromautofix-ci[bot]CopilotCopilot
authored
feat: fallback arm64 to x64 architecture for win32 platform (#131)
* feat: fallback arm64 to x64 architecture for win32 platform closes #130 * [autofix.ci] apply automated fixes * ci: test on windows-11-arm runner * refactor: move logic to getEffectiveArch func * [autofix.ci] apply automated fixes * feat: add warning message for windows arm64 fallback to x64 * [autofix.ci] apply automated fixes * feat: don't mention arch in warning msg aboout fallback * [autofix.ci] apply automated fixes * debug time * [autofix.ci] apply automated fixes * feat: force baseline for win32 arm fallback to x64 * [autofix.ci] apply automated fixes * ci: dont use windows-11-arm on setup bun from download url * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * apply changes Co-authored-by: Copilot <[email protected]> * [autofix.ci] apply automated fixes * docs: clarify * [autofix.ci] apply automated fixes * test: add unit tests for getAvx2 Windows ARM64 fallback logic (#154) * Initial plan * Add unit tests for getAvx2 function Co-authored-by: xhyrom <[email protected]> * Consolidate duplicate test assertions in getAvx2 tests Co-authored-by: xhyrom <[email protected]> * Fix whitespace formatting in test file Co-authored-by: xhyrom <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: xhyrom <[email protected]> * test: add unit tests for getArchitecture and getAvx2 Windows ARM64 fallback logic (#153) * Initial plan * Add unit tests for getArchitecture function Co-authored-by: xhyrom <[email protected]> * Remove unused import in utils.spec.ts Co-authored-by: xhyrom <[email protected]> * Apply suggestion from @Copilot Co-authored-by: Copilot <[email protected]> * Merge pr-131 and resolve test file conflicts Co-authored-by: xhyrom <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: xhyrom <[email protected]> Co-authored-by: Jozef Steinhübl <[email protected]> Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 8c296f9 commit b02f8a8

File tree

5 files changed

+266
-113
lines changed

5 files changed

+266
-113
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
- ubuntu-latest
5151
- macos-latest
5252
- windows-latest
53+
- windows-11-arm
5354
bun-version:
5455
- latest
5556
- canary
@@ -98,6 +99,7 @@ jobs:
9899
- ubuntu-latest
99100
- macos-latest
100101
- windows-latest
102+
- windows-11-arm
101103

102104
file:
103105
- name: package.json (packageManager [email protected])

dist/setup/index.js

Lines changed: 108 additions & 107 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/download-url.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { compareVersions, satisfies, validate } from "compare-versions";
22
import { Input } from "./action";
3-
import { getArchitecture, getPlatform, request } from "./utils";
3+
import { getArchitecture, getAvx2, getPlatform, request } from "./utils";
44

55
export async function getDownloadUrl(options: Input): Promise<string> {
66
const { customUrl } = options;
@@ -50,8 +50,14 @@ async function getSemverDownloadUrl(options: Input): Promise<string> {
5050

5151
const eversion = encodeURIComponent(tag ?? version);
5252
const eos = encodeURIComponent(os ?? getPlatform());
53-
const earch = encodeURIComponent(arch ?? getArchitecture());
54-
const eavx2 = encodeURIComponent(avx2 === false ? "-baseline" : "");
53+
const earch = encodeURIComponent(
54+
getArchitecture(os ?? getPlatform(), arch ?? process.arch),
55+
);
56+
const eavx2 = encodeURIComponent(
57+
getAvx2(os ?? getPlatform(), arch ?? process.arch, avx2) === false
58+
? "-baseline"
59+
: "",
60+
);
5561
const eprofile = encodeURIComponent(profile === true ? "-profile" : "");
5662

5763
const { href } = new URL(

src/utils.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,33 @@ export function getPlatform(): string {
4242
return platform;
4343
}
4444

45-
export function getArchitecture(): string {
46-
const arch = process.arch;
47-
if (arch === "arm64") return "aarch64";
45+
export function getArchitecture(os: string, arch: string): string {
46+
if (os === "windows" && (arch === "aarch64" || arch === "arm64")) {
47+
warning(
48+
[
49+
"⚠️ Bun does not provide native arm64 builds for Windows.",
50+
"Using x64 baseline build which will run through Microsoft's x64 emulation layer.",
51+
"This may result in reduced performance and potential compatibility issues.",
52+
"💡 For best performance, consider using x64 Windows runners or other platforms with native support.",
53+
].join("\n"),
54+
);
4855

56+
return "x64";
57+
}
58+
59+
if (arch === "arm64") return "aarch64";
4960
return arch;
5061
}
5162

63+
export function getAvx2(os: string, arch: string, avx2?: boolean): boolean {
64+
// Temporary workaround for absence of arm64 builds on Windows (#130)
65+
if (os === "windows" && (arch === "aarch64" || arch === "arm64")) {
66+
return false;
67+
}
68+
69+
return avx2 ?? true;
70+
}
71+
5272
const FILE_VERSION_READERS = {
5373
"package.json": (content: string) => {
5474
const pkg = JSON.parse(content);

tests/utils.spec.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { afterEach, describe, expect, it, spyOn } from "bun:test";
2+
import { getArchitecture, getAvx2 } from "../src/utils";
3+
import * as core from "@actions/core";
4+
5+
describe("getArchitecture", () => {
6+
let warningSpy: ReturnType<typeof spyOn>;
7+
8+
afterEach(() => {
9+
warningSpy?.mockRestore();
10+
});
11+
12+
it("should return x64 for Windows with arm64 architecture", () => {
13+
warningSpy = spyOn(core, "warning");
14+
const result = getArchitecture("windows", "arm64");
15+
16+
expect(result).toBe("x64");
17+
expect(warningSpy).toHaveBeenCalledTimes(1);
18+
expect(warningSpy).toHaveBeenCalledWith(
19+
expect.stringContaining(
20+
"⚠️ Bun does not provide native arm64 builds for Windows."
21+
)
22+
);
23+
});
24+
25+
it("should return x64 for Windows with aarch64 architecture", () => {
26+
warningSpy = spyOn(core, "warning");
27+
const result = getArchitecture("windows", "aarch64");
28+
29+
expect(result).toBe("x64");
30+
expect(warningSpy).toHaveBeenCalledTimes(1);
31+
expect(warningSpy).toHaveBeenCalledWith(
32+
expect.stringContaining(
33+
"⚠️ Bun does not provide native arm64 builds for Windows."
34+
)
35+
);
36+
});
37+
38+
it("should return aarch64 for non-Windows platforms with arm64", () => {
39+
warningSpy = spyOn(core, "warning");
40+
const result = getArchitecture("linux", "arm64");
41+
42+
expect(result).toBe("aarch64");
43+
expect(warningSpy).not.toHaveBeenCalled();
44+
});
45+
46+
it("should return aarch64 for macOS with arm64", () => {
47+
warningSpy = spyOn(core, "warning");
48+
const result = getArchitecture("darwin", "arm64");
49+
50+
expect(result).toBe("aarch64");
51+
expect(warningSpy).not.toHaveBeenCalled();
52+
});
53+
54+
it("should return original arch value for x64", () => {
55+
warningSpy = spyOn(core, "warning");
56+
const result = getArchitecture("windows", "x64");
57+
58+
expect(result).toBe("x64");
59+
expect(warningSpy).not.toHaveBeenCalled();
60+
});
61+
62+
it("should return original arch value for x86", () => {
63+
warningSpy = spyOn(core, "warning");
64+
const result = getArchitecture("linux", "x86");
65+
66+
expect(result).toBe("x86");
67+
expect(warningSpy).not.toHaveBeenCalled();
68+
});
69+
70+
it("should return original arch value for aarch64 on Linux", () => {
71+
warningSpy = spyOn(core, "warning");
72+
const result = getArchitecture("linux", "aarch64");
73+
74+
expect(result).toBe("aarch64");
75+
expect(warningSpy).not.toHaveBeenCalled();
76+
});
77+
});
78+
79+
describe("getAvx2", () => {
80+
it("should return false when called with os: 'windows' and arch: 'arm64'", () => {
81+
const result = getAvx2("windows", "arm64");
82+
expect(result).toBe(false);
83+
});
84+
85+
it("should return false when called with os: 'windows' and arch: 'aarch64'", () => {
86+
const result = getAvx2("windows", "aarch64");
87+
expect(result).toBe(false);
88+
});
89+
90+
it("should return false when called with os: 'windows', arch: 'arm64', and avx2: true", () => {
91+
const result = getAvx2("windows", "arm64", true);
92+
expect(result).toBe(false);
93+
});
94+
95+
it("should return false when called with os: 'windows', arch: 'aarch64', and avx2: false", () => {
96+
const result = getAvx2("windows", "aarch64", false);
97+
expect(result).toBe(false);
98+
});
99+
100+
it("should return the provided avx2 value (true) when specified and not on Windows ARM64", () => {
101+
expect(getAvx2("linux", "x64", true)).toBe(true);
102+
expect(getAvx2("darwin", "x64", true)).toBe(true);
103+
expect(getAvx2("windows", "x64", true)).toBe(true);
104+
});
105+
106+
it("should return the provided avx2 value (false) when specified and not on Windows ARM64", () => {
107+
expect(getAvx2("linux", "x64", false)).toBe(false);
108+
expect(getAvx2("darwin", "x64", false)).toBe(false);
109+
expect(getAvx2("windows", "x64", false)).toBe(false);
110+
});
111+
112+
it("should return true by default when avx2 is not specified and not on Windows ARM64", () => {
113+
// x64 architecture on various platforms
114+
expect(getAvx2("linux", "x64")).toBe(true);
115+
expect(getAvx2("darwin", "x64")).toBe(true);
116+
expect(getAvx2("windows", "x64")).toBe(true);
117+
118+
// ARM architecture on non-Windows platforms
119+
expect(getAvx2("linux", "arm64")).toBe(true);
120+
expect(getAvx2("linux", "aarch64")).toBe(true);
121+
expect(getAvx2("darwin", "arm64")).toBe(true);
122+
expect(getAvx2("darwin", "aarch64")).toBe(true);
123+
});
124+
});

0 commit comments

Comments
 (0)