name: CI
on:
  pull_request:
  merge_group:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - name: stable linux
            os: ubuntu-latest
            rust: stable
            target: x86_64-unknown-linux-gnu
          - name: beta linux
            os: ubuntu-latest
            rust: beta
            target: x86_64-unknown-linux-gnu
          - name: nightly linux
            os: ubuntu-latest
            rust: nightly
            target: x86_64-unknown-linux-gnu
          - name: stable x86_64-unknown-linux-musl
            os: ubuntu-22.04
            rust: stable
            target: x86_64-unknown-linux-musl
          - name: stable x86_64 macos
            os: macos-latest
            rust: stable
            target: x86_64-apple-darwin
          - name: stable aarch64 macos
            os: macos-latest
            rust: stable
            target: aarch64-apple-darwin
          - name: stable windows-msvc
            os: windows-latest
            rust: stable
            target: x86_64-pc-windows-msvc
          - name: msrv
            os: ubuntu-22.04
            # sync MSRV with docs: guide/src/guide/installation.md and Cargo.toml
            rust: 1.88.0
            target: x86_64-unknown-linux-gnu
    name: ${{ matrix.name }}
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
    - name: Install Rust
      run: bash ci/install-rust.sh ${{ matrix.rust }} ${{ matrix.target }}
    - name: Build and run tests
      run: cargo test --workspace --locked --target ${{ matrix.target }}
    - name: Test no default
      run: cargo test --workspace --no-default-features --target ${{ matrix.target }}

  aarch64-cross-builds:
    runs-on: ubuntu-22.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
    - name: Install Rust
      run: bash ci/install-rust.sh stable aarch64-unknown-linux-musl
    - name: Build
      run: cargo build --locked --target aarch64-unknown-linux-musl

  rustfmt:
    name: Rustfmt
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
    - name: Install Rust
      run: rustup update stable && rustup default stable && rustup component add rustfmt
    - run: cargo fmt --check

  gui:
    name: GUI tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
      - name: Install Rust
        run: bash ci/install-rust.sh stable x86_64-unknown-linux-gnu
      - name: Install npm
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e  # v6.4.0
        with:
          node-version: 24
      - name: Install browser-ui-test
        run: npm install
      - name: Run eslint
        run: npm run lint
      - name: Build and run tests (+ GUI)
        run: cargo test --locked --target x86_64-unknown-linux-gnu --test gui

  # Ensure there are no clippy warnings
  clippy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
      - name: Install Rust
        run: bash ci/install-rust.sh stable x86_64-unknown-linux-gnu
      - run: rustup component add clippy
      - run: cargo clippy --workspace --all-targets --no-deps -- -D warnings

  docs:
    name: Check API docs
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
      - name: Install Rust
        run: bash ci/install-rust.sh stable x86_64-unknown-linux-gnu
      - name: Ensure intradoc links are valid
        run: cargo doc --workspace --document-private-items --no-deps
        env:
          RUSTDOCFLAGS: -D warnings

  check-version-bump:
    name: Check version bump
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
      - run: rustup update stable && rustup default stable
      - name: Install cargo-semver-checks
        run: |
          mkdir installed-bins
          curl -Lf https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.47.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz \
            | tar -xz --directory=./installed-bins
          echo `pwd`/installed-bins >> $GITHUB_PATH
      - run: cargo semver-checks --workspace

  # The success job is here to consolidate the total success/failure state of
  # all other jobs. This job is then included in the GitHub branch protection
  # rule which prevents merges unless all other jobs are passing. This makes
  # it easier to manage the list of jobs via this yml file and to prevent
  # accidentally adding new jobs without also updating the branch protections.
  success:
    name: Success gate
    if: always()
    needs:
      - test
      - rustfmt
      - aarch64-cross-builds
      - gui
      - clippy
      - docs
      - check-version-bump
    runs-on: ubuntu-latest
    steps:
      - run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
      - name: Done
        run: exit 0
