Compare commits

...

12 Commits

Author SHA1 Message Date
LukeParkerDev
b8d2a6ec41 ci: move arm64 tauri test to windows-2025
Use GitHub-hosted Windows for the temporary Tauri ARM64 test job because the Blacksmith Windows Build Tools image does not expose the ARM64 MSVC linker/libs we need. The hosted Windows images already include LLVM and VC.Tools.ARM64, so we can drop the custom installer and linker hacks.
2026-03-09 16:28:28 +10:00
LukeParkerDev
00787c1641 ci: avoid pwsh host variable clash
Rename the temporary ARM64 linker-path local so the PowerShell step stops colliding with the built-in read-only  variable before it rewrites LIB and the target linker.
2026-03-09 16:21:57 +10:00
LukeParkerDev
eae68e8ed2 ci: force arm64 linker in test workflow
Pin the Windows ARM64 test build to the HostX64 ARM64 linker and overwrite LIB with only ARM64 SDK and MSVC paths so Tauri stops resolving x64 runtimes during cross-link.
2026-03-09 16:16:00 +10:00
LukeParkerDev
520483ea15 ci: quote arm64 tool install path
Invoke the Visual Studio installer directly so the Build Tools install path with spaces stays intact. The previous Start-Process call split the path and caused setup.exe to target  instead of the actual VS instance.
2026-03-09 16:02:41 +10:00
LukeParkerDev
1e49c5b1a5 ci: use setup.exe for arm64 tool install
Use the documented Visual Studio installer entrypoint for modify operations and remove the unsupported wait flag that was returning exit code 87 on the Blacksmith Windows runner.
2026-03-09 15:55:52 +10:00
LukeParkerDev
ed9cd9dd2f ci: set arm64 msvc env in test workflow
Install the Visual Studio ARM64 toolchain and switch the temporary Windows ARM64 test build into the amd64_arm64 developer environment so the Tauri linker stops pulling x64 SDK libraries.
2026-03-09 15:49:55 +10:00
LukeParkerDev
4b08236192 ci: install llvm in arm64 test workflow
Install clang with Chocolatey on the temporary Windows ARM64 test workflow because the Blacksmith Windows image does not expose LLVM through the Visual Studio path lookup.
2026-03-09 15:30:51 +10:00
LukeParkerDev
121fac44b8 ci: make arm64 test workflow fork-safe
Run the temporary Windows ARM64 workflow from the PR head branch without release credentials. Disable Tauri updater artifacts so the build can run without signing secrets.
2026-03-09 15:05:38 +10:00
LukeParkerDev
c8f58758c0 ci: add windows arm64 test workflow
Build the CLI, Tauri, and Electron Windows ARM64 artifacts on pushes to the feature branch so we can validate CI without manual prereleases.
2026-03-09 15:03:14 +10:00
LukeParkerDev
39b269f594 Merge remote-tracking branch 'upstream/dev' into feat/windows-arm64-support 2026-03-09 14:52:47 +10:00
LukeParkerDev
f9ac142d62 fix(ci): add clang for windows arm64 tauri builds 2026-03-06 18:02:35 +10:00
LukeParkerDev
ac991e8242 feat(windows): add arm64 release targets for cli and desktop 2026-03-06 17:04:52 +10:00
9 changed files with 178 additions and 4 deletions

View File

