name: CI

on:
  push:
    branches:
      - main
  pull_request:
  workflow_dispatch:
  schedule:
    - cron: "11 4 * * 1"

permissions:
  contents: read

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  fmt:
    name: Format
    runs-on: ubuntu-latest
    timeout-minutes: 10

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

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

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

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

  links:
    name: Links
    runs-on: ubuntu-latest
    timeout-minutes: 10

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

      - name: Check documentation and workflow links
        uses: lycheeverse/lychee-action@v2.7.0
        with:
          args: README.md .github/workflows/*.yml
          lycheeVersion: v0.21.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  docs:
    name: Docs
    runs-on: ubuntu-latest
    timeout-minutes: 15

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

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

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

      - name: Build docs
        env:
          RUSTDOCFLAGS: -D warnings
        run: cargo doc --no-deps --all-features --locked

  msrv:
    name: MSRV
    runs-on: ubuntu-latest
    timeout-minutes: 20

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

      - name: Install MSRV toolchain
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: 1.86.0

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

      - name: Check crate with MSRV
        run: cargo +1.86.0 check --all-features --locked

      - name: Test crate with MSRV
        run: cargo +1.86.0 test --all-features --locked --lib --tests

      - name: Test docs with MSRV
        run: cargo +1.86.0 test --all-features --locked --doc

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    timeout-minutes: 20

    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

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

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

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

  test:
    name: Test (${{ matrix.name }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: linux-default
            os: ubuntu-latest
            command: cargo test --locked
          - name: linux-all-features
            os: ubuntu-latest
            command: cargo test --all-features --locked
          - name: linux-native-tls
            os: ubuntu-latest
            command: cargo test --no-default-features --features native-tls --locked
          - name: macos-default
            os: macos-latest
            command: cargo test --locked
          - name: windows-default
            os: windows-latest
            command: cargo test --locked
          - name: windows-native-tls
            os: windows-latest
            command: cargo test --no-default-features --features native-tls --locked

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

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

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

      - name: Run tests
        run: ${{ matrix.command }}

  package:
    name: Package
    runs-on: ubuntu-latest
    timeout-minutes: 15

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

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

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

      - name: Verify publish package
        run: cargo publish --dry-run --locked

  semver:
    name: Semver
    runs-on: ubuntu-latest
    timeout-minutes: 20

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

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

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

      - name: Install cargo-semver-checks
        uses: taiki-e/install-action@cargo-semver-checks

      - name: Resolve semver baseline
        id: semver-baseline
        shell: bash
        run: |
          if [ "${{ github.event_name }}" = "pull_request" ]; then
            git fetch origin "${{ github.base_ref }}" --depth=1
            baseline="$(git merge-base HEAD "origin/${{ github.base_ref }}")"
          elif git rev-parse --verify HEAD^ >/dev/null 2>&1; then
            baseline="$(git rev-parse HEAD^)"
          else
            echo "skip=true" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          echo "skip=false" >> "$GITHUB_OUTPUT"
          echo "rev=$baseline" >> "$GITHUB_OUTPUT"

      - name: Check semver compatibility
        if: ${{ steps.semver-baseline.outputs.skip != 'true' }}
        run: cargo semver-checks check-release --release-type patch --baseline-rev "${{ steps.semver-baseline.outputs.rev }}"

  audit:
    name: Audit
    runs-on: ubuntu-latest
    timeout-minutes: 10

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

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

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

      - name: Install cargo-audit
        uses: taiki-e/install-action@cargo-audit

      - name: Audit dependencies
        run: cargo audit

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
      id-token: write

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

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

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

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

      - name: Check coverage
        run: cargo llvm-cov --all-features --locked --lcov --output-path lcov.info --fail-under-lines 90

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v5
        with:
          files: ./lcov.info
          disable_search: true
          fail_ci_if_error: true
          flags: unittests
          name: figshare-rs
          use_oidc: true
          verbose: true
