From c223cd508c24bfc724cff38556df0c419078f6e8 Mon Sep 17 00:00:00 2001 From: BeaCox Date: Sun, 30 Aug 2026 13:45:33 +0800 Subject: [PATCH 1/2] feat: add ARM64 release builds --- .cargo/config.toml | 3 ++ .github/ISSUE_TEMPLATE/bug.yml | 2 + .github/ISSUE_TEMPLATE/compatibility.yml | 2 + .github/workflows/ci.yml | 33 ++++++++++++--- .github/workflows/release.yml | 53 ++++++++++++++++-------- README.md | 10 +++-- docs/open-source-release-plan.md | 2 +- docs/roadmap.md | 11 ++--- docs/update-strategy.md | 13 ++++-- scripts/generate-update-manifest.mjs | 10 +++-- scripts/generate-update-manifest.test.js | 22 ++++++---- 11 files changed, 114 insertions(+), 47 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index ac2b23f..81b00ec 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,5 @@ [target.x86_64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] + +[target.aarch64-pc-windows-msvc] +rustflags = ["-C", "target-feature=+crt-static"] diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 1ccb29a..a791482 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -20,7 +20,9 @@ body: options: - macOS 13 or later - x86_64 Linux + - ARM64 Linux - x86_64 Windows 10/11 + - ARM64 Windows 11 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/compatibility.yml b/.github/ISSUE_TEMPLATE/compatibility.yml index 2e4cb12..c3bef37 100644 --- a/.github/ISSUE_TEMPLATE/compatibility.yml +++ b/.github/ISSUE_TEMPLATE/compatibility.yml @@ -20,7 +20,9 @@ body: options: - macOS 13 or later - x86_64 Linux + - ARM64 Linux - x86_64 Windows 10/11 + - ARM64 Windows 11 validations: required: true - type: input diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c98a39..31ce934 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,18 +66,36 @@ jobs: fail-fast: false matrix: include: - - name: macOS + - name: macOS ARM64 runner: macos-15 - smoke: false - - name: Windows + platform: macos + - name: Linux ARM64 + runner: ubuntu-22.04-arm + platform: linux + - name: Windows x64 runner: windows-2025 - smoke: true + platform: windows + - name: Windows ARM64 + runner: windows-11-vs2026-arm + platform: windows runs-on: ${{ matrix.runner }} timeout-minutes: 30 steps: - uses: actions/checkout@v7 with: persist-credentials: false + - name: Install Linux application dependencies + if: matrix.platform == 'linux' + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + libssl-dev \ + libwebkit2gtk-4.1-dev \ + libxdo-dev \ + xvfb - uses: pnpm/action-setup@v6 with: version: 11.3.0 @@ -88,7 +106,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: - shared-key: ci-${{ runner.os }} + shared-key: ci-${{ runner.os }}-${{ runner.arch }} - run: pnpm install --frozen-lockfile - name: Build frontend assets run: pnpm build @@ -97,6 +115,9 @@ jobs: - name: Build desktop application run: cargo build -p cleanerx-app - name: Smoke-test Windows application - if: matrix.smoke + if: matrix.platform == 'windows' shell: pwsh run: ./scripts/smoke-windows.ps1 -Profile debug + - name: Smoke-test Linux application + if: matrix.platform == 'linux' + run: make smoke-linux LINUX_PROFILE=debug diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e59d735..977b425 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,17 +94,27 @@ jobs: - name: macOS x86_64 os: macos-15-intel platform: macos - arch: x86_64 + arch: x64 target: x86_64-apple-darwin - name: Linux x86_64 os: ubuntu-22.04 platform: linux - arch: x86_64 + arch: x64 + target: "" + - name: Linux arm64 + os: ubuntu-22.04-arm + platform: linux + arch: arm64 target: "" - name: Windows x86_64 os: windows-2025 platform: windows - arch: x86_64 + arch: x64 + target: "" + - name: Windows arm64 + os: windows-11-vs2026-arm + platform: windows + arch: arm64 target: "" runs-on: ${{ matrix.os }} timeout-minutes: 40 @@ -126,6 +136,10 @@ jobs: libxdo-dev \ patchelf \ xvfb + - name: Install GNU Make on Windows ARM64 + if: matrix.platform == 'windows' && matrix.arch == 'arm64' + shell: pwsh + run: choco install make --no-progress -y - uses: pnpm/action-setup@v6 with: version: 11.3.0 @@ -225,18 +239,20 @@ jobs: echo "Expected exactly one macOS app, DMG, updater archive, and updater signature." >&2 exit 1 fi + asset_base="CleanerX-${RELEASE_VERSION}-macos-${RELEASE_ARCH}" ditto -c -k --keepParent "${app_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.zip" + "release-assets/${asset_base}.zip" cp "${dmg_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.dmg" + "release-assets/${asset_base}.dmg" cp "${updater_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.tar.gz" + "release-assets/${asset_base}.tar.gz" cp "${updater_signature_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_macos_${RELEASE_ARCH}_unsigned.app.tar.gz.sig" + "release-assets/${asset_base}.tar.gz.sig" - name: Stage Linux release assets if: matrix.platform == 'linux' env: RELEASE_VERSION: ${{ needs.validate.outputs.version }} + RELEASE_ARCH: ${{ matrix.arch }} run: | set -euo pipefail mkdir release-assets @@ -248,17 +264,19 @@ jobs: echo "Expected exactly one deb, AppImage, and AppImage updater signature." >&2 exit 1 fi + asset_base="CleanerX-${RELEASE_VERSION}-linux-${RELEASE_ARCH}" cp "${deb_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.deb" + "release-assets/${asset_base}.deb" cp "${appimage_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.AppImage" + "release-assets/${asset_base}.AppImage" cp "${appimage_signature_paths[0]}" \ - "release-assets/CleanerX_${RELEASE_VERSION}_linux_x86_64_unsigned.AppImage.sig" + "release-assets/${asset_base}.AppImage.sig" - name: Stage Windows release assets if: matrix.platform == 'windows' shell: pwsh env: RELEASE_VERSION: ${{ needs.validate.outputs.version }} + RELEASE_ARCH: ${{ matrix.arch }} run: | New-Item -ItemType Directory -Path release-assets | Out-Null $msi = @(Get-ChildItem target/release/bundle/msi/*.msi) @@ -267,9 +285,10 @@ jobs: if ($msi.Count -ne 1 -or $nsis.Count -ne 1 -or $nsisSignature.Count -ne 1) { throw "Expected exactly one MSI, NSIS installer, and NSIS updater signature." } - Copy-Item $msi[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned.msi" - Copy-Item $nsis[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned_setup.exe" - Copy-Item $nsisSignature[0].FullName "release-assets/CleanerX_$($env:RELEASE_VERSION)_windows_x86_64_unsigned_setup.exe.sig" + $assetBase = "CleanerX-$($env:RELEASE_VERSION)-windows-$($env:RELEASE_ARCH)" + Copy-Item $msi[0].FullName "release-assets/$assetBase.msi" + Copy-Item $nsis[0].FullName "release-assets/$assetBase.exe" + Copy-Item $nsisSignature[0].FullName "release-assets/$assetBase.exe.sig" - name: Record build metadata shell: bash env: @@ -293,7 +312,7 @@ jobs: echo "cargo=$(cargo --version)" echo "node=$(node --version)" echo "pnpm=$(pnpm --version)" - } > "release-assets/CleanerX_${RELEASE_VERSION}_${RELEASE_PLATFORM}_${RELEASE_ARCH}_build-metadata.txt" + } > "release-assets/CleanerX-${RELEASE_VERSION}-${RELEASE_PLATFORM}-${RELEASE_ARCH}.txt" - uses: actions/upload-artifact@v7 with: name: release-${{ matrix.platform }}-${{ matrix.arch }} @@ -325,7 +344,7 @@ jobs: RELEASE_VERSION: ${{ needs.validate.outputs.version }} run: | set -euo pipefail - tar -czf "release-assets/CleanerX_${RELEASE_VERSION}_source-lockfiles.tar.gz" \ + tar -czf "release-assets/CleanerX-${RELEASE_VERSION}-lockfiles.tar.gz" \ Cargo.lock pnpm-lock.yaml { echo "tag=$GITHUB_REF_NAME" @@ -334,8 +353,8 @@ jobs: echo "published_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)" echo "source=https://github.com/$GITHUB_REPOSITORY/tree/$GITHUB_SHA" echo "workflow=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" - } > "release-assets/CleanerX_${RELEASE_VERSION}_release-metadata.txt" - checksum_file="CleanerX_${RELEASE_VERSION}_SHA256SUMS.txt" + } > "release-assets/CleanerX-${RELEASE_VERSION}-release.txt" + checksum_file="CleanerX-${RELEASE_VERSION}-checksums.txt" rm -f "release-assets/$checksum_file" (cd release-assets && sha256sum * > "$checksum_file") - name: Create draft release diff --git a/README.md b/README.md index a8780f1..6428598 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,8 @@ The detailed routes, gates, limitations, and automated evidence live in the [mut | Platform | Current boundary | Build output | | --- | --- | --- | | macOS 13+ | Apple Silicon and Intel | Unsigned `.app` and DMG | -| Linux x86_64 | WebKitGTK 4.1 desktop environment; CI uses Ubuntu 22.04 | Unsigned `.deb` and AppImage | -| Windows 10/11 x86_64 | WebView2 Runtime; MSVC C runtime is statically linked | Unsigned MSI and NSIS installers | +| Linux x64 / ARM64 | WebKitGTK 4.1 desktop environment; release CI uses native Ubuntu 22.04 runners | Unsigned `.deb` and AppImage | +| Windows 10/11 x64; Windows 11 ARM64 | WebView2 Runtime; MSVC C runtime is statically linked | Unsigned MSI and NSIS installers | [CleanerX v0.1.0](https://github.com/BeaCox/CleanerX/releases/tag/v0.1.0) is the current stable release within the published compatibility matrix. Its macOS, Linux, and Windows artifacts are explicitly unsigned and not notarized; verify manually downloaded files against the release's SHA-256 checksums. See the [release policy](docs/open-source-release-plan.md) for the gates that separate source availability, mutation safety, and publisher identity. @@ -135,11 +135,13 @@ make check | --- | --- | | `make app` | macOS: unsigned `.app` | | `make bundles` | macOS: unsigned `.app` and DMG | -| `make linux` | Linux x86_64: unsigned `.deb` and AppImage | -| `make windows` | Windows x86_64 Developer PowerShell: unsigned MSI and NSIS installers | +| `make linux` | Native Linux architecture: unsigned `.deb` and AppImage | +| `make windows` | Native Windows Developer PowerShell: unsigned MSI and NSIS installers | Use `TARGET=` with bundle commands when selecting an explicit architecture. Native packages are written beneath `target/release/bundle/`. +Tagged release assets use the predictable form `CleanerX-{version}-{os}-{arch}.{ext}`, for example `CleanerX-0.2.0-linux-arm64.AppImage` and `CleanerX-0.2.0-windows-x64.exe`. The release warning, not a filename suffix, records that current builds are unsigned. + Unsigned builds may trigger Gatekeeper or SmartScreen. Verify that the binary came from the expected commit before approving it. Do not disable platform protections globally or trust a checksum as proof of publisher identity. ## Use CleanerX diff --git a/docs/open-source-release-plan.md b/docs/open-source-release-plan.md index 16aea76..d317147 100644 --- a/docs/open-source-release-plan.md +++ b/docs/open-source-release-plan.md @@ -77,7 +77,7 @@ An artifact is released from its exact tested tag. An earlier build is never pro - The public key is pinned in `src-tauri/tauri.conf.json`. Release automation reads the private key only from the `TAURI_SIGNING_PRIVATE_KEY` GitHub Actions secret, while the maintainer keeps a recovery copy in the native credential store. It must never be committed, logged, or copied into a release artifact. - Losing or rotating the private key without a signed transition strands installed builds on their pinned key. Key rotation therefore requires a release signed by the old key that embeds the new trust path before subsequent releases use the new key. - The release job fails if any platform artifact or `.sig` file is absent. It creates `latest.json` only after all architecture-specific artifacts have been collected, and checksums include the manifest, signatures, and updater payloads. -- macOS arm64/x86_64, Windows x86_64 NSIS, and Linux x86_64 AppImage are the in-app update targets. MSI, `.deb`, DMG, and application ZIP artifacts remain manual distribution formats. +- macOS arm64/x86_64, Windows arm64/x86_64 NSIS, and Linux arm64/x86_64 AppImage are the in-app update targets. MSI, `.deb`, DMG, and application ZIP artifacts remain manual distribution formats. ## Pilot and defect policy diff --git a/docs/roadmap.md b/docs/roadmap.md index 4ce2f70..c957949 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -26,12 +26,12 @@ CleanerX currently has: - encrypted `.cxb` backup/restore primitives, path guards, and an operation journal; - optional, off-by-default cleanup backups with an explicit irreversible-deletion warning; - macOS Apple Silicon and Intel `.app`/DMG builds; -- unsigned x86_64 Linux `.deb` and AppImage builds on Ubuntu 22.04, with a native Xvfb launch smoke test and an isolated Secret Service backup/restore round trip; -- unsigned x86_64 Windows MSI and NSIS builds, with a native launch smoke test and an isolated Credential Manager backup/restore round trip; +- release automation for unsigned x64 and ARM64 Linux `.deb` and AppImage builds on native Ubuntu 22.04 runners, with Xvfb launch smoke tests and an isolated x64 Secret Service backup/restore round trip; the published `v0.1.0` assets remain x64-only; +- release automation for unsigned x64 and ARM64 Windows MSI and NSIS builds on native runners, with launch smoke tests and an isolated x64 Credential Manager backup/restore round trip; the published `v0.1.0` assets remain x64-only; - Windows application-data and package-manager launcher discovery, stdio-only Codex control transport, writer-process recognition, write-through atomic replacement, volume/file identity checks, owner validation, and junction/reparse-point rejection; -- reusable product CI with the complete Linux quality gate, cross-platform Rust tests, and native Linux/Windows launch smoke tests; +- reusable product CI with the complete Linux x64 quality gate, cross-platform Rust tests, and native x64/ARM64 Linux/Windows launch smoke tests; - a published, explicitly unsigned and non-notarized [`v0.1.0`](https://github.com/BeaCox/CleanerX/releases/tag/v0.1.0) stable release with macOS, Linux, and Windows assets, updater signatures, build metadata, committed lockfiles, and SHA-256 checksums; and -- one SemVer tag workflow that reruns product CI, validates synchronized versions and `main` ancestry, builds every supported platform, and stages a GitHub Release for maintainer approval. +- one SemVer tag workflow that reruns product CI, validates synchronized versions and `main` ancestry, builds every supported platform/architecture, and stages consistently named `CleanerX-{version}-{os}-{arch}.{ext}` assets for maintainer approval. This is a bounded stable release, not a promise that every Agent version, storage revision, native environment, or crash boundary has production-grade coverage. @@ -107,9 +107,10 @@ Priority: maintain the published unsigned `v0.1.0` release and close the outstan - Add Tauri smoke tests for launch, scan, read-only degradation, detail loading, review dialog, backup listing, and settings persistence on macOS 13+. - Launch each architecture artifact on a clean supported environment and run an isolated mutation/backup/restore cycle with disposable Agent data. +- Record the first tagged native Linux ARM64 and Windows ARM64 package/install/update evidence; workflow support alone does not retroactively widen the published `v0.1.0` boundary. - Confirm bundles contain no development URLs, private source-map paths, local preferences, test data, journals, or backup identities. - Verify accessibility: keyboard-only navigation, focus order, contrast, system Chinese/English switching, dark mode, and reduced motion. -- Document reproducible local commands for both architectures and the supported Finder/System Settings opening path. Never instruct users to disable Gatekeeper globally or run broad quarantine-removal commands. +- Document reproducible local commands for each architecture and the supported Finder/System Settings opening path. Never instruct users to disable Gatekeeper globally or run broad quarantine-removal commands. - Verify the manual signed updater on every supported updater package after draft artifacts exist: no startup/background request, invalid signatures fail closed, stable feeds exclude prereleases, and installation still requires two explicit user actions. ### Remaining pilot and compatibility evidence diff --git a/docs/update-strategy.md b/docs/update-strategy.md index 4ca2367..0a5f27e 100644 --- a/docs/update-strategy.md +++ b/docs/update-strategy.md @@ -2,7 +2,7 @@ Status: implemented for tagged desktop releases -Last reviewed: 2026-08-28 +Last reviewed: 2026-08-30 ## Research summary @@ -17,6 +17,9 @@ GitButler adds a configurable periodic check interval and stable/nightly channel Primary references: - [Tauri v2 updater documentation](https://v2.tauri.app/plugin/updater/) +- [Tauri ARM AppImage guidance](https://v2.tauri.app/distribute/appimage/#appimages-for-arm-based-devices) +- [Tauri Windows ARM64 installer guidance](https://v2.tauri.app/distribute/windows-installer/#building) +- [GitHub-hosted ARM64 runner labels](https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories) and [Windows ARM64 image inventory](https://github.com/actions/runner-images/blob/main/images/windows/Windows11-VS2026-Arm64-Readme.md) - [`tauri-apps/tauri-action` updater manifest support](https://github.com/tauri-apps/tauri-action) - [Entracte updater command](https://github.com/drmowinckels/entracte/blob/main/src-tauri/src/updater.rs) and [configuration](https://github.com/drmowinckels/entracte/blob/main/src-tauri/tauri.conf.json) - [Atuin Desktop endpoint selection](https://github.com/atuinsh/desktop/blob/main/backend/src/commands/updates.rs) and [update UI](https://github.com/atuinsh/desktop/blob/main/src/routes/root/UpdateNotifier.tsx) @@ -37,15 +40,19 @@ The fixed stable endpoint intentionally excludes GitHub prereleases. A future be | --- | --- | --- | --- | | macOS arm64 | `.app.tar.gz` | DMG, application ZIP | Tauri replaces the installed application bundle; the DMG remains a manual installer. | | macOS x86_64 | `.app.tar.gz` | DMG, application ZIP | Separate static-feed target preserves architecture matching. | +| Windows arm64 | NSIS `.exe` | MSI | The application is native ARM64; Tauri documents that the NSIS installer shell itself runs through Windows emulation. | | Windows x86_64 | NSIS `.exe` | MSI | One static target cannot select both installer families; CleanerX standardizes the updater on NSIS. | +| Linux arm64 | AppImage | `.deb` | ARM AppImages require a native ARM host, so release CI uses GitHub's Ubuntu 22.04 ARM64 runner. | | Linux x86_64 | AppImage | `.deb` | A static feed has one `linux-x86_64` entry and cannot distinguish AppImage from `.deb`; non-AppImage runs do not contact the feed. | ## Release construction -Normal developer bundle commands remain unsigned and do not require the updater private key. Tagged releases add `src-tauri/tauri.updater.conf.json`, set `TAURI_SIGNING_PRIVATE_KEY` from GitHub Actions secrets, and ask Tauri to create update artifacts and `.sig` files. The release-draft job gathers every architecture, runs `scripts/generate-update-manifest.mjs`, and fails closed on a missing/empty signature before staging `latest.json` and checksums in a draft GitHub Release. A maintainer verifies the complete draft before publishing it. +Normal developer bundle commands remain unsigned and do not require the updater private key. Tagged releases add `src-tauri/tauri.updater.conf.json`, set `TAURI_SIGNING_PRIVATE_KEY` from GitHub Actions secrets, and ask Tauri to create update artifacts and `.sig` files. Linux and Windows packages are built and smoke-tested on native x64 and ARM64 GitHub runners; ARM AppImage packaging is intentionally not cross-compiled, and Windows ARM64 uses the image with Visual Studio ARM64 C++ tools. Regular product CI also builds and launch-smoke-tests the two new ARM64 targets before a tag can reach the release matrix. The release-draft job gathers every architecture, runs `scripts/generate-update-manifest.mjs`, and fails closed on a missing/empty signature before staging `latest.json` and checksums in a draft GitHub Release. A maintainer verifies the complete draft before publishing it. + +Release filenames follow `CleanerX-{version}-{os}-{arch}.{ext}`. User-facing architecture labels are `x64` and `arm64`, while `latest.json` retains Tauri's required `x86_64` and `aarch64` target keys. [Tauri normally skips Finder cosmetic metadata when it detects `CI=true`](https://github.com/tauri-apps/tauri/blob/tauri-cli-v2.11.4/crates/tauri-bundler/src/bundle/macos/dmg/mod.rs#L160-L168), which would silently reduce a configured DMG to Finder's default icon view. The macOS release jobs explicitly set Tauri's supported `TAURI_BUNDLER_DMG_IGNORE_CI=true` override, then mount each completed DMG read-only and require the tracked field-manual background, a non-empty `.DS_Store` selecting that background and the configured window size, the application bundle, and the exact `/Applications` link. A missing or stale layout fails the release before assets are staged. WiX/MSI does not accept alphanumeric Semantic Versioning prerelease identifiers. The Windows release job therefore uses `scripts/generate-windows-release-config.mjs` to derive a numeric MSI-only version that sorts below the eventual stable version (`0.1.0-alpha.1` becomes `0.0.65535.10001`). The application, tag, updater manifest, NSIS installer, and release asset names retain the public Semantic Versioning value. Unsupported prerelease shapes fail during tag validation before platform builds begin. -Tauri's signature establishes continuity with the public key embedded in an installed CleanerX build. It does not establish operating-system publisher identity. Artifact names and release warnings therefore continue to say that current binaries are unsigned and not notarized. +Tauri's signature establishes continuity with the public key embedded in an installed CleanerX build. It does not establish operating-system publisher identity. The release warning and documentation continue to say that current binaries are unsigned and not notarized; filenames stay short and machine-predictable. diff --git a/scripts/generate-update-manifest.mjs b/scripts/generate-update-manifest.mjs index d65155e..6e517be 100644 --- a/scripts/generate-update-manifest.mjs +++ b/scripts/generate-update-manifest.mjs @@ -3,10 +3,12 @@ import path from "node:path"; import { pathToFileURL } from "node:url"; const targets = [ - ["darwin-aarch64", (version) => `CleanerX_${version}_macos_arm64_unsigned.app.tar.gz`], - ["darwin-x86_64", (version) => `CleanerX_${version}_macos_x86_64_unsigned.app.tar.gz`], - ["linux-x86_64", (version) => `CleanerX_${version}_linux_x86_64_unsigned.AppImage`], - ["windows-x86_64", (version) => `CleanerX_${version}_windows_x86_64_unsigned_setup.exe`], + ["darwin-aarch64", (version) => `CleanerX-${version}-macos-arm64.tar.gz`], + ["darwin-x86_64", (version) => `CleanerX-${version}-macos-x64.tar.gz`], + ["linux-aarch64", (version) => `CleanerX-${version}-linux-arm64.AppImage`], + ["linux-x86_64", (version) => `CleanerX-${version}-linux-x64.AppImage`], + ["windows-aarch64", (version) => `CleanerX-${version}-windows-arm64.exe`], + ["windows-x86_64", (version) => `CleanerX-${version}-windows-x64.exe`], ]; export function buildUpdateManifest({ assetsDirectory, version, repository, tag, publishedAt }) { diff --git a/scripts/generate-update-manifest.test.js b/scripts/generate-update-manifest.test.js index dd0361d..6b81f4a 100644 --- a/scripts/generate-update-manifest.test.js +++ b/scripts/generate-update-manifest.test.js @@ -16,10 +16,12 @@ function updaterAssets(version = "1.2.3") { const directory = fs.mkdtempSync(path.join(os.tmpdir(), "cleanerx-updater-manifest-")); temporaryDirectories.push(directory); const names = [ - `CleanerX_${version}_macos_arm64_unsigned.app.tar.gz`, - `CleanerX_${version}_macos_x86_64_unsigned.app.tar.gz`, - `CleanerX_${version}_linux_x86_64_unsigned.AppImage`, - `CleanerX_${version}_windows_x86_64_unsigned_setup.exe`, + `CleanerX-${version}-macos-arm64.tar.gz`, + `CleanerX-${version}-macos-x64.tar.gz`, + `CleanerX-${version}-linux-arm64.AppImage`, + `CleanerX-${version}-linux-x64.AppImage`, + `CleanerX-${version}-windows-arm64.exe`, + `CleanerX-${version}-windows-x64.exe`, ]; names.forEach((name, index) => { fs.writeFileSync(path.join(directory, name), `artifact-${index}`); @@ -41,18 +43,24 @@ describe("update manifest generation", () => { expect(Object.keys(manifest.platforms)).toEqual([ "darwin-aarch64", "darwin-x86_64", + "linux-aarch64", "linux-x86_64", + "windows-aarch64", "windows-x86_64", ]); + expect(manifest.platforms["linux-aarch64"]).toEqual({ + signature: "signature-2", + url: "https://github.com/BeaCox/CleanerX/releases/download/v1.2.3/CleanerX-1.2.3-linux-arm64.AppImage", + }); expect(manifest.platforms["windows-x86_64"]).toEqual({ - signature: "signature-3", - url: "https://github.com/BeaCox/CleanerX/releases/download/v1.2.3/CleanerX_1.2.3_windows_x86_64_unsigned_setup.exe", + signature: "signature-5", + url: "https://github.com/BeaCox/CleanerX/releases/download/v1.2.3/CleanerX-1.2.3-windows-x64.exe", }); }); it("fails closed when an artifact signature is missing", () => { const directory = updaterAssets(); - fs.rmSync(path.join(directory, "CleanerX_1.2.3_linux_x86_64_unsigned.AppImage.sig")); + fs.rmSync(path.join(directory, "CleanerX-1.2.3-linux-x64.AppImage.sig")); expect(() => buildUpdateManifest({ assetsDirectory: directory, From eef64c1e87677fdc46e16b653b8bbbb9e845fc6d Mon Sep 17 00:00:00 2001 From: BeaCox Date: Sun, 30 Aug 2026 16:34:55 +0800 Subject: [PATCH 2/2] fix: preserve required CI check names --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31ce934..4e32aa9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,13 +66,13 @@ jobs: fail-fast: false matrix: include: - - name: macOS ARM64 + - name: macOS runner: macos-15 platform: macos - name: Linux ARM64 runner: ubuntu-22.04-arm platform: linux - - name: Windows x64 + - name: Windows runner: windows-2025 platform: windows - name: Windows ARM64