@@ -115,6 +115,8 @@ jobs:
target: x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
- host: blacksmith-4vcpu-windows-2025
target: aarch64-pc-windows-msvc
- host: blacksmith-4vcpu-windows-2025
target: x86_64-pc-windows-msvc
- host: blacksmith-4vcpu-ubuntu-2404
@@ -212,6 +214,27 @@ jobs:
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
- name: Setup Windows ARM64 clang
if: runner.os == 'Windows' && matrix.settings.target == 'aarch64-pc-windows-msvc'
shell: pwsh
run: |
$vswhere = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\Installer\vswhere.exe"
if (!(Test-Path $vswhere)) { throw "vswhere.exe not found at $vswhere" }
$root = & $vswhere -latest -products * -property installationPath
if (!$root) { throw "Visual Studio installation not found" }
$llvm = Join-Path $root "VC\Tools\Llvm"
$bin = @(
(Join-Path $llvm "x64\bin"),
(Join-Path $llvm "bin")
) | Where-Object { Test-Path (Join-Path $_ "clang.exe") } | Select-Object -First 1
if (!$bin -and (Test-Path $llvm)) {
$bin = Get-ChildItem -Path $llvm -Filter clang.exe -Recurse -File | Select-Object -First 1 | ForEach-Object { $_.DirectoryName }
}
if (!$bin) { throw "clang.exe not found under $llvm" }
$env:PATH = "$bin;$env:PATH"
Add-Content -Path $env:GITHUB_PATH -Value $bin
clang --version
- name: Build and upload artifacts
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
timeout-minutes: 60
@@ -254,6 +277,9 @@ jobs:
- host: macos-latest
target: aarch64-apple-darwin
platform_flag: --mac --arm64
- host: "blacksmith-4vcpu-windows-2025"
target: aarch64-pc-windows-msvc
platform_flag: --win --arm64
- host: "blacksmith-4vcpu-windows-2025"
target: x86_64-pc-windows-msvc
platform_flag: --win

122
.github/workflows/test-windows-arm64.yml vendored Normal file
View File

