name: Lint & Format (Rust)

on:
    pull_request:

jobs:
    lint-format:
        runs-on: alpine
        container: node:26-alpine
        env:
            CARGO_HOME: ${{ github.workspace }}/.cargo

        steps:
            - name: Checkout
              uses: actions/checkout@v4

            - name: Cache cargo packages
              uses: actions/cache@v4
              env:
                  cache-name: cache-cargo-packages
              with:
                  path: |
                      .cargo/registry
                      .cargo/git
                      target
                  key: rust-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
                  restore-keys: |
                      rust-${{ runner.os }}-build-${{ env.cache-name }}-
                      rust-${{ runner.os }}-build-
                      rust-

            - name: Install tools
              run: |
                  apk add --no-cache \
                    git \
                    cargo \
                    rust \
                    rustfmt \
                    rust-clippy

            - id: format-check
              name: Format check
              continue-on-error: true
              run: |
                  if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
                    status=0
                    for manifest in $(find . -name "Cargo.toml"); do
                      cargo fmt --manifest-path "$manifest" --check && \
                        echo "$manifest: formatting OK" || \
                        { echo "$manifest: needs formatting"; status=1; }
                    done
                    exit $status
                  elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
                    echo "Rust files found but no Cargo.toml"
                    exit 1
                  else
                    echo "No Rust project found"
                  fi

            - id: clippy
              name: Clippy
              run: |
                  if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
                    status=0
                    for manifest in $(find . -name "Cargo.toml"); do
                      cargo clippy --manifest-path "$manifest" --all-targets --all-features -- -D warnings && \
                        echo "$manifest: Clippy passed" || \
                        { echo "$manifest: Clippy failed"; status=1; }
                    done
                    exit $status
                  elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
                    echo "Rust files found but no Cargo.toml"
                    exit 1
                  else
                    echo "No Rust project found"
                  fi

            - name: Check results
              if: always()
              run: |
                  if [ "${{ steps.format-check.outcome }}" = "failure" ] || [ "${{ steps.clippy.outcome }}" = "failure" ]; then
                    echo "One or more checks failed"
                    exit 1
                  fi
                  echo "All checks passed"
