name: Release
on:
push:
tags:
- "v*"
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
BINARY_NAME: opencode-ralph-loop-cli
jobs:
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- run: cargo fmt --all --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features
- run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
- run: cargo publish --dry-run --allow-dirty
build-matrix:
name: Build (${{ matrix.target }})
needs: validate
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
archive: tar.gz
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
archive: tar.gz
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
archive: tar.gz
use_cross: true
- target: x86_64-apple-darwin
os: macos-latest
archive: tar.gz
- target: aarch64-apple-darwin
os: macos-latest
archive: tar.gz
- target: x86_64-pc-windows-msvc
os: windows-latest
archive: zip
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install musl-tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt-get install -y musl-tools
- name: Install cross
if: matrix.use_cross
run: cargo install cross --locked
- name: Build with cross
if: matrix.use_cross
run: cross build --release --target ${{ matrix.target }}
- name: Build
if: "!matrix.use_cross"
run: cargo build --release --target ${{ matrix.target }}
- name: Package (Unix)
if: matrix.archive == 'tar.gz'
shell: bash
run: |
BINARY="target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}"
ARCHIVE="${{ env.BINARY_NAME }}-${{ matrix.target }}.tar.gz"
tar -czf "$ARCHIVE" -C "$(dirname "$BINARY")" "$(basename "$BINARY")"
sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"
echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"
- name: Package (Windows)
if: matrix.archive == 'zip'
shell: pwsh
run: |
$Binary = "target\${{ matrix.target }}\release\${{ env.BINARY_NAME }}.exe"
$Archive = "${{ env.BINARY_NAME }}-${{ matrix.target }}.zip"
Compress-Archive -Path $Binary -DestinationPath $Archive
$Hash = (Get-FileHash $Archive -Algorithm SHA256).Hash.ToLower()
"$Hash $Archive" | Out-File -FilePath "$Archive.sha256" -Encoding utf8
"ARCHIVE=$Archive" | Add-Content -Path $env:GITHUB_ENV
- uses: actions/upload-artifact@v4
with:
name: binary-${{ matrix.target }}
path: |
${{ env.ARCHIVE }}
${{ env.ARCHIVE }}.sha256
macos-universal:
name: macOS Universal Binary
needs: build-matrix
runs-on: macos-latest
steps:
- uses: actions/download-artifact@v4
with:
name: binary-x86_64-apple-darwin
path: dist/x86_64
- uses: actions/download-artifact@v4
with:
name: binary-aarch64-apple-darwin
path: dist/aarch64
- name: Create universal binary
run: |
tar -xzf "dist/x86_64/${{ env.BINARY_NAME }}-x86_64-apple-darwin.tar.gz" -C dist/x86_64
tar -xzf "dist/aarch64/${{ env.BINARY_NAME }}-aarch64-apple-darwin.tar.gz" -C dist/aarch64
lipo -create \
"dist/x86_64/${{ env.BINARY_NAME }}" \
"dist/aarch64/${{ env.BINARY_NAME }}" \
-output "${{ env.BINARY_NAME }}-universal"
ARCHIVE="${{ env.BINARY_NAME }}-universal-apple-darwin.tar.gz"
tar -czf "$ARCHIVE" "${{ env.BINARY_NAME }}-universal"
shasum -a 256 "$ARCHIVE" > "$ARCHIVE.sha256"
echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
with:
name: binary-universal-apple-darwin
path: |
${{ env.ARCHIVE }}
${{ env.ARCHIVE }}.sha256
publish-github-release:
name: GitHub Release
needs: macos-universal
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
pattern: binary-*
path: dist
merge-multiple: true
- name: Generate SHA256SUMS
run: |
cd dist
cat *.sha256 > SHA256SUMS.txt
- name: Extract release notes from CHANGELOG
run: |
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#v}"
python3 - "$VERSION" << 'EOF'
import sys, re
version = sys.argv[1]
content = open("CHANGELOG.md").read()
pattern = rf"## \[{re.escape(version)}\][^\n]*\n(.*?)(?=\n## \[|\Z)"
m = re.search(pattern, content, re.DOTALL)
print(m.group(1).strip() if m else "See CHANGELOG.md for details.")
EOF
> RELEASE_NOTES.md
echo "TAG=$TAG" >> "$GITHUB_ENV"
- uses: softprops/action-gh-release@v2
with:
name: "${{ env.TAG }}"
body_path: RELEASE_NOTES.md
files: |
dist/*.tar.gz
dist/*.zip
dist/SHA256SUMS.txt
publish-crates-io:
name: Publish to crates.io
needs: publish-github-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo publish --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}