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

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

name: Build

permissions:
  contents: read

jobs:
  lint:
    runs-on: ubuntu-latest
    name: Lint

    steps:
      - uses: actions/checkout@v6

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

      - name: cargo fmt --check
        run: cargo fmt --check

      - name: cargo-semver-checks
        uses: obi1kenobi/cargo-semver-checks-action@v2
        continue-on-error: true

  clippy:
    runs-on: ubuntu-latest
    name: Clippy (${{ matrix.toolchain }})
    needs: [lint]

    strategy:
      fail-fast: false
      matrix:
        toolchain: [stable, beta]

    steps:
      - uses: actions/checkout@v6

      - name: Install ${{ matrix.toolchain }}
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.toolchain }}
          components: clippy

      - name: cargo clippy
        uses: giraffate/clippy-action@v1
        with:
          reporter: "github-pr-check"
          github_token: ${{ secrets.GITHUB_TOKEN }}

  msrv:
    runs-on: ubuntu-latest
    name: MSRV (${{ matrix.msrv }})
    needs: [lint]

    strategy:
      matrix:
        msrv: ["1.87.0"]

    steps:
      - uses: actions/checkout@v6

      - name: Install ${{ matrix.msrv }}
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.msrv }}

      - name: cargo +${{ matrix.msrv }} check
        run: cargo check

  docs:
    runs-on: ubuntu-latest
    name: Docs (nightly)
    needs: [lint]
    steps:
      - uses: actions/checkout@v6

      - name: Install nightly
        uses: dtolnay/rust-toolchain@nightly

      - name: Install Cargo Docs-rs
        uses: dtolnay/install@cargo-docs-rs

      - name: Install Cargo Rdme
        run: cargo install cargo-rdme

      - name: cargo rdme --check
        run: cargo rdme --check

      - name: Build docs
        run: cargo docs-rs

      - name: cargo doc
        run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: --cfg docsrs

  test:
    name: Tests (${{ matrix.os }} / ${{ matrix.toolchain }})
    runs-on: ${{ matrix.os }}
    needs: [clippy, msrv, docs]

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        toolchain: [stable, beta]

    steps:
      - uses: actions/checkout@v6

      - name: Install ${{ matrix.toolchain }}
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.toolchain }}

      - name: cargo test --locked
        run: cargo test --locked --all-features --all-targets

      - name: cargo test --doc
        run: cargo test --locked --all-features --doc

  minimal:
    runs-on: ubuntu-latest
    name: Test (minimal versions)
    needs: [clippy, msrv, docs]

    steps:
      - uses: actions/checkout@v6

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

      - name: Install nightly for -Zminimal-versions
        uses: dtolnay/rust-toolchain@nightly

      - name: Setup environment variables
        uses: SpicyPizza/create-envfile@v2.0
        with:
          envkey_POOL_ID: ${{ needs.setup.outputs.user_pool_id }}
          envkey_REGION: ${{ env.region }}
          envkey_CLIENT_ID: ${{ needs.setup.outputs.test_user_pool_client_id }}
          envkey_CLIENT_SECRET: ${{ needs.setup.outputs.test_user_pool_client_secret }}
          envkey_USER_EMAIL: ${{ secrets.INTEGRATION_TEST_USER_EMAIL }}
          envkey_USER_PASSWORD: ${{ secrets.INTEGRATION_TEST_USER_PASSWORD }}
          directory: ./
          file_name: .env
          fail_on_empty: false

      - run: rustup default stable

      - name: cargo update -Zdirect-minimal-versions
        run: cargo +nightly update -Zdirect-minimal-versions

      - name: cargo test
        run: cargo test --locked --all-features --all-targets

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    needs: [clippy, msrv, docs]
    steps:
      - uses: actions/checkout@v6

      - name: Install nightly
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: llvm-tools-preview

      - name: cargo install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov

      - run: cargo +nightly llvm-cov --locked --branch --all-features --lcov --output-path lcov_unit.info

      - run: cargo +nightly llvm-cov --locked --branch --doc --all-features --lcov --output-path lcov_docs.info

      - uses: actions/upload-artifact@v7
        with:
          name: coverage
          path: lcov_*.info

      - uses: coverage-robot/action@v1.0.12
        with:
          token: ${{ secrets.COVERAGE_TOKEN }}
          files: |
            lcov_unit.info
          tag: unit-tests
        continue-on-error: true

      - uses: coverage-robot/action@v1.0.12
        with:
          token: ${{ secrets.COVERAGE_TOKEN }}
          files: |
            lcov_docs.info
          tag: doc-tests
        continue-on-error: true

  publish:
    name: Publish Crate
    needs: [test, coverage]
    if: ${{ startsWith(github.ref, 'refs/tags/') }}
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6

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

      - name: Login to crates.io
        run: cargo login ${{ secrets.CRATES_IO_API_TOKEN }}

      - name: Install cargo-release
        run: cargo install cargo-release

      - name: Publish version
        run: cargo release ${GITHUB_REF#refs/tags/v} -vv --no-tag --no-push --allow-branch HEAD --execute --no-confirm
