on:
  push:
    branches:
      - main
  pull_request:

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

jobs:
  test:
    name: OTP ${{matrix.pair.otp}} / Elixir ${{matrix.pair.elixir}}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - pair:
              elixir: "1.15.0"
              otp: "24.3.4.10"
              benchmark: false
          - pair:
              elixir: "1.18.2"
              otp: "27.2.2"
              benchmark: true
    env:
      MIX_ENV: test
    steps:
      - uses: actions/checkout@v4

      - name: Install Erlang & Elixir
        uses: erlef/setup-beam@v1
        with:
          otp-version: ${{matrix.pair.otp}}
          elixir-version: ${{matrix.pair.elixir}}

      - name: Cache mix dependencies
        uses: actions/cache@v3
        with:
          path: |
            deps
            _build
          key: ${{ runner.os }}-mix-${{ matrix.pair.elixir }}-${{ matrix.pair.otp }}-${{ hashFiles('**/mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-mix-${{ matrix.pair.elixir }}-${{ matrix.pair.otp }}-

      # Cache key based on Erlang/Elixir version and the mix.lock hash
      - name: Restore PLT cache
        id: plt_cache
        uses: actions/cache/restore@v3
        with:
          key: |
            plt-${{ runner.os }}-${{ matrix.pair.otp }}-${{ matrix.pair.elixir }}-${{ hashFiles('**/mix.lock') }}
          restore-keys: |
            plt-${{ runner.os }}-${{ matrix.pair.otp }}-${{ matrix.pair.elixir }}-
          path: |
            priv/plts

      - name: Install mix dependencies
        run: mix deps.get

      - name: Run dialyzer
        run: mix dialyzer --format github

      # Create PLTs if no cache was found
      - name: Create PLTs
        if: steps.plt_cache.outputs.cache-hit != 'true'
        run: mix dialyzer --plt

      # By default, the GitHub Cache action will only save the cache if all steps in the job succeed,
      # so we separate the cache restore and save steps in case running dialyzer fails.
      - name: Save PLT cache
        id: plt_cache_save
        uses: actions/cache/save@v3
        if: steps.plt_cache.outputs.cache-hit != 'true'
        with:
          key: |
            plt-${{ runner.os }}-${{ matrix.pair.otp }}-${{ matrix.pair.elixir }}-${{ hashFiles('**/mix.lock') }}
          path: |
            priv/plts

      - name: Check formatting
        run: mix format --check-formatted

      - name: Check warnings
        run: mix compile --warnings-as-errors

      - name: Run tests
        run: mix test --warnings-as-errors --include slow:true --include benchmark:true
        if: ${{ matrix.pair.benchmark }}

      - name: Run tests
        run: mix test --warnings-as-errors --include slow:true
        if: ${{ ! matrix.pair.benchmark }}

      - name: Check docs
        run: mix doctor
