name: Release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
tag:
description: "Existing tag to build and attach assets to (e.g. v0.0.22)"
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions:
contents: write
jobs:
release:
if: github.event_name == 'push'
runs-on: cpu
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with:
fetch-depth: 0
- name: Create GitHub Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b with:
generate_release_notes: true
build-linux:
needs: release
if: ${{ always() && (needs.release.result == 'success' || needs.release.result == 'skipped') }}
runs-on: cpu
timeout-minutes: 30
env:
HOME: /home/runner
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
asset: zc-linux-x86_64
cross: false
- target: aarch64-unknown-linux-gnu
asset: zc-linux-arm64
cross: true
steps:
- name: Purge stale git URL rewrites (ARC runner hygiene)
shell: bash
run: |
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/' 2>/dev/null || true
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/zakuro-drive' 2>/dev/null || true
git config --global --unset-all core.sshCommand 2>/dev/null || true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with:
ref: ${{ inputs.tag || github.ref_name }}
- name: Git auth for private zakuro-drive dependency (read-only deploy key)
shell: bash
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "${{ secrets.DRIVE_DEPLOY_KEY }}" > ~/.ssh/zakuro_drive_deploy
chmod 600 ~/.ssh/zakuro_drive_deploy
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
git config --global core.sshCommand "ssh -i ~/.ssh/zakuro_drive_deploy -o IdentitiesOnly=yes"
git config --global url."ssh://git@github.com/zakuro-ai/".insteadOf "https://github.com/zakuro-ai/"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with:
toolchain: "stable"
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 with:
key: ${{ matrix.target }}
- name: Install cross toolchain (arm64 only)
if: matrix.cross
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- name: Build release binaries
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
run: cargo build --release --workspace --target ${{ matrix.target }}
- name: Stage assets
run: |
set -euo pipefail
cp target/${{ matrix.target }}/release/zc ${{ matrix.asset }}
cp target/${{ matrix.target }}/release/zc-hooks ${{ matrix.asset }}-hooks
- name: Verify architecture
run: |
set -euo pipefail
ASSET="${{ matrix.asset }}"
MACHINE=$(od -An -tx1 -j18 -N2 "$ASSET" | tr -d ' \n')
echo "$ASSET e_machine=0x$MACHINE"
case "${{ matrix.target }}" in
aarch64-*) EXPECT="b700" ;;
x86_64-*) EXPECT="3e00" ;;
*) echo "::error::no e_machine mapping for ${{ matrix.target }}"; exit 1 ;;
esac
if [ "$MACHINE" != "$EXPECT" ]; then
echo "::error::$ASSET is e_machine=0x$MACHINE, expected 0x$EXPECT for ${{ matrix.target }}"
exit 1
fi
- name: Attach to release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b with:
tag_name: ${{ inputs.tag || github.ref_name }}
files: |
${{ matrix.asset }}
${{ matrix.asset }}-hooks
- name: Cleanup git SSH config (runner hygiene)
if: always()
run: |
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/' 2>/dev/null || true
git config --global --unset-all 'core.sshCommand' 2>/dev/null || true
build-macos:
needs: release
if: ${{ always() && (needs.release.result == 'success' || needs.release.result == 'skipped') && vars.MACOS_RELEASE == 'true' }}
runs-on: [self-hosted, macOS, ARM64]
timeout-minutes: 30
steps:
- name: Purge stale git URL rewrites (ARC runner hygiene)
shell: bash
run: |
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/' 2>/dev/null || true
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/zakuro-drive' 2>/dev/null || true
git config --global --unset-all core.sshCommand 2>/dev/null || true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with:
ref: ${{ inputs.tag || github.ref_name }}
- name: Git auth for private zakuro-drive dependency (read-only deploy key)
shell: bash
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "${{ secrets.DRIVE_DEPLOY_KEY }}" > ~/.ssh/zakuro_drive_deploy
chmod 600 ~/.ssh/zakuro_drive_deploy
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
git config --global core.sshCommand "ssh -i ~/.ssh/zakuro_drive_deploy -o IdentitiesOnly=yes"
git config --global url."ssh://git@github.com/zakuro-ai/".insteadOf "https://github.com/zakuro-ai/"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with:
toolchain: "stable"
targets: aarch64-apple-darwin
- name: Build release binaries
run: cargo build --release --workspace --target aarch64-apple-darwin
- name: Stage assets
run: |
set -euo pipefail
cp target/aarch64-apple-darwin/release/zc zc-darwin-arm64
cp target/aarch64-apple-darwin/release/zc-hooks zc-darwin-arm64-hooks
- name: Attach to release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b with:
tag_name: ${{ inputs.tag || github.ref_name }}
files: |
zc-darwin-arm64
zc-darwin-arm64-hooks
- name: Cleanup git SSH config (runner hygiene)
if: always()
run: |
git config --global --remove-section 'url.ssh://git@github.com/zakuro-ai/' 2>/dev/null || true
git config --global --unset-all 'core.sshCommand' 2>/dev/null || true
deploy-prod:
needs: release
if: github.event_name == 'push'
runs-on: cpu
timeout-minutes: 10
steps:
- name: Deploy to production
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.DEPLOY_PAT }}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/zakuro-ai/zakuro-infra/dispatches \
-d '{"event_type":"deploy-prod","client_payload":{"service":"zc","version":"${{ github.ref_name }}"}}'