CI/CD Integrations Guide

Complete guide for integrating ai-slop-gate into your CI/CD pipelines.


Quick Reference

Platform

Status

GitHub Actions

Full Support

GitLab CI

Full Support


Before You Start

--policy is required for every run command

policy.yml controls which directories are sent to providers via include_paths. Without it, LLM providers receive the entire repository and fail with token-limit errors.

Policy discovery order:

  1. --policy <explicit path> β€” always wins

  2. <--path>/policy.yml β€” auto-discovered if the scanned repo has its own policy

  3. ./policy.yml β€” current working directory

  4. Bundled default (permissive, no include_paths β€” not safe for LLM providers)

Recommendation: every repository you scan should have its own minimal policy.yml (see the Minimal Policy section below).

Enforcement levels

Flag

Behaviour

When to use

--enforcement advisory

Findings reported, CI always passes

Initial rollout, noise tuning

--enforcement blocking

CI fails on violations

Production gate

--enforcement never

Report only, exit 0 always

Dry-run / debugging

Start with advisory. Switch to blocking once the baseline is clean.


Minimal Policy for a Target Repository

Place this policy.yml in the root of the repository you want to scan. The gate will auto-discover it when you pass --path pointing to that repository.

# policy.yml β€” minimal config for the scanned repository
version: "v1.4"
project_name: "my-project"

enforcement: advisory   # start here; tighten to blocking after tuning

# Required for LLM providers.
# Without include_paths, the entire repo is sent to the API β†’ token limit errors.
include_paths:
  - src   # adjust to your source directory

ai_provider:
  name: groq
  models:
    groq: llama-3.3-70b-versatile

compliance:
  enabled: false

rules:
  - id: block-hardcoded-secrets
    when:
      signal: "hardcoded_.*"
    then:
      action: blocking
      message: "Hardcoded secret detected."

Supported Providers

Provider

API key required

Mode

static / static_pipeline

No

Deterministic β€” secrets, Dockerfile, PII, supply-chain

groq

SLOPE_GATE_GROQ

LLM β€” PR diff or --llm-local

gemini

GEMINI_API_KEY

LLM β€” PR diff or --llm-local

ollama

No (local)

LLM β€” local only, 100% private

LLM providers in --llm-local mode automatically exclude: .env, policy.yml, docs/, scripts/, lock files, minified bundles.


GitHub Actions


Minimal Static-Only Workflow

Fast gate with no API keys required:

name: Static Analysis
on: [pull_request]

jobs:
  static:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip
      - run: pip install -e .
      - run: |
          python -m ai_slop_gate.cli run \
            --provider static \
            --policy policy.yml \
            --enforcement advisory

GitHub PR Comment (All-in-One)

name: PR Analysis
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  pr-comment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip
      - run: pip install -e .

      - name: Analyze PR and Post Comment
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GROQ_API_KEY: ${{ secrets.SLOPE_GATE_GROQ }}
        run: |
          python -m ai_slop_gate.cli run \
            --provider groq \
            --github-repo ${{ github.repository }} \
            --pr-id ${{ github.event.pull_request.number }} \
            --policy policy.yml \
            --enforcement advisory

--github-repo, --pr-id, and GITHUB_TOKEN are all required together for PR commenting. In PR mode the LLM receives only the diff β€” include_paths guard is skipped.


GitHub Secrets Setup

Go to Settings β†’ Secrets and variables β†’ Actions and add:

Secret

Description

SLOPE_GATE_GROQ

Groq API key

GEMINI_API_KEY

Google Gemini API key (if using Gemini)

GITHUB_TOKEN

Auto-provided by GitHub β€” no setup needed


GitLab CI


GitLab Variables Setup

Go to Settings β†’ CI/CD β†’ Variables and add (protected + masked):

Variable

Description

GROQ_API_KEY

Groq API key

GEMINI_API_KEY

Google Gemini API key (if using Gemini)

