name: Release & Publish
on:
push:
tags:
- 'v*'
permissions:
contents: write
packages: write
env:
CARGO_TERM_COLOR: always
jobs:
quality-checks:
name: Pre-Release Quality Checks
runs-on: [self-hosted, macOS, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
run: |
rustup default stable
rustup component add rustfmt clippy
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/cache
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-release-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt -- --check
- name: Run clippy
run: cargo clippy -- -D warnings
- name: Run tests
run: cargo test --verbose
- name: Security audit
run: |
cargo install cargo-audit
cargo audit --ignore RUSTSEC-2020-0071 --ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2024-0375 --ignore RUSTSEC-2021-0145 || true
build-release:
name: Build Release Artifacts
runs-on: [self-hosted, macOS, ARM64]
needs: quality-checks
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
run: rustup default stable
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/cache
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-release-build-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Extract version from tag
id: version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"
- name: Build release binary
run: |
export RUSTFLAGS="-C target-feature=+aes,+sha2,+neon"
cargo build --release
- name: Generate coverage report
run: |
cargo install cargo-tarpaulin
cargo tarpaulin --verbose --timeout 120 --out Json --out Html --no-default-features
- name: Create release archive
run: |
mkdir -p ./assets
cp target/release/ai-code-buddy ./assets/
cp tarpaulin-report.html ./assets/
cd ./assets
tar -czf ai-code-buddy-v${{ steps.version.outputs.version }}-aarch64-apple-darwin.tar.gz ai-code-buddy
cd ..
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: release-assets
path: ./assets/
retention-days: 7
publish-to-crates:
name: Publish to Crates.io
runs-on: [self-hosted, macOS, ARM64]
needs: [quality-checks, build-release]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
run: rustup default stable
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/cache
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-publish-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Verify version consistency
run: |
CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
TAG_VERSION=${{ needs.build-release.outputs.version }}
echo "Cargo.toml version: $CARGO_VERSION"
echo "Git tag version: $TAG_VERSION"
if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
echo "❌ Version mismatch! Cargo.toml version ($CARGO_VERSION) doesn't match tag version ($TAG_VERSION)"
exit 1
fi
echo "✅ Version consistency check passed"
- name: Final build verification
run: |
echo "Running final build verification before publishing..."
cargo build --release
echo "Build verification successful"
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
echo "Publishing ai-code-buddy v${{ needs.build-release.outputs.version }} to crates.io..."
cargo publish --token $CARGO_REGISTRY_TOKEN
echo "Successfully published to crates.io!"
- name: Verify publication
run: |
echo "Waiting for crates.io to update..."
sleep 30
# Check if the version is available on crates.io
PUBLISHED_VERSION=$(curl -s https://crates.io/api/v1/crates/ai-code-buddy | jq -r '.crate.max_version // "not found"')
EXPECTED_VERSION=${{ needs.build-release.outputs.version }}
echo "Expected version: $EXPECTED_VERSION"
echo "Published version: $PUBLISHED_VERSION"
if [ "$PUBLISHED_VERSION" = "$EXPECTED_VERSION" ]; then
echo "✅ Successfully verified publication on crates.io!"
else
echo "⚠️ Version not yet visible on crates.io (may take a few minutes to propagate)"
fi
create-github-release:
name: Create GitHub Release
runs-on: [self-hosted, macOS, ARM64]
needs: [build-release, publish-to-crates]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download release assets
uses: actions/download-artifact@v4
with:
name: release-assets
path: ./assets
- name: Generate changelog
id: changelog
run: |
# Get the previous tag for comparison
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
if [ -n "$PREVIOUS_TAG" ]; then
echo "Generating changelog from $PREVIOUS_TAG to ${{ github.ref_name }}"
# Use git log to generate changelog
{
echo "## Changes in ${{ github.ref_name }}"
echo ""
git log --pretty=format:"- %s (%h)" --no-merges $PREVIOUS_TAG..HEAD
} > temp_changelog.md
else
echo "Generating changelog for first release"
{
echo "## Initial Release ${{ github.ref_name }}"
echo ""
echo "- First release of AI Code Buddy"
} > temp_changelog.md
fi
# Output the changelog for the release
{
echo 'changelog<<EOF'
cat temp_changelog.md
echo 'EOF'
} >> $GITHUB_OUTPUT
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: AI Code Buddy v${{ needs.build-release.outputs.version }}
body: |
# AI Code Buddy v${{ needs.build-release.outputs.version }}
${{ steps.changelog.outputs.changelog }}
## Downloads
- **macOS (Apple Silicon)**: `ai-code-buddy-v${{ needs.build-release.outputs.version }}-aarch64-apple-darwin.tar.gz`
## Installation
### Via Cargo
```bash
cargo install ai-code-buddy
```
### Via Binary Download
```bash
# Download the archive
wget https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ai-code-buddy-v${{ needs.build-release.outputs.version }}-aarch64-apple-darwin.tar.gz
# Extract the archive
tar -xzf ai-code-buddy-v${{ needs.build-release.outputs.version }}-aarch64-apple-darwin.tar.gz
# Move to PATH (optional)
sudo mv ai-code-buddy /usr/local/bin/
```
**Verify Installation:**
```bash
ai-code-buddy --version
```
## What's New
For detailed changes, see the [full changelog](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md).
---
**Published to crates.io**: ✅
draft: false
prerelease: false
- name: Upload Release Assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./assets/ai-code-buddy-v${{ needs.build-release.outputs.version }}-aarch64-apple-darwin.tar.gz
asset_name: ai-code-buddy-v${{ needs.build-release.outputs.version }}-aarch64-apple-darwin.tar.gz
asset_content_type: application/gzip
- name: Upload Coverage Report
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./assets/tarpaulin-report.html
asset_name: coverage-report-v${{ needs.build-release.outputs.version }}.html
asset_content_type: text/html