api-version 0.3.8

Axum middleware to add a version prefix to request paths based on a set of versions and an optional `x-api-version` header
Documentation
name: CI

permissions:
  contents: read

on:
  pull_request:
    branches:
      - main
  push:
    branches:
      - main
    tags:
      - v*
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  single-commit:
    name: Enforce single commit
    runs-on: ubuntu-latest
    steps:
      - name: Enforce exactly one commit for a PR
        if: github.event_name == 'pull_request'
        run: |
          COUNT="${{ github.event.pull_request.commits }}"
          echo "PR contains $COUNT commit(s)"
          if [ "$COUNT" -ne 1 ]; then
            echo "::error::PRs must contain exactly one commit. Squash locally (git rebase -i) and force-push."
            exit 1
          fi

  toolchain:
    name: Setup Rust toolchain
    runs-on: ubuntu-latest
    needs: single-commit
    outputs:
      stable: ${{ steps.set_toolchain.outputs.stable }}
      nightly: ${{ steps.set_toolchain.outputs.nightly }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

      - name: Output toolchain
        id: set_toolchain
        run: |
          stable=$(grep channel rust-toolchain.toml | sed -r 's/channel = "(.*)"/\1/')
          echo "stable=$stable" | tee -a "$GITHUB_OUTPUT"
          nightly=$(rustc --version | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' | sed 's/^/nightly-/')
          echo "nightly=$nightly" | tee -a "$GITHUB_OUTPUT"

  fmt-check:
    name: Check Code Format
    runs-on: ubuntu-latest
    needs: toolchain
    steps:
      - name: Checkout repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
        with:
          toolchain: ${{ needs.toolchain.outputs.nightly }}
          components: rustfmt

      - name: Install just
        uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
        with:
          tool: just

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: just fmt-check
        run: |
          just fmt-check

  lint:
    name: Lint Code
    runs-on: ubuntu-latest
    needs: toolchain
    steps:
      - name: Checkout repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
        with:
          toolchain: ${{ needs.toolchain.outputs.stable }}
          components: clippy

      - name: Install just
        uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
        with:
          tool: just

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: just lint
        run: |
          rustup override set ${{ needs.toolchain.outputs.stable }}
          just lint

  test:
    name: Run Tests
    runs-on: ubuntu-latest
    needs: toolchain
    steps:
      - name: Checkout repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
        with:
          toolchain: ${{ needs.toolchain.outputs.stable }}

      - name: Install just
        uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
        with:
          tool: just

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: just test
        run: |
          rustup override set ${{ needs.toolchain.outputs.stable }}
          just test

  doc:
    name: Create Documentation
    runs-on: ubuntu-latest
    needs: toolchain
    steps:
      - name: Checkout repository
        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
        with:
          toolchain: ${{ needs.toolchain.outputs.stable }}
          components: rust-docs

      - name: Install just
        uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
        with:
          tool: just

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: just doc
        run: |
          rustup override set ${{ needs.toolchain.outputs.stable }}
          just doc