github-actions-maintainer 0.6.3

General-purpose GitHub Actions maintenance toolkit with secure workflow pinning
Documentation
name: CI

on:
  push:
    branches: [main, dev]
    paths-ignore:
      - "**.md"
      - "LICENSE"
      - ".gitignore"
      - "docs/**"
  pull_request:
    branches: [main, dev]
    paths-ignore:
      - "**.md"
      - "LICENSE"
      - ".gitignore"
      - "docs/**"
  schedule:
    - cron: "0 0 * * 0"
  workflow_dispatch:

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1
  RUSTFLAGS: -D warnings
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  RUSTUP_MAX_RETRIES: 10
  RUST_STABLE_VERSION: 1.97.1

jobs:
  quick-check:
    name: Quick Check
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ env.RUST_STABLE_VERSION }}
          components: rustfmt, clippy

      - name: Cache cargo
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry/index
            ~/.cargo/registry/cache
            ~/.cargo/git/db
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Check bootstrap placeholders
        run: python3 scripts/check_template_placeholders.py

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

      - name: Run clippy
        run: |
          cargo clippy --all-features --all-targets -- \
            -D warnings \
            -D clippy::all \
            -D clippy::pedantic \
            -D clippy::nursery \
            -A clippy::multiple_crate_versions \
            -A clippy::module_name_repetitions \
            -A clippy::missing_errors_doc \
            -A clippy::missing_panics_doc \
            -A clippy::must_use_candidate

  test:
    name: Test (${{ matrix.os }} / ${{ matrix.rust }})
    needs: quick-check
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: linux
            runner: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
            rust: stable
          - os: linux
            runner: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
            rust: beta
          - os: linux
            runner: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
            rust: nightly
          - os: macos
            runner: ${{ vars.RUST_TEMPLATE_RUNNER_MACOS || 'macos-latest' }}
            rust: stable
          - os: windows
            runner: ${{ vars.RUST_TEMPLATE_RUNNER_WINDOWS || 'windows-latest' }}
            rust: stable
    continue-on-error: ${{ matrix.rust == 'nightly' }}

    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ matrix.rust }}

      - name: Install dependencies (Ubuntu)
        if: matrix.os == 'linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y libssl-dev pkg-config

      - name: Install dependencies (macOS)
        if: matrix.os == 'macos'
        run: |
          brew install openssl@3
          echo "OPENSSL_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV

      - name: Cache cargo
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry/index
            ~/.cargo/registry/cache
            ~/.cargo/git/db
            target
          key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.rust }}-cargo-

      - name: Build
        run: cargo build --all-features --verbose

      - name: Run tests
        run: cargo test --all-features --verbose

      - name: Run doc tests
        run: cargo test --doc --all-features

  msrv:
    name: MSRV Check
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install MSRV toolchain
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ env.RUST_STABLE_VERSION }}

      - name: Cache cargo
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry/index
            ~/.cargo/registry/cache
            ~/.cargo/git/db
          key: ${{ runner.os }}-msrv-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Check MSRV
        run: cargo check --workspace --all-features

  features:
    name: Feature Checks
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    needs: quick-check
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ env.RUST_STABLE_VERSION }}

      - name: Install cargo-hack
        uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2.85.8
        with:
          tool: cargo-hack

      - name: Cache cargo
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry/index
            ~/.cargo/registry/cache
            ~/.cargo/git/db
            target
          key: ${{ runner.os }}-features-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Check no default features
        run: cargo check --workspace --no-default-features

      - name: Check all features
        run: cargo check --workspace --all-features

      - name: Check feature combinations
        run: cargo hack check --workspace --feature-powerset --no-dev-deps

  docs:
    name: Documentation
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    needs: quick-check
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ env.RUST_STABLE_VERSION }}

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

      - name: Test documentation examples
        run: cargo test --doc --all-features

  bench:
    name: Benchmarks
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    needs: quick-check
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: ${{ env.RUST_STABLE_VERSION }}

      - name: Check benchmarks compile
        run: cargo bench --all-features --no-run

  action-smoke:
    name: Action Smoke (${{ matrix.command }})
    runs-on: ${{ vars.RUST_TEMPLATE_RUNNER_UBUNTU || 'ubuntu-latest' }}
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        command: [pin, update, status, release]

    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      # Exercises the action wiring (inputs, args, INPUT_* environment) against
      # whatever binary the runtime/Dockerfile pin currently holds. Every
      # command runs with --dry-run, so read-only contents permission is
      # enough; the token only raises the API rate limit for the commands that
      # query GitHub.
      - name: Run the local action
        uses: ./
        with:
          command: ${{ matrix.command }}
          dry-run: "true"
          all: ${{ matrix.command == 'update' && 'true' || 'false' }}
          token: ${{ secrets.GITHUB_TOKEN }}