Skip to content

Release

Release #2

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., 0.2.0 - no v prefix)'
required: true
type: string
# Prevent concurrent releases
concurrency:
group: release
cancel-in-progress: false
# Restrict permissions to minimum required
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
validate:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.validate.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Validate version format
id: validate
run: |
VERSION="${{ inputs.version }}"
if ! echo "$VERSION" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
echo "::error::Version must be in format X.Y.Z or X.Y.Z-suffix (e.g., 0.2.0, 1.0.0-alpha.1)"
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Valid version: $VERSION"
- name: Check tag does not exist
run: |
if git rev-parse "v${{ steps.validate.outputs.version }}" >/dev/null 2>&1; then
echo "::error::Tag v${{ steps.validate.outputs.version }} already exists"
exit 1
fi
echo "Tag v${{ steps.validate.outputs.version }} is available"
# Test gate: ensure code compiles and tests pass
test:
runs-on: macos-latest
needs: validate
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-test-
- name: Run tests
run: cargo test --all-features
- name: Build release binary
run: cargo build --release
# Security gate: must pass before release proceeds
security:
runs-on: ubuntu-latest
needs: validate
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
key: ${{ runner.os }}-cargo-security-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-security-
- name: Install security tools
run: |
cargo install cargo-audit --locked
cargo install cargo-deny --locked
- name: Run cargo audit
run: cargo audit --deny warnings
- name: Run cargo deny
run: cargo deny check
# Prepare release: bump version, generate changelog, create tag
prepare:
runs-on: ubuntu-latest
needs: [validate, test, security]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
key: ${{ runner.os }}-cargo-release-tools-v1
- name: Install release tools
run: |
# Install cargo-edit for version bumping
cargo install cargo-edit --locked
# Install git-cliff for changelog generation
cargo install git-cliff --locked
- name: Bump version in Cargo.toml
run: |
cargo set-version ${{ needs.validate.outputs.version }}
cargo update -p sx
- name: Generate changelog
run: |
git-cliff --tag v${{ needs.validate.outputs.version }} --output CHANGELOG.md
- name: Commit version bump and changelog
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock CHANGELOG.md
git commit -m "chore(release): v${{ needs.validate.outputs.version }}"
git tag -a "v${{ needs.validate.outputs.version }}" -m "Release v${{ needs.validate.outputs.version }}"
git push origin main
git push origin "v${{ needs.validate.outputs.version }}"
# Build release binaries for macOS (Intel and Apple Silicon)
build:
runs-on: macos-latest
needs: [validate, prepare]
strategy:
fail-fast: false
matrix:
target:
- x86_64-apple-darwin
- aarch64-apple-darwin
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: v${{ needs.validate.outputs.version }}
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.target }}-cargo-
- name: Build release binary
run: cargo build --release --target ${{ matrix.target }}
- name: Create archive
run: |
mkdir -p dist
cp target/${{ matrix.target }}/release/sx dist/
cd dist
tar czf sx-${{ needs.validate.outputs.version }}-${{ matrix.target }}.tar.gz sx
shasum -a 256 sx-${{ needs.validate.outputs.version }}-${{ matrix.target }}.tar.gz > sx-${{ needs.validate.outputs.version }}-${{ matrix.target }}.tar.gz.sha256
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sx-${{ matrix.target }}
path: dist/*.tar.gz*
retention-days: 1
# Create GitHub release with all artifacts
release:
runs-on: ubuntu-latest
needs: [validate, build]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: v${{ needs.validate.outputs.version }}
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: List artifacts
run: ls -la artifacts/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.validate.outputs.version }}
name: v${{ needs.validate.outputs.version }}
body_path: CHANGELOG.md
draft: false
prerelease: ${{ contains(needs.validate.outputs.version, '-') }}
files: |
artifacts/*.tar.gz
artifacts/*.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Update Homebrew tap with new version
# NOTE: This job is specific to agentic-dev3o organization.
# Forks should either disable this job or update the owner/repositories values.
update-tap:
runs-on: ubuntu-latest
needs: [validate, release]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: v${{ needs.validate.outputs.version }}
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: agentic-dev3o
repositories: homebrew-sx
- name: Update Homebrew formula
uses: mislav/bump-homebrew-formula-action@v3
with:
formula-name: sx
homebrew-tap: agentic-dev3o/homebrew-sx
tag-name: v${{ needs.validate.outputs.version }}
commit-message: |
{{formulaName}} {{version}}
Created by https://github.com/mislav/bump-homebrew-formula-action
env:
COMMITTER_TOKEN: ${{ steps.app-token.outputs.token }}