canact 0.1.1

Probe an LLM and return host policy: max tools, edit format, XML fallback, JSON repair
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 launch surfaces
        env:
          GH_TOKEN: ${{ github.token }}
        run: bash scripts/assert-launch.sh canact/canact

  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@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
        with:
          toolchain: "1.85"
          components: rustfmt, clippy
      - uses: taiki-e/install-action@5bf6ce016fd2e72eefc647cbca1e4213f65955b8 # 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
      - run: cargo clippy --locked --all-targets -- -D warnings
      - run: cargo clippy --locked --all-targets --features runtime -- -D warnings
      - run: cargo clippy --locked --all-targets --features cli -- -D warnings
      - run: bash scripts/deny-check.sh
      - run: python3 scripts/test_fossa_filter.py
      - run: python3 scripts/test_update_scoop_manifest.py

  test:
    name: Test
    runs-on: ubuntu-latest
    timeout-minutes: 20
    permissions:
      contents: read
      checks: write
    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@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
        with:
          toolchain: "1.85"
      - uses: taiki-e/install-action@5bf6ce016fd2e72eefc647cbca1e4213f65955b8 # v2
        with:
          tool: cargo-nextest@0.9.140
      - 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
        run: |
          set -euo pipefail
          out="${CARGO_TARGET_DIR}/junit"
          mkdir -p "$out"
          # nextest writes junit.xml under workspace target/nextest, not CARGO_TARGET_DIR
          cargo nextest run --locked --profile ci
          cp target/nextest/ci/junit.xml "${out}/default.xml"
          cargo nextest run --locked --features runtime --profile ci
          cp target/nextest/ci/junit.xml "${out}/runtime.xml"
          cargo nextest run --locked --features cli --profile ci
          cp target/nextest/ci/junit.xml "${out}/cli.xml"
      - run: cargo test --locked --doc
      - name: Test summary
        if: always()
        uses: test-summary/action@37b508cfee6d4d080eedd00b5bb240a6a784a6a5 # v2.6
        with:
          paths: target/ci-test/junit/*.xml
          show: all

  fuzz:
    name: Fuzz smoke
    runs-on: ubuntu-latest
    timeout-minutes: 20
    env:
      CARGO_TARGET_DIR: target/ci-fuzz
    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@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
        with:
          toolchain: nightly
      - uses: taiki-e/install-action@5bf6ce016fd2e72eefc647cbca1e4213f65955b8 # v2
        with:
          tool: cargo-fuzz
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
        with:
          workspaces: |
            .
            fuzz
          shared-key: fuzz
          cache-on-failure: true
          save-if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'workflow_dispatch' }}
      - name: Build fuzz targets
        env:
          RUSTUP_TOOLCHAIN: nightly
        run: cargo fuzz build --target x86_64-unknown-linux-gnu
      - name: Smoke-run fuzz targets
        env:
          RUSTUP_TOOLCHAIN: nightly
        run: |
          cargo fuzz run fuzz_cache_json --target x86_64-unknown-linux-gnu -- -max_total_time=5
          cargo fuzz run fuzz_endpoint --target x86_64-unknown-linux-gnu -- -max_total_time=5
          cargo fuzz run fuzz_host_policy --target x86_64-unknown-linux-gnu -- -max_total_time=5

  workflow-sanity:
    name: Workflow sanity
    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: zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99 # v0.6.3
        with:
          inputs: .github/workflows
          min-severity: high
          version: "1.30.0"
          advanced-security: "false"
          online-audits: "false"