name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
jobs:
build:
name: Build ${{ matrix.asset }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
asset: holon-linux-amd64
- os: macos-latest
target: x86_64-apple-darwin
asset: holon-darwin-amd64
- os: macos-latest
target: aarch64-apple-darwin
asset: holon-darwin-arm64
steps:
- uses: actions/checkout@v4
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Build release binary
run: cargo build --release --locked --target "${{ matrix.target }}"
- name: Package release archive
run: |
set -euo pipefail
mkdir -p dist
tmpdir="$(mktemp -d)"
cp "target/${{ matrix.target }}/release/holon" "$tmpdir/holon"
tar -czf "dist/${{ matrix.asset }}.tar.gz" -C "$tmpdir" holon
shasum -a 256 "dist/${{ matrix.asset }}.tar.gz" > "dist/${{ matrix.asset }}.tar.gz.sha256"
- name: Upload release artifact
uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.asset }}
path: dist/*
if-no-files-found: error
release:
name: Publish GitHub release
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- name: Download release artifacts
uses: actions/download-artifact@v4
with:
path: dist-artifacts
pattern: release-*
merge-multiple: true
- name: Validate release version
run: |
set -euo pipefail
crate_version="$(awk -F '"' '/^version = / { print $2; exit }' Cargo.toml)"
tag_version="${GITHUB_REF_NAME#v}"
if [ "$crate_version" != "$tag_version" ]; then
echo "Cargo.toml version ($crate_version) must match tag version ($tag_version)." >&2
exit 1
fi
- name: Prepare checksums and Homebrew formula
run: |
set -euo pipefail
(
cd dist-artifacts
rm -f ./*.sha256
shasum -a 256 ./*.tar.gz | sort -k2 > checksums.txt
)
bash scripts/generate-homebrew-formula.sh \
"$GITHUB_REF_NAME" \
dist-artifacts/checksums.txt \
homebrew-tap/Formula/holon.rb
- name: Upload Homebrew formula artifact
uses: actions/upload-artifact@v4
with:
name: homebrew-formula
path: homebrew-tap/Formula/holon.rb
if-no-files-found: error
- name: Prepare release notes
run: |
set -euo pipefail
cat > release-notes.md <<EOF
## Runtime line
Holon ${GITHUB_REF_NAME} is part of the Rust runtime line. The Rust runtime is now the main \`holon\` binary.
This line is intentionally breaking relative to the old Go-line releases. If you need the old Go implementation, stay on \`v0.12.0\`.
Supported binary assets for this release are Linux amd64, macOS amd64, and macOS arm64.
## Install
Homebrew:
\`\`\`bash
brew tap holon-run/tap
brew install holon
\`\`\`
Direct binary:
\`\`\`bash
curl -L "https://github.com/holon-run/holon/releases/download/${GITHUB_REF_NAME}/holon-linux-amd64.tar.gz" | tar -xz
chmod +x holon
./holon --help
\`\`\`
Replace \`holon-linux-amd64.tar.gz\` with \`holon-darwin-amd64.tar.gz\` or \`holon-darwin-arm64.tar.gz\` on macOS.
EOF
- name: Publish GitHub release
uses: softprops/action-gh-release@v2
with:
body_path: release-notes.md
files: |
dist-artifacts/*.tar.gz
dist-artifacts/checksums.txt
- name: Push Homebrew formula
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
set -euo pipefail
if [ -z "${HOMEBREW_TAP_TOKEN}" ]; then
echo "HOMEBREW_TAP_TOKEN is not configured; formula was generated as an artifact only."
exit 0
fi
tap_dir="$(mktemp -d)"
git clone "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/holon-run/homebrew-tap.git" "$tap_dir"
mkdir -p "$tap_dir/Formula"
cp homebrew-tap/Formula/holon.rb "$tap_dir/Formula/holon.rb"
cd "$tap_dir"
git config user.name "holon-bot"
git config user.email "holon-bot@holon.run"
git add Formula/holon.rb
if git diff --staged --quiet; then
echo "Homebrew formula is already up to date."
exit 0
fi
git commit -m "Update Holon formula for ${GITHUB_REF_NAME}"
git push origin main