ai-code-buddy 0.4.20

An AI-powered code review tool with elegant Bevy-based TUI
Documentation
name: Release & Publish

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write
  packages: write

env:
  CARGO_TERM_COLOR: always

jobs:
  # Quality checks before release
  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 artifacts
  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.io
  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
  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