snapif 0.1.2

Snapif scores one tool call and returns Auto, Review, or Escalate.
Documentation
name: CI

on:
  pull_request:
  merge_group: {}
  workflow_dispatch: {}

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

permissions:
  contents: read

env:
  CARGO_INCREMENTAL: "0"
  RUSTFLAGS: "-D warnings"

jobs:
  stealth:
    name: Stealth
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Assert stealth surfaces
        env:
          GH_TOKEN: ${{ github.token }}
        run: bash scripts/assert-stealth.sh snapif/snapif

  lint:
    name: Lint
    runs-on: ubuntu-latest
    timeout-minutes: 15
    env:
      CARGO_TARGET_DIR: target/ci-lint
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: "1.95"
          components: rustfmt, clippy
      - uses: taiki-e/install-action@9983c65e42da123ff25d1f78505eb6de315aa172 # v2
        with:
          tool: cargo-deny@0.20.2
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
        with:
          save-if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'workflow_dispatch' }}
      - run: cargo fmt --check
      - name: Full clippy
        if: >-
          github.event_name != 'pull_request' ||
          !startsWith(github.head_ref, 'release-please')
        run: |
          cargo clippy --locked --all-targets -- -D warnings
          cargo clippy --locked --all-targets --features http -- -D warnings
          cargo clippy --locked --all-targets --features cli -- -D warnings
          cargo clippy --locked --all-targets --features http,cli -- -D warnings
      - name: Rustdoc
        if: >-
          github.event_name != 'pull_request' ||
          !startsWith(github.head_ref, 'release-please')
        run: RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps
      - name: Release-please check
        if: >-
          github.event_name == 'pull_request' &&
          startsWith(github.head_ref, 'release-please')
        run: cargo check --locked --all-targets
      - run: cargo deny check
      - run: bash scripts/forbid-deps.sh
      - run: python3 scripts/test_workflow_triggers.py
      - run: python3 scripts/test_forbid_deps.py

  workflows:
    name: Workflows
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12
      - uses: taiki-e/install-action@9983c65e42da123ff25d1f78505eb6de315aa172 # v2
        with:
          tool: zizmor@1.16.0
      - run: zizmor --min-severity=high .github/workflows

  test:
    name: Test
    runs-on: ubuntu-latest
    timeout-minutes: 15
    env:
      CARGO_TARGET_DIR: target/ci-test
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: "1.95"
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
        with:
          save-if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'workflow_dispatch' }}
      - name: Unit and integration tests
        if: >-
          github.event_name != 'pull_request' ||
          !startsWith(github.head_ref, 'release-please')
        run: |
          cargo test --locked
          cargo test --locked --features http
          cargo test --locked --features cli
          cargo test --locked --features http,cli
      - name: Release-please check
        if: >-
          github.event_name == 'pull_request' &&
          startsWith(github.head_ref, 'release-please')
        run: cargo check --locked --all-targets

  gitleaks:
    name: Gitleaks
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
          fetch-depth: 0
      - name: Install gitleaks
        run: |
          set -euo pipefail
          curl -fsSL -o /tmp/gitleaks.tar.gz \
            https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz
          echo "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb  /tmp/gitleaks.tar.gz" | sha256sum -c -
          tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
          /tmp/gitleaks version
      - run: /tmp/gitleaks detect --source . --exit-code 1 --no-banner

  ci:
    name: CI
    needs: [stealth, lint, workflows, test, gitleaks]
    if: always()
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2
        with:
          egress-policy: audit
      - name: All required jobs passed
        env:
          STEALTH: ${{ needs.stealth.result }}
          LINT: ${{ needs.lint.result }}
          WORKFLOWS: ${{ needs.workflows.result }}
          TEST: ${{ needs.test.result }}
          GITLEAKS: ${{ needs.gitleaks.result }}
        run: |
          test "$STEALTH" = success
          test "$LINT" = success
          test "$WORKFLOWS" = success
          test "$TEST" = success
          test "$GITLEAKS" = success