name: Publish

on:
  push:
    tags: ['v*']

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  ci:
    name: CI
    runs-on: blacksmith-2vcpu-ubuntu-2404
    steps:
      - uses: actions/checkout@v7

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

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2

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

      - name: Build (all features)
        run: cargo build -p echidna --features "bytecode,taylor,laurent,stde,serde,faer,nalgebra,ndarray,parallel"

      - name: Test echidna
        run: cargo test -p echidna --features "bytecode,taylor,laurent,stde,serde,faer,nalgebra,ndarray,parallel"

      - name: Test echidna-optim
        run: cargo test -p echidna-optim

      - name: Clippy
        run: cargo clippy --features "bytecode,taylor,laurent,stde,serde,faer,nalgebra,ndarray,parallel" -- -D warnings

      - name: Build docs
        run: cargo doc --no-deps --features "bytecode,taylor,laurent,stde,serde,faer,nalgebra,ndarray,parallel"
        env:
          RUSTDOCFLAGS: -D warnings

      - name: Install cargo-deny
        run: cargo install cargo-deny --locked

      - name: Check dependency policies
        run: cargo deny check

  publish-echidna:
    name: Publish echidna
    needs: [ci]
    runs-on: blacksmith-2vcpu-ubuntu-2404
    environment: release
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v7

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

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2

      - name: Validate tag matches Cargo.toml version
        run: |
          TAG="${GITHUB_REF#refs/tags/v}"
          VERSION=$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "echidna") | .version')
          echo "Tag version: $TAG"
          echo "Cargo.toml version: $VERSION"
          if [ "$TAG" != "$VERSION" ]; then
            echo "ERROR: Tag v$TAG does not match Cargo.toml version $VERSION"
            exit 1
          fi

      - name: Dry run
        run: cargo publish -p echidna --dry-run

      - name: Authenticate with crates.io
        id: crates-io-auth
        uses: rust-lang/crates-io-auth-action@v1

      - name: Publish echidna
        run: cargo publish -p echidna
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }}

  publish-optim:
    name: Publish echidna-optim
    needs: [publish-echidna]
    runs-on: blacksmith-2vcpu-ubuntu-2404
    environment: release
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v7

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

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2

      - name: Dry run
        run: cargo publish -p echidna-optim --dry-run

      - name: Authenticate with crates.io
        id: crates-io-auth
        uses: rust-lang/crates-io-auth-action@v1

      - name: Publish echidna-optim
        run: cargo publish -p echidna-optim
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }}

  release:
    name: Create GitHub Release
    needs: [publish-echidna]
    runs-on: blacksmith-2vcpu-ubuntu-2404
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v7

      - name: Extract changelog for this version
        id: changelog
        run: |
          TAG="${GITHUB_REF#refs/tags/v}"
          CHANGELOG=$(awk -v ver="$TAG" '
            /^## \[/ {
              if (found) exit
              if ($0 ~ "\\[" ver "\\]") found=1
              next
            }
            found { print }
          ' CHANGELOG.md)
          if [ -z "$CHANGELOG" ]; then
            CHANGELOG="Release v$TAG"
          fi
          echo "$CHANGELOG" > /tmp/changelog.txt

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v3
        with:
          body_path: /tmp/changelog.txt
          generate_release_notes: false
