name: Continuous integration

on:
  push:
    branches:
      - main
      - master
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  check-release:
    name: Check release
    runs-on: ubuntu-latest
    permissions:
      contents: write
      issues: write
      pull-requests: write
    outputs:
      new-release: ${{ steps.release.outputs.new_release }}
      version: ${{ steps.build-version.outputs.version }}
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
        with:
          fetch-depth: 0
      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
        with:
          node-version: lts/*
      - run: npm install
      - name: Release
        id: release
        if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release
      - name: Build version
        id: build-version
        run: echo "version=${BUILD_VERSION}" >> "$GITHUB_OUTPUT"
        env:
          BUILD_VERSION: ${{ steps.release.outputs.new_release == 'true' && steps.release.outputs.version || format('0.0.{0}', github.run_id) }}

  check:
    name: Check
    runs-on: ubuntu-latest
    needs: [check-release]
    strategy:
      matrix:
        rust:
          - stable
          - 1.88.0
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: ${{ matrix.rust }}
      - run: cargo check

  test:
    name: Test Suite
    runs-on: ubuntu-latest
    needs: [check-release]
    strategy:
      matrix:
        rust:
          - stable
          - 1.88.0
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: ${{ matrix.rust }}
      - run: cargo test

  fmt:
    name: Rustfmt
    runs-on: ubuntu-latest
    needs: [check-release]
    strategy:
      matrix:
        rust:
          - stable
          - 1.88.0
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: ${{ matrix.rust }}
          components: rustfmt
      - run: cargo fmt --all -- --check

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    needs: [check-release]
    strategy:
      matrix:
        rust:
          - stable
          - 1.88.0
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: ${{ matrix.rust }}
          components: clippy
      - run: cargo clippy -- -D warnings

  tarpaulin:
    name: Tarpaulin
    runs-on: ubuntu-latest
    needs: [check-release]
    strategy:
      matrix:
        rust:
          - stable
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: ${{ matrix.rust }}
      - run: cargo install cargo-tarpaulin
      - run: cargo tarpaulin --out xml
      - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ./cobertura.xml
          verbose: true

  msrv:
    name: Verify msrv
    runs-on: ubuntu-latest
    needs: [check-release]
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        with:
          toolchain: stable
      - run: |
          cargo install cargo-msrv
          cargo msrv verify

  publish:
    runs-on: ubuntu-latest
    needs:
      - check-release
      - check
      - test
      - fmt
      - clippy
      - tarpaulin
      - msrv
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
      - name: Set version
        run: python3 prepare.py "${{ needs.check-release.outputs.version }}"
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
      - name: Publish to crates.io
        run: cargo publish --allow-dirty
        if: needs.check-release.outputs.new-release == 'true'
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.PUBLISH_SECRET }}
      - name: Dry-run publish
        run: cargo publish --allow-dirty --dry-run
        if: needs.check-release.outputs.new-release != 'true'

  success:
    # Success stage for RequireStatus check.
    name: Success
    runs-on: ubuntu-latest
    needs: [publish]
    steps:
      - name: Success
        run: echo "CI completed successfully!"
