Skip to content

Merge pull request #23 from anomalyco/bump-0.3.0 #122

Merge pull request #23 from anomalyco/bump-0.3.0

Merge pull request #23 from anomalyco/bump-0.3.0 #122

Workflow file for this run

name: Windows
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: windows-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
jobs:
test:
name: Build and test (${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: windows-2025
target: x86_64-pc-windows-msvc
machine: "8664"
- arch: arm64
runner: windows-11-arm
target: aarch64-pc-windows-msvc
machine: "aa64"
defaults:
run:
shell: pwsh
env:
CARGO_TERM_COLOR: always
CARGO_BUILD_TARGET: ${{ matrix.target }}
RUSTUP_TOOLCHAIN: 1.90.0-x86_64-pc-windows-msvc
RUST_BACKTRACE: "1"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Enable long dependency paths
run: git config --global core.longpaths true
- uses: mlugg/setup-zig@8d6198c65fb0feaa111df26e6b467fea8345e46f # v2.0.5
if: matrix.arch == 'x64'
with:
version: 0.16.0
cache-key: ${{ matrix.target }}
# Zig 0.16 crashes when building Ghostty on the native ARM64 host.
# Use x64-hosted compilers on this ARM64 runner, but execute ARM64 tests natively.
- name: Install x64 Zig for ARM64 cross-compilation
if: matrix.arch == 'arm64'
run: |
$archive = Join-Path $env:RUNNER_TEMP 'zig-x64.zip'
Invoke-WebRequest 'https://ziglang.org/download/0.16.0/zig-x86_64-windows-0.16.0.zip' -OutFile $archive
if ((Get-FileHash $archive -Algorithm SHA256).Hash -ne '68659eb5f1e4eb1437a722f1dd889c5a322c9954607f5edcf337bc3684a75a7e') { throw 'Zig archive checksum mismatch' }
Expand-Archive $archive -DestinationPath $env:RUNNER_TEMP
Join-Path $env:RUNNER_TEMP 'zig-x86_64-windows-0.16.0' >> $env:GITHUB_PATH
- name: Fix Zig 0.16 ARM64 function-pointer alignment
if: matrix.arch == 'arm64'
run: |
# ARM64 function pointers require 4-byte alignment, unlike *anyopaque.
# Zig 0.16's Windows stack-trace helper omits the required alignment assertion.
$file = Join-Path $env:RUNNER_TEMP 'zig-x86_64-windows-0.16.0/lib/std/debug/SelfInfo/Windows.zig'
$source = [System.IO.File]::ReadAllText($file)
$old = '@ptrCast(try si.loadNtdllProc(@tagName(proc)))'
if (!$source.Contains($old)) { throw 'Zig alignment workaround no longer matches; re-evaluate it' }
[System.IO.File]::WriteAllText($file, $source.Replace($old, '@ptrCast(@alignCast(try si.loadNtdllProc(@tagName(proc))))'))
- name: Install Rust toolchain and target
run: rustup toolchain install $env:RUSTUP_TOOLCHAIN --force-non-host --profile minimal --component rustfmt --component clippy --target $env:CARGO_BUILD_TARGET
- name: Verify runner and compiler architecture
env:
EXPECTED_ARCH: ${{ matrix.arch }}
run: |
$arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()
Write-Output "Windows architecture: $arch"
if ($arch -ine $env:EXPECTED_ARCH) { throw "Expected native $env:EXPECTED_ARCH runner, got $arch" }
$compiler = rustc -vV
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$compiler
if ($compiler -notcontains 'host: x86_64-pc-windows-msvc') { throw 'Unexpected Rust compiler host' }
Write-Output "Executable target: $env:CARGO_BUILD_TARGET"
zig version
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
with:
key: windows-${{ matrix.target }}-zig-0.16.0
# The native Ghostty build is now an output of the workspace crate.
cache-workspace-crates: true
cache-on-failure: true
- name: Check formatting
run: cargo fmt --check
- name: Check Clippy
run: cargo clippy --locked --all-targets --all-features -- -D warnings
- name: Build executable
id: build
run: cargo build --locked
- name: Run tests
id: tests
timeout-minutes: 10
run: cargo test --locked --all-targets --all-features
- name: Run standalone library tests
env:
EXPECTED_MACHINE: ${{ matrix.machine }}
run: |
$artifacts = cargo test --locked --lib --no-run --message-format=json | ForEach-Object { $_ | ConvertFrom-Json }
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$binary = ($artifacts | Where-Object { $_.reason -eq 'compiler-artifact' -and $_.profile.test -and $_.executable }).executable
# Cargo adds native library paths to PATH, which can hide accidental DLL dependencies.
# Copy only the executable so neither Cargo nor adjacent build artifacts can supply them.
$directory = Join-Path $env:RUNNER_TEMP 'pty-standalone-tests'
New-Item -ItemType Directory -Force $directory | Out-Null
$standalone = Join-Path $directory 'opencode-pty-tests.exe'
Copy-Item $binary $standalone
$bytes = [System.IO.File]::ReadAllBytes($standalone)
$header = [BitConverter]::ToInt32($bytes, 0x3c)
$machine = [BitConverter]::ToUInt16($bytes, $header + 4)
if ($machine -ne [Convert]::ToUInt16($env:EXPECTED_MACHINE, 16)) { throw 'Test executable architecture does not match the runner' }
& $standalone
- name: Diagnose failed library tests
if: failure() && steps.tests.outcome == 'failure'
timeout-minutes: 10
run: cargo test --locked --lib --all-features -- --test-threads=1 --nocapture
- name: Diagnose failed runtime tests
if: failure() && steps.tests.outcome == 'failure'
timeout-minutes: 3
run: cargo test --locked --test runtime -- --test-threads=1 --nocapture
- name: Diagnose failed daemon tests
if: failure() && steps.tests.outcome == 'failure'
timeout-minutes: 3
run: cargo test --locked --test windows-daemon -- --test-threads=1 --nocapture
- name: Smoke test executable
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
$metadata = cargo metadata --locked --no-deps --format-version 1 | ConvertFrom-Json
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$version = ($metadata.packages | Where-Object name -eq 'opencode-pty').version
$binary = Join-Path $metadata.target_directory "$env:CARGO_BUILD_TARGET/debug/opencode-pty.exe"
$output = & $binary --version
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Write-Output $output
if ($output -ne "opencode-pty $version (protocol 7)") { throw "Unexpected executable version: $output" }
- name: Document current coverage
if: always()
run: |
@"
## Windows ${{ matrix.arch }}
Target: $env:CARGO_BUILD_TARGET
This job builds the executable and runs all enabled tests natively, including libghostty parser, protocol, direct TerminalService ConPTY runtime, named-pipe transport, and daemon tests.
The runtime suite spawns real Rust console children and checks input/output, Unicode, cwd/environment/argv/PATH, OS resize, snapshots, replay, terminal replies, and independent terminals.
Daemon tests cover private atomic registration, ownership/handoff, stale registration/locking, partial requests, blocked subscribers, and live ConPTY operations over real named pipes.
The older service, ownership, playground, and rows integration suites remain Unix-only.
Basic tests do not establish exhaustive lifecycle coverage or Windows interactive CLI parity.
No packages or releases are published.
"@ >> $env:GITHUB_STEP_SUMMARY