name: Release
on:
push:
tags: ["v*"]
permissions:
contents: write
env:
BIN_NAME: claude-codex
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- name: Test
run: cargo test --locked -- --test-threads=1
build:
needs: checks
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
target: aarch64-apple-darwin
platform: darwin-arm64
ext: ""
archive: tar.gz
- os: macos-15-intel
target: x86_64-apple-darwin
platform: darwin-amd64
ext: ""
archive: tar.gz
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
platform: linux-amd64
ext: ""
archive: tar.gz
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
platform: linux-arm64
ext: ""
archive: tar.gz
- os: windows-latest
target: x86_64-pc-windows-msvc
platform: windows-amd64
ext: .exe
archive: zip
- os: windows-11-arm
target: aarch64-pc-windows-msvc
platform: windows-arm64
ext: .exe
archive: zip
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Build
run: |
cargo build --release --locked --target ${{ matrix.target }}
- name: Verify Unix binary
if: runner.os != 'Windows'
env:
VERSION: ${{ github.ref_name }}
run: |
expected="claude-codex ${VERSION#v}"
actual="$(target/${{ matrix.target }}/release/${BIN_NAME} --version)"
test "$actual" = "$expected"
- name: Verify Windows binary
if: runner.os == 'Windows'
shell: pwsh
env:
VERSION: ${{ github.ref_name }}
run: |
$expected = "claude-codex $($env:VERSION.TrimStart('v'))"
$actual = & "target/${{ matrix.target }}/release/${env:BIN_NAME}.exe" --version
if ($actual -ne $expected) {
Write-Error "expected '$expected', got '$actual'"
}
- name: Package Unix
if: runner.os != 'Windows'
run: |
mkdir -p dist
cp "target/${{ matrix.target }}/release/${BIN_NAME}" "dist/${BIN_NAME}"
archive="${BIN_NAME}-${{ matrix.platform }}.${{ matrix.archive }}"
tar -C dist -czf "$archive" "${BIN_NAME}"
shasum -a 256 "$archive" > "${BIN_NAME}-${{ matrix.platform }}.sha256"
- name: Package Windows
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force dist | Out-Null
Copy-Item "target/${{ matrix.target }}/release/${env:BIN_NAME}.exe" "dist/${env:BIN_NAME}.exe"
$archive = "${env:BIN_NAME}-${{ matrix.platform }}.${{ matrix.archive }}"
Compress-Archive -Path "dist/${env:BIN_NAME}.exe" -DestinationPath $archive -Force
$hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLower()
"$hash $archive" | Out-File -FilePath "${env:BIN_NAME}-${{ matrix.platform }}.sha256" -Encoding ascii
- uses: actions/upload-artifact@v5
with:
name: ${{ matrix.platform }}
path: |
${{ env.BIN_NAME }}-${{ matrix.platform }}.${{ matrix.archive }}
${{ env.BIN_NAME }}-${{ matrix.platform }}.sha256
smoke-windows:
needs: build
runs-on: windows-latest
steps:
- uses: actions/download-artifact@v5
with:
name: windows-amd64
- shell: pwsh
run: |
Expand-Archive claude-codex-windows-amd64.zip -DestinationPath .
.\claude-codex.exe --version
release:
needs: [build, smoke-windows]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v5
with:
merge-multiple: true
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
*.tar.gz
*.zip
*.sha256