pipechecker 0.2.3

CI/CD Pipeline Auditor - Catch errors before you push
Documentation
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  RUST_BACKTRACE: 1
  CARGO_INCREMENTAL: 0
  SCCACHE_VERSION: "0.8.0"

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

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt

      - name: Cache cargo registry
        uses: actions/cache@v4
        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: Clippy
        run: cargo clippy -- -D warnings

      - name: Formatting check
        run: cargo fmt -- --check

  security:
    name: Security
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: security-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: security-cargo-registry-

      - name: Cache cargo-audit binary
        id: cache-cargo-audit
        uses: actions/cache@v4
        with:
          path: ~/.cargo/bin/cargo-audit
          key: cargo-audit-bin-v1

      - name: Install cargo-audit
        if: steps.cache-cargo-audit.outputs.cache-hit != 'true'
        run: cargo install cargo-audit --locked

      - name: Run security audit
        run: cargo audit
        env:
          ADVISORY_DB_CACHE_DIR: /tmp/advisory-db

      - name: Run cargo deny
        uses: EmbarkStudios/cargo-deny-action@v1
        with:
          command: check bans licenses sources
          arguments: --all-features

  docs:
    name: Docs
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: docs-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: docs-cargo-registry-

      - name: Build documentation
        run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: coverage-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: coverage-cargo-registry-

      - name: Cache cargo-tarpaulin binary
        id: cache-tarpaulin
        uses: actions/cache@v4
        with:
          path: ~/.cargo/bin/cargo-tarpaulin
          key: cargo-tarpaulin-bin-v1

      - name: Install cargo-tarpaulin
        if: steps.cache-tarpaulin.outputs.cache-hit != 'true'
        run: cargo install cargo-tarpaulin --locked

      - name: Generate coverage report
        run: |
          cargo tarpaulin \
            --out Json \
            --output-file ./coverage/tarpaulin-report.json \
            --fail-under 60

      - name: Upload coverage reports
        uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: coverage/
        continue-on-error: true

      - name: Generate summary
        run: |
          echo "## Code Coverage" >> $GITHUB_STEP_SUMMARY
          python3 - <<'EOF' >> $GITHUB_STEP_SUMMARY || echo "Coverage report generated" >> $GITHUB_STEP_SUMMARY
          import json
          with open("coverage/tarpaulin-report.json") as f:
              d = json.load(f)
          covered = d.get("covered", 0)
          coverable = d.get("coverable", 1)
          pct = covered / coverable * 100
          print(f"**Coverage: {pct:.1f}%** ({covered}/{coverable} lines)")
          EOF

  # Full matrix — push to main only
  test:
    name: Test (${{ matrix.target }})
    needs: [lint, security, docs]
    if: github.event_name != 'pull_request'
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            sccache-arch: x86_64-unknown-linux-musl

          - os: macos-latest
            target: aarch64-apple-darwin
            sccache-arch: aarch64-apple-darwin

          - os: windows-latest
            target: x86_64-pc-windows-msvc
            sccache-arch: x86_64-pc-windows-msvc

          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            sccache-arch: x86_64-unknown-linux-musl
            use-cross: true

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install sccache (Linux / macOS)
        if: runner.os != 'Windows'
        shell: bash
        run: |
          URL="https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-${{ matrix.sccache-arch }}.tar.gz"
          curl -sSL "$URL" | tar -xz
          mkdir -p "$CARGO_HOME/bin"
          mv "sccache-v${SCCACHE_VERSION}-${{ matrix.sccache-arch }}/sccache" "$CARGO_HOME/bin/"
          chmod +x "$CARGO_HOME/bin/sccache"
          echo "RUSTC_WRAPPER=$CARGO_HOME/bin/sccache" >> "$GITHUB_ENV"
          "$CARGO_HOME/bin/sccache" --start-server

      - name: Install sccache (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          $url = "https://github.com/mozilla/sccache/releases/download/v$env:SCCACHE_VERSION/sccache-v$env:SCCACHE_VERSION-${{ matrix.sccache-arch }}.tar.gz"
          Invoke-WebRequest $url -OutFile sccache.tar.gz
          tar -xzf sccache.tar.gz
          $dest = "$env:CARGO_HOME\bin"
          New-Item -ItemType Directory -Force -Path $dest | Out-Null
          Move-Item "sccache-v$env:SCCACHE_VERSION-${{ matrix.sccache-arch }}\sccache.exe" "$dest\sccache.exe"
          Add-Content $env:GITHUB_ENV "RUSTC_WRAPPER=$dest\sccache.exe"
          & "$dest\sccache.exe" --start-server

      - name: Cache sccache storage
        uses: actions/cache@v4
        with:
          path: |
            ~/.cache/sccache
            ~/AppData/Local/Mozilla/sccache
          key: ${{ runner.os }}-sccache-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-sccache-${{ matrix.target }}-
            ${{ runner.os }}-sccache-

      - name: Cache cargo registry
        uses: actions/cache@v4
        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: Cache build artifacts
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-${{ matrix.target }}-target-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-${{ matrix.target }}-target-

      - name: Cache cross binary
        if: matrix.use-cross == true
        id: cache-cross
        uses: actions/cache@v4
        with:
          path: ~/.cargo/bin/cross
          key: cross-bin-v1

      - name: Install cross
        if: matrix.use-cross == true && steps.cache-cross.outputs.cache-hit != 'true'
        run: cargo install cross --locked

      - name: Build
        shell: bash
        run: |
          if [ "${{ matrix.use-cross }}" = "true" ]; then
            cross build --target ${{ matrix.target }}
          else
            cargo build --target ${{ matrix.target }}
          fi

      - name: Run tests
        shell: bash
        run: |
          if [ "${{ matrix.use-cross }}" = "true" ]; then
            cross test --target ${{ matrix.target }}
          else
            cargo test --target ${{ matrix.target }}
          fi

      - name: Test CLI
        if: matrix.use-cross != true
        shell: bash
        run: |
          cargo run -- -- tests/fixtures/github/valid.yml
          cargo run -- tests/fixtures/github/circular.yml || true

      - name: Print sccache stats
        if: always() && runner.os != 'Windows'
        shell: bash
        run: $CARGO_HOME/bin/sccache --show-stats
        continue-on-error: true

  # Reduced matrix — pull requests only
  test-pr:
    name: Test PR (${{ matrix.target }})
    needs: [lint, security, docs]
    if: github.event_name == 'pull_request'
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            sccache-arch: x86_64-unknown-linux-musl

          - os: macos-latest
            target: aarch64-apple-darwin
            sccache-arch: aarch64-apple-darwin

          - os: windows-latest
            target: x86_64-pc-windows-msvc
            sccache-arch: x86_64-pc-windows-msvc

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install sccache (Linux / macOS)
        if: runner.os != 'Windows'
        shell: bash
        run: |
          URL="https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-${{ matrix.sccache-arch }}.tar.gz"
          curl -sSL "$URL" | tar -xz
          mkdir -p "$CARGO_HOME/bin"
          mv "sccache-v${SCCACHE_VERSION}-${{ matrix.sccache-arch }}/sccache" "$CARGO_HOME/bin/"
          chmod +x "$CARGO_HOME/bin/sccache"
          echo "RUSTC_WRAPPER=$CARGO_HOME/bin/sccache" >> "$GITHUB_ENV"
          "$CARGO_HOME/bin/sccache" --start-server

      - name: Install sccache (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          $url = "https://github.com/mozilla/sccache/releases/download/v$env:SCCACHE_VERSION/sccache-v$env:SCCACHE_VERSION-${{ matrix.sccache-arch }}.tar.gz"
          Invoke-WebRequest $url -OutFile sccache.tar.gz
          tar -xzf sccache.tar.gz
          $dest = "$env:CARGO_HOME\bin"
          New-Item -ItemType Directory -Force -Path $dest | Out-Null
          Move-Item "sccache-v$env:SCCACHE_VERSION-${{ matrix.sccache-arch }}\sccache.exe" "$dest\sccache.exe"
          Add-Content $env:GITHUB_ENV "RUSTC_WRAPPER=$dest\sccache.exe"
          & "$dest\sccache.exe" --start-server

      - name: Cache sccache storage
        uses: actions/cache@v4
        with:
          path: |
            ~/.cache/sccache
            ~/AppData/Local/Mozilla/sccache
          key: ${{ runner.os }}-sccache-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-sccache-${{ matrix.target }}-
            ${{ runner.os }}-sccache-

      - name: Cache cargo registry
        uses: actions/cache@v4
        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: Cache build artifacts
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-${{ matrix.target }}-target-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-${{ matrix.target }}-target-

      - name: Build
        shell: bash
        run: cargo build --target ${{ matrix.target }}

      - name: Run tests
        shell: bash
        run: cargo test --target ${{ matrix.target }}

      - name: Test CLI
        shell: bash
        run: |
          cargo run -- -- tests/fixtures/github/valid.yml
          cargo run -- tests/fixtures/github/circular.yml || true

      - name: Print sccache stats
        if: always() && runner.os != 'Windows'
        shell: bash
        run: $CARGO_HOME/bin/sccache --show-stats
        continue-on-error: true