GITLAB_TOKEN

GitLab access token with api scope


Advanced Patterns

Progressive Enforcement

Run advisory on feature branches, blocking on main:

- name: Run Analysis
  run: |
    ENFORCEMENT="advisory"
    if [ "${{ github.ref }}" = "refs/heads/main" ]; then
      ENFORCEMENT="blocking"
    fi
    python -m ai_slop_gate.cli run \
      --provider static \
      --policy policy.yml \
      --enforcement $ENFORCEMENT

Matrix Strategy (Multiple Providers in Parallel)

jobs:
  analyze:
    strategy:
      fail-fast: false
      matrix:
        provider: [static, groq]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip
      - run: pip install -e .

      - name: Cache (LLM only)
        if: matrix.provider != 'static'
        uses: actions/cache@v3
        with:
          path: .ai-slop-cache
          key: llm-cache-${{ matrix.provider }}-${{ hashFiles('**/*.py') }}

      - name: Run ${{ matrix.provider }}
        env:
          GROQ_API_KEY: ${{ secrets.SLOPE_GATE_GROQ }}
        run: |
          EXTRA=""
          if [ "${{ matrix.provider }}" != "static" ]; then
            EXTRA="--llm-local"
          fi
          python -m ai_slop_gate.cli run \
            --provider ${{ matrix.provider }} \
            --policy policy.yml \
            --enforcement advisory \
            $EXTRA

Scheduled Deep Scan (Weekly)

name: Weekly Deep Scan
on:
  schedule:
    - cron: '0 2 * * 1'   # Every Monday at 2 AM

jobs:
  deep-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip
      - run: pip install -e .

      - name: Full Scan (no cache β€” fresh results)
        env:
          GROQ_API_KEY: ${{ secrets.SLOPE_GATE_GROQ }}
        run: |
          python -m ai_slop_gate.cli run \
            --provider static groq \
            --llm-local \
            --compliance \
            --policy policy.yml \
            --no-cache \
            --enforcement advisory \
            --verbose

Best Practices

1. Always include --policy with include_paths

# βœ… GOOD β€” scoped to source directory
python -m ai_slop_gate.cli run --provider groq --llm-local --policy policy.yml

# ❌ BAD β€” entire repo sent to the API, token limit hit
python -m ai_slop_gate.cli run --provider groq --llm-local

2. Start with advisory, tighten later

# Step 1: understand findings
--enforcement advisory

# Step 2: once baseline is clear
--enforcement blocking

3. Always cache LLM responses in CI

- uses: actions/cache@v3
  with:
    path: .ai-slop-cache
    key: llm-cache-${{ hashFiles('**/*.py', '**/*.js') }}
    restore-keys: llm-cache-

4. Use secrets, never inline API keys

# βœ… GOOD
env:
  GROQ_API_KEY: ${{ secrets.SLOPE_GATE_GROQ }}

# ❌ BAD β€” visible in logs and git history
env:
  GROQ_API_KEY: "gsk_actual_key_here"

5. Run static and LLM jobs in parallel

Static analysis is fast (~5s). LLM analysis takes ~15s on first run (cached after). Running them as separate parallel jobs gives faster overall feedback.


Troubleshooting

β€œthe following arguments are required: –policy”

Every run command requires --policy. Add it:

python -m ai_slop_gate.cli run --provider static --policy policy.yml

β€œLLM providers require include_paths”

Your policy.yml is missing include_paths. Add it:

include_paths:
  - src

β€œAPI rate limit exceeded”

Enable cache (default) and avoid --no-cache in CI. Cache persists between runs with actions/cache.

β€œTrivy / Syft binary not found”

Install them explicitly in the workflow before running static analysis:

- name: Install Trivy
  run: |
    curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
      | sh -s -- -b /usr/local/bin v0.69.2

- name: Install Syft
  run: |
    curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \
      | sh -s -- -b /usr/local/bin


Support