yaak 0.0.3

Translate natural language to bash commands using an OpenAI-compatible LLM
name: CI

on:
  push:
    branches: [main]
    tags: ["v*"]
  pull_request:
    branches: [main]

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # ──────────────────────────────────────────────
  # Lint: formatting + clippy
  # ──────────────────────────────────────────────
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - uses: Swatinem/rust-cache@v2

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

  # ──────────────────────────────────────────────
  # Test: unit + integration tests
  # ──────────────────────────────────────────────
  test:
    name: Test (${{ matrix.os }})
    needs: lint
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Run tests
        run: cargo test --all-features --verbose

  # ──────────────────────────────────────────────
  # Build: cross-platform release binaries
  # ──────────────────────────────────────────────
  build:
    name: Build (${{ matrix.target }})
    needs: test
    if: startsWith(github.ref, 'refs/tags/v')
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
            archive: tar.gz

          # TODO: re-enable once cross-compilation OpenSSL issue is resolved
          # - target: aarch64-unknown-linux-gnu
          #   os: ubuntu-latest
          #   archive: tar.gz

          - 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

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install cross-compilation deps (aarch64-linux)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu
          echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV

      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Build release binary
        run: cargo build --release --target ${{ matrix.target }}

      - name: Get version from tag
        id: version
        shell: bash
        run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Package (unix)
        if: matrix.archive == 'tar.gz'
        shell: bash
        run: |
          STAGING="yaak-${{ steps.version.outputs.version }}-${{ matrix.target }}"
          mkdir "$STAGING"
          cp target/${{ matrix.target }}/release/yaak "$STAGING/"
          cp README.md LICENSE* "$STAGING/" 2>/dev/null || true
          tar czf "$STAGING.tar.gz" "$STAGING"
          echo "ASSET=$STAGING.tar.gz" >> $GITHUB_ENV

      - name: Package (windows)
        if: matrix.archive == 'zip'
        shell: bash
        run: |
          STAGING="yaak-${{ steps.version.outputs.version }}-${{ matrix.target }}"
          mkdir "$STAGING"
          cp target/${{ matrix.target }}/release/yaak.exe "$STAGING/"
          cp README.md LICENSE* "$STAGING/" 2>/dev/null || true
          7z a "$STAGING.zip" "$STAGING"
          echo "ASSET=$STAGING.zip" >> $GITHUB_ENV

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}
          path: ${{ env.ASSET }}

  # ──────────────────────────────────────────────
  # Release: create GitHub release with all binaries
  # ──────────────────────────────────────────────
  release:
    name: Release
    needs: build
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: List artifacts
        run: find artifacts -type f | sort

      - name: Generate checksums
        shell: bash
        run: |
          cd artifacts
          find . -type f \( -name '*.tar.gz' -o -name '*.zip' \) \
            -exec sh -c 'sha256sum "$1" >> ../SHA256SUMS.txt' _ {} \;
          cd ..
          cat SHA256SUMS.txt

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          generate_release_notes: true
          files: |
            artifacts/**/*.tar.gz
            artifacts/**/*.zip
            SHA256SUMS.txt