@@ -0,0 +1,122 @@
name: test-windows-arm64
on:
push:
branches:
- feat/windows-arm64-support
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: read
contents: read
jobs:
build-cli:
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-bun
- name: Build
run: ./packages/opencode/script/build.ts
env:
OPENCODE_VERSION: 0.0.0-windows-arm64-test
- uses: actions/upload-artifact@v4
with:
name: opencode-cli
path: packages/opencode/dist
build-tauri:
needs: build-cli
runs-on: windows-2025
steps:
- uses: actions/checkout@v4
with:
fetch-tags: true
- uses: ./.github/actions/setup-bun
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-pc-windows-msvc
- uses: Swatinem/rust-cache@v2
with:
workspaces: packages/desktop/src-tauri
shared-key: aarch64-pc-windows-msvc
- name: Create test config
shell: pwsh
run: |
$cfg = Get-Content "packages/desktop/src-tauri/tauri.prod.conf.json" -Raw | ConvertFrom-Json -AsHashtable
$cfg.bundle.createUpdaterArtifacts = $false
if ($cfg.plugins) { $cfg.plugins.Remove("updater") }
$cfg | ConvertTo-Json -Depth 100 | Set-Content "packages/desktop/src-tauri/tauri.test.conf.json"
- name: Prepare
run: |
cd packages/desktop
bun ./scripts/prepare.ts
env:
OPENCODE_VERSION: 0.0.0-windows-arm64-test
RUST_TARGET: aarch64-pc-windows-msvc
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}
- name: Build and upload artifacts
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
timeout-minutes: 60
with:
projectPath: packages/desktop
uploadWorkflowArtifacts: true
args: --target aarch64-pc-windows-msvc --config ./src-tauri/tauri.test.conf.json --verbose
updaterJsonPreferNsis: true
env:
GITHUB_TOKEN: ${{ github.token }}
build-electron:
needs: build-cli
runs-on: blacksmith-4vcpu-windows-2025
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-bun
- uses: actions/setup-node@v4
with:
node-version: "24"
- name: Prepare
run: bun ./scripts/prepare.ts
working-directory: packages/desktop-electron
env:
OPENCODE_VERSION: 0.0.0-windows-arm64-test
OPENCODE_CHANNEL: prod
RUST_TARGET: aarch64-pc-windows-msvc
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}
- name: Build
run: bun run build
working-directory: packages/desktop-electron
env:
OPENCODE_CHANNEL: prod
- name: Package
run: npx electron-builder --win --arm64 --publish never --config electron-builder.config.ts
working-directory: packages/desktop-electron
timeout-minutes: 60
env:
OPENCODE_CHANNEL: prod
- uses: actions/upload-artifact@v4
with:
name: opencode-electron-aarch64-pc-windows-msvc
path: packages/desktop-electron/dist/*

View File

@@ -78,9 +78,17 @@ async function read(subdir: string, filename: string): Promise<LatestYml | undef
const output: Record<string, string> = {}
// Windows: single arch, pass through
const win = await read("latest-yml-x86_64-pc-windows-msvc", "latest.yml")
if (win) output["latest.yml"] = serialize(win)
// Windows: merge arm64 + x64 into single file
const winX64 = await read("latest-yml-x86_64-pc-windows-msvc", "latest.yml")
const winArm64 = await read("latest-yml-aarch64-pc-windows-msvc", "latest.yml")
if (winX64 || winArm64) {
const base = winArm64 ?? winX64!
output["latest.yml"] = serialize({
version: base.version,
files: [...(winArm64?.files ?? []), ...(winX64?.files ?? [])],
releaseDate: base.releaseDate,
})
}
// Linux x64: pass through
const linuxX64 = await read("latest-yml-x86_64-unknown-linux-gnu", "latest-linux.yml")

View File

@@ -19,6 +19,11 @@ export const SIDECAR_BINARIES: Array<{ rustTarget: string; ocBinary: string; ass
ocBinary: "opencode-darwin-x64-baseline",
assetExt: "zip",
},
{
rustTarget: "aarch64-pc-windows-msvc",
ocBinary: "opencode-windows-arm64",
assetExt: "zip",
},
{
rustTarget: "x86_64-pc-windows-msvc",
ocBinary: "opencode-windows-x64-baseline",
@@ -41,7 +46,7 @@ export const RUST_TARGET = Bun.env.RUST_TARGET
function nativeTarget() {
const { platform, arch } = process
if (platform === "darwin") return arch === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin"
if (platform === "win32") return "x86_64-pc-windows-msvc"
if (platform === "win32") return arch === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc"
if (platform === "linux") return arch === "arm64" ? "aarch64-unknown-linux-gnu" : "x86_64-unknown-linux-gnu"
throw new Error(`Unsupported platform: ${platform}/${arch}`)
}

View File

@@ -101,6 +101,7 @@ const targets = [
{ key: "linux-x86_64-rpm", asset: "opencode-desktop-linux-x86_64.rpm" },
{ key: "linux-aarch64-deb", asset: "opencode-desktop-linux-arm64.deb" },
{ key: "linux-aarch64-rpm", asset: "opencode-desktop-linux-aarch64.rpm" },
{ key: "windows-aarch64-nsis", asset: "opencode-desktop-windows-arm64.exe" },
{ key: "windows-x86_64-nsis", asset: "opencode-desktop-windows-x64.exe" },
{ key: "darwin-x86_64-app", asset: "opencode-desktop-darwin-x64.app.tar.gz" },
{
@@ -129,6 +130,7 @@ const alias = (key: string, source: string) => {
alias("linux-x86_64", "linux-x86_64-deb")
alias("linux-aarch64", "linux-aarch64-deb")
alias("windows-aarch64", "windows-aarch64-nsis")
alias("windows-x86_64", "windows-x86_64-nsis")
alias("darwin-x86_64", "darwin-x86_64-app")
alias("darwin-aarch64", "darwin-aarch64-app")

View File

@@ -11,6 +11,11 @@ export const SIDECAR_BINARIES: Array<{ rustTarget: string; ocBinary: string; ass
ocBinary: "opencode-darwin-x64-baseline",
assetExt: "zip",
},
{
rustTarget: "aarch64-pc-windows-msvc",
ocBinary: "opencode-windows-arm64",
assetExt: "zip",
},
{
rustTarget: "x86_64-pc-windows-msvc",
ocBinary: "opencode-windows-x64-baseline",

View File

@@ -35,6 +35,7 @@
"@parcel/watcher-linux-arm64-musl": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-musl": "2.5.1",
"@parcel/watcher-win32-arm64": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1",
"@standard-schema/spec": "1.0.0",
"@tsconfig/bun": "catalog:",

View File

@@ -108,6 +108,10 @@ const allTargets: {
arch: "x64",
avx2: false,
},
{
os: "win32",
arch: "arm64",
},
{
os: "win32",
arch: "x64",

View File

@@ -100,6 +100,7 @@ export namespace Ripgrep {
},
"x64-darwin": { platform: "x86_64-apple-darwin", extension: "tar.gz" },
"x64-linux": { platform: "x86_64-unknown-linux-musl", extension: "tar.gz" },
"arm64-win32": { platform: "aarch64-pc-windows-msvc", extension: "zip" },
"x64-win32": { platform: "x86_64-pc-windows-msvc", extension: "zip" },
} as const