From 620c9503b4da77e575095be430f4bfd550bd7a6f Mon Sep 17 00:00:00 2001 From: thesiti92 Date: Mon, 28 Sep 2026 22:48:07 -0400 Subject: [PATCH 1/2] Add Linux ARM64 release builds AI-assisted with Codex. --- .github/workflows/release.yml | 4 +++- README.md | 2 +- scripts/release.py | 13 +++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e1c071494..1e05d1400 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,6 +26,8 @@ jobs: os: macos-15-intel - target: x86_64-unknown-linux-gnu os: ubuntu-22.04 + - target: aarch64-unknown-linux-gnu + os: ubuntu-24.04-arm runs-on: ${{ matrix.os }} timeout-minutes: 45 steps: @@ -83,7 +85,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-14, macos-15-intel, ubuntu-22.04] + os: [macos-14, macos-15-intel, ubuntu-22.04, ubuntu-24.04-arm] runs-on: ${{ matrix.os }} timeout-minutes: 15 env: diff --git a/README.md b/README.md index 3885554d2..0c73fb4b7 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ diffr main...HEAD -- src/ # merge-base comparison ## Installation -CLI and terminal UI (Apple Silicon macOS, Intel macOS, and x64 Linux): +CLI and terminal UI (Apple Silicon macOS, Intel macOS, and x64/ARM64 Linux): ```sh brew install devdotfast/tap/diffr diff --git a/scripts/release.py b/scripts/release.py index 3d8848b37..f7797c9b0 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -6,7 +6,7 @@ import subprocess import tarfile -TARGETS = ("aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu") +TARGETS = ("aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu") ROOT = Path(__file__).resolve().parent.parent @@ -52,9 +52,14 @@ def formula(version, output): end on_linux do - depends_on arch: :x86_64 - url "{url}-x86_64-unknown-linux-gnu.tar.gz" - sha256 "{checksums['x86_64-unknown-linux-gnu']}" + on_arm do + url "{url}-aarch64-unknown-linux-gnu.tar.gz" + sha256 "{checksums['aarch64-unknown-linux-gnu']}" + end + on_intel do + url "{url}-x86_64-unknown-linux-gnu.tar.gz" + sha256 "{checksums['x86_64-unknown-linux-gnu']}" + end end def install From 1c20678cc013b4552a41953a55f652cb281bf3a5 Mon Sep 17 00:00:00 2001 From: thesiti92 Date: Mon, 28 Sep 2026 22:58:03 -0400 Subject: [PATCH 2/2] Support ARM64 fetching and build on Ubuntu 22.04 AI-assisted with Codex. --- .github/workflows/release.yml | 4 ++-- diffr-ts/README.md | 3 +++ diffr-ts/bin/fetch.mjs | 2 +- diffr-ts/scripts/pin.mjs | 2 +- diffr-ts/src/fetch.test.ts | 23 ++++++++++++++++++++--- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e05d1400..03b6a44e1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: - target: x86_64-unknown-linux-gnu os: ubuntu-22.04 - target: aarch64-unknown-linux-gnu - os: ubuntu-24.04-arm + os: ubuntu-22.04-arm runs-on: ${{ matrix.os }} timeout-minutes: 45 steps: @@ -85,7 +85,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-14, macos-15-intel, ubuntu-22.04, ubuntu-24.04-arm] + os: [macos-14, macos-15-intel, ubuntu-22.04, ubuntu-22.04-arm] runs-on: ${{ matrix.os }} timeout-minutes: 15 env: diff --git a/diffr-ts/README.md b/diffr-ts/README.md index 66790ef35..cab8281ce 100644 --- a/diffr-ts/README.md +++ b/diffr-ts/README.md @@ -29,6 +29,9 @@ Keep these files in sync: ## Release +Linux ARM64 fetch support requires a release containing an `aarch64-unknown-linux-gnu` +archive and regenerated pins; the bundled 0.1.4 pins do not include it. + After tagging the matching Rust release and building with `cargo build --locked`, run from `diffr-ts`: diff --git a/diffr-ts/bin/fetch.mjs b/diffr-ts/bin/fetch.mjs index e579b4241..fbd9af2e3 100755 --- a/diffr-ts/bin/fetch.mjs +++ b/diffr-ts/bin/fetch.mjs @@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); -const targets = { "darwin-arm64": "aarch64-apple-darwin", "darwin-x64": "x86_64-apple-darwin", "linux-x64": "x86_64-unknown-linux-gnu" }; +const targets = { "darwin-arm64": "aarch64-apple-darwin", "darwin-x64": "x86_64-apple-darwin", "linux-x64": "x86_64-unknown-linux-gnu", "linux-arm64": "aarch64-unknown-linux-gnu" }; try { await main(); diff --git a/diffr-ts/scripts/pin.mjs b/diffr-ts/scripts/pin.mjs index 423770def..84f98de43 100755 --- a/diffr-ts/scripts/pin.mjs +++ b/diffr-ts/scripts/pin.mjs @@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url"; const here = dirname(fileURLToPath(import.meta.url)); const root = join(here, ".."); const version = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version; -const targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; +const targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]; const sha256 = {}; for (const target of targets) { const url = `https://github.com/devdotfast/diffr/releases/download/${version}/diffr-${version}-${target}.tar.gz`; diff --git a/diffr-ts/src/fetch.test.ts b/diffr-ts/src/fetch.test.ts index 3ba87f302..ca81f16d8 100644 --- a/diffr-ts/src/fetch.test.ts +++ b/diffr-ts/src/fetch.test.ts @@ -6,14 +6,15 @@ import { join } from "node:path"; const fetchScript = join(import.meta.dir, "..", "bin", "fetch.mjs"); const { version } = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf8")); -const targets: Record = { "darwin-arm64": "aarch64-apple-darwin", "darwin-x64": "x86_64-apple-darwin", "linux-x64": "x86_64-unknown-linux-gnu" }; +const targets: Record = { "darwin-arm64": "aarch64-apple-darwin", "darwin-x64": "x86_64-apple-darwin", "linux-x64": "x86_64-unknown-linux-gnu", "linux-arm64": "aarch64-unknown-linux-gnu" }; const target = targets[`${process.platform}-${process.arch}`]; const dirs: string[] = []; afterEach(() => { for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true }); }); -function fixture(entry = "diffr") { +function fixture(entry = "diffr", platform = process.platform, arch = process.arch) { + const target = targets[`${platform}-${arch}`]; if (!target) throw new Error("Fetch tests require a supported release platform"); const dir = mkdtempSync(join(tmpdir(), "diffr-fetch-test-")); dirs.push(dir); @@ -25,9 +26,11 @@ function fixture(entry = "diffr") { const pins = join(dir, "pins.json"); writeFileSync(pins, JSON.stringify({ version, sha256: { [target]: hash } })); const mock = join(dir, "mock.mjs"); - // Intercept only the network boundary, leaving the actual CLI and tar intact. + // Mock the platform and network, leaving the actual CLI and tar intact. writeFileSync(mock, ` import { readFileSync, writeFileSync } from "node:fs"; + Object.defineProperty(process, "platform", { value: ${JSON.stringify(platform)} }); + Object.defineProperty(process, "arch", { value: ${JSON.stringify(arch)} }); globalThis.fetch = async (url) => { writeFileSync(${JSON.stringify(join(dir, "requested"))}, url); if (process.env.FETCH_FAILURE) throw new Error("offline"); @@ -119,3 +122,17 @@ test("missing option values fail clearly", () => { expect(f.run(["--pins"]).code).toBe(1); expect(f.run(["--into"]).code).toBe(1); }); + +test("Linux ARM64 downloads and stamps the aarch64 release", () => { + const f = fixture("diffr", "linux", "arm64"); + const result = f.run(["--required"]); + expect(result.code, result.err).toBe(0); + expect(readFileSync(join(f.dir, "requested"), "utf8")).toBe( + `https://github.com/devdotfast/diffr/releases/download/${version}/diffr-${version}-aarch64-unknown-linux-gnu.tar.gz`, + ); + expect(readFileSync(join(f.into, "diffr"), "utf8")).toBe(f.content); + expect(JSON.parse(readFileSync(join(f.into, "diffr.stamp.json"), "utf8"))).toEqual({ + version, target: "aarch64-unknown-linux-gnu", + }); + expect(f.run(["--check"], true).code).toBe(0); +});