name: Release CLI
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Tag to release (e.g. v2026.4.6)"
required: true
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
RSCLAW_BUILD_VERSION: ${{ inputs.tag || github.ref_name }}
RSCLAW_BUILD_DATE: ${{ github.event.head_commit.timestamp || github.event.repository.updated_at }}
jobs:
build:
name: CLI ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-22.04
archive: tar.gz
- target: aarch64-unknown-linux-gnu
os: ubuntu-22.04-arm
archive: tar.gz
- target: x86_64-apple-darwin
os: macos-14
archive: tar.gz
- target: aarch64-apple-darwin
os: macos-14
archive: tar.gz
- target: x86_64-pc-windows-msvc
os: windows-latest
archive: zip
- target: aarch64-pc-windows-msvc
os: windows-latest
archive: zip
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.91"
targets: ${{ matrix.target }}
- name: Ensure rust target installed
shell: bash
run: rustup target add ${{ matrix.target }} || true
- uses: Swatinem/rust-cache@v2
with:
key: cli-${{ matrix.target }}
- name: Install protoc (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler libwayland-dev libpipewire-0.3-dev libegl-dev libxkbcommon-dev libgbm-dev
- name: Install protoc (macOS)
if: runner.os == 'macOS'
run: brew install protobuf
- name: Install protoc (Windows)
if: runner.os == 'Windows'
run: choco install protoc -y
- name: Install zigbuild (Linux only)
if: runner.os == 'Linux'
run: |
pip install --user ziglang
cargo install --locked cargo-zigbuild
- name: Build (Linux, glibc-pinned via zigbuild)
if: runner.os == 'Linux'
run: cargo zigbuild --release --target ${{ matrix.target }}.2.34
- name: Build (macOS)
if: runner.os == 'macOS'
run: cargo build --release --target ${{ matrix.target }}
- name: Build (Windows)
if: runner.os == 'Windows'
run: cargo build --release --target ${{ matrix.target }}
- name: Package (tar.gz)
if: matrix.archive == 'tar.gz'
run: |
cd target/${{ matrix.target }}/release
tar czf ../../../rsclaw-${{ github.ref_name }}-${{ matrix.target }}.tar.gz rsclaw
cd ../../..
- name: Package (zip)
if: matrix.archive == 'zip'
shell: pwsh
run: |
Compress-Archive -Path "target/${{ matrix.target }}/release/rsclaw.exe" `
-DestinationPath "rsclaw-${{ github.ref_name }}-${{ matrix.target }}.zip"
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: rsclaw-${{ matrix.target }}
path: rsclaw-${{ github.ref_name }}-${{ matrix.target }}.${{ matrix.archive }}
release:
name: Create CLI Release
runs-on: ubuntu-latest
needs: build
if: always() && !cancelled()
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
path: artifacts
merge-multiple: true
- name: Generate checksums
run: |
cd artifacts
sha256sum rsclaw-* 2>/dev/null > SHA256SUMS.txt || true
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.tag || github.ref_name }}
generate_release_notes: true
files: |
artifacts/rsclaw-*
artifacts/SHA256SUMS.txt
update-tap:
name: Update homebrew-tap Formula
runs-on: ubuntu-latest
needs: release
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout tap repo
uses: actions/checkout@v6
with:
repository: rsclaw-ai/homebrew-tap
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: tap
- name: Fetch SHA256SUMS from the release we just published
env:
GH_TOKEN: ${{ github.token }}
run: |
tag="${{ github.ref_name }}"
gh release download "$tag" -R rsclaw-ai/rsclaw -p SHA256SUMS.txt -O sha.txt
# Each line: "<sha256> rsclaw-<tag>-<target>.tar.gz"
extract() { awk -v t="$1" '$2 == "rsclaw-'"$tag"'-"t".tar.gz" {print $1}' sha.txt; }
{
echo "SHA_AA_DARWIN=$(extract aarch64-apple-darwin)"
echo "SHA_X86_DARWIN=$(extract x86_64-apple-darwin)"
echo "SHA_AA_LINUX=$(extract aarch64-unknown-linux-gnu)"
echo "SHA_X86_LINUX=$(extract x86_64-unknown-linux-gnu)"
} >> "$GITHUB_ENV"
- name: Regenerate Formula
run: |
tag="${{ github.ref_name }}"
cat > tap/Formula/rsclaw.rb <<EOF
class Rsclaw < Formula
desc "AI Agent Engine Compatible with OpenClaw"
homepage "https://github.com/rsclaw-ai/rsclaw"
license any_of: ["MIT", "Apache-2.0"]
on_macos do
if Hardware::CPU.arm?
url "https://github.com/rsclaw-ai/rsclaw/releases/download/${tag}/rsclaw-${tag}-aarch64-apple-darwin.tar.gz"
sha256 "${SHA_AA_DARWIN}"
else
url "https://github.com/rsclaw-ai/rsclaw/releases/download/${tag}/rsclaw-${tag}-x86_64-apple-darwin.tar.gz"
sha256 "${SHA_X86_DARWIN}"
end
end
on_linux do
if Hardware::CPU.arm?
url "https://github.com/rsclaw-ai/rsclaw/releases/download/${tag}/rsclaw-${tag}-aarch64-unknown-linux-gnu.tar.gz"
sha256 "${SHA_AA_LINUX}"
else
url "https://github.com/rsclaw-ai/rsclaw/releases/download/${tag}/rsclaw-${tag}-x86_64-unknown-linux-gnu.tar.gz"
sha256 "${SHA_X86_LINUX}"
end
end
def install
bin.install "rsclaw"
end
test do
assert_match(/\d+\.\d+\.\d+/, shell_output("#{bin}/rsclaw --version"))
end
end
EOF
- name: Commit + push
working-directory: tap
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if git diff --quiet -- Formula/rsclaw.rb; then
echo "Formula already up-to-date — nothing to push."
exit 0
fi
git add Formula/rsclaw.rb
git commit -m "rsclaw ${{ github.ref_name }}"
git push