name: Release
on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
version:
description: 'Version to release'
required: true
type: string
permissions:
contents: write
jobs:
create-release:
name: Create Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get version
id: get_version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Generate release notes
id: release_notes
run: |
echo "# Release ${{ steps.get_version.outputs.version }}" > release_notes.md
echo "" >> release_notes.md
echo "## Changes" >> release_notes.md
# Get the previous tag
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
if [[ -n "$PREVIOUS_TAG" ]]; then
echo "Changes since $PREVIOUS_TAG:" >> release_notes.md
git log --oneline --format="- %s" $PREVIOUS_TAG..HEAD >> release_notes.md
else
echo "Initial release" >> release_notes.md
git log --oneline --format="- %s" >> release_notes.md
fi
- name: Create Release
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ steps.get_version.outputs.version }}" \
--title "Release ${{ steps.get_version.outputs.version }}" \
--notes-file release_notes.md \
--draft=false \
--prerelease=false
build-release:
name: Build Release
needs: create-release
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
binary: claudeforge
archive: tar.gz
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
binary: claudeforge
archive: tar.gz
- os: macos-latest
target: x86_64-apple-darwin
binary: claudeforge
archive: tar.gz
- os: macos-latest
target: aarch64-apple-darwin
binary: claudeforge
archive: tar.gz
- os: windows-latest
target: x86_64-pc-windows-msvc
binary: claudeforge.exe
archive: zip
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: |
sudo apt-get update
sudo apt-get install -y musl-tools pkg-config
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build release binary
run: cargo build --release --target ${{ matrix.target }}
env:
OPENSSL_STATIC: ${{ matrix.target == 'x86_64-unknown-linux-musl' && '1' || '' }}
- name: Create archive (Unix)
if: matrix.archive == 'tar.gz'
run: |
mkdir -p release
cp target/${{ matrix.target }}/release/${{ matrix.binary }} release/
cp README.md LICENSE release/
cd release
tar -czf ../claudeforge-${{ matrix.target }}.tar.gz .
- name: Create archive (Windows)
if: matrix.archive == 'zip'
run: |
mkdir release
cp target/${{ matrix.target }}/release/${{ matrix.binary }} release/
cp README.md release/
cp LICENSE release/
cd release
7z a ../claudeforge-${{ matrix.target }}.zip .
- name: Generate checksums
shell: bash
run: |
if [[ "${{ matrix.archive }}" == "tar.gz" ]]; then
if [[ "${{ runner.os }}" == "macOS" ]]; then
shasum -a 256 claudeforge-${{ matrix.target }}.tar.gz > claudeforge-${{ matrix.target }}.tar.gz.sha256
else
sha256sum claudeforge-${{ matrix.target }}.tar.gz > claudeforge-${{ matrix.target }}.tar.gz.sha256
fi
else
if [[ "${{ runner.os }}" == "Windows" ]]; then
powershell -Command "Get-FileHash -Algorithm SHA256 claudeforge-${{ matrix.target }}.zip | ForEach-Object { \$_.Hash.ToLower() + ' ' + \$_.Path.Split('\')[-1] }" > claudeforge-${{ matrix.target }}.zip.sha256
else
sha256sum claudeforge-${{ matrix.target }}.zip > claudeforge-${{ matrix.target }}.zip.sha256
fi
fi
- name: Upload Release Assets
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ "${{ matrix.archive }}" == "tar.gz" ]]; then
gh release upload "${{ needs.create-release.outputs.version }}" \
"claudeforge-${{ matrix.target }}.tar.gz" \
"claudeforge-${{ matrix.target }}.tar.gz.sha256"
else
gh release upload "${{ needs.create-release.outputs.version }}" \
"claudeforge-${{ matrix.target }}.zip" \
"claudeforge-${{ matrix.target }}.zip.sha256"
fi