Skip to content

CI Recipes

Pengfei Hu edited this page Apr 26, 2026 · 1 revision

CI Recipes

Patterns for running Agents Shipgate in CI. The default mode is advisory — the action never blocks a PR unless you ask it to.


GitHub Actions

Minimum: advisory PR comment

# .github/workflows/shipgate.yml
name: Agents Shipgate
on: pull_request
permissions:
  contents: read
  pull-requests: write   # only needed for pr_comment
jobs:
  shipgate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ThreeMoonsLab/agents-shipgate@v0.2.0
        with:
          ci_mode: advisory
          pr_comment: 'true'

What you get on every PR:

  • A "Agents Shipgate" comment summarizing critical/high/medium counts and top three findings
  • A workflow artifact agents-shipgate-report with report.md and report.json
  • A markdown step summary in the Actions UI

The job exits 0 regardless of findings.

Strict on critical, advisory on the rest

- uses: ThreeMoonsLab/agents-shipgate@v0.2.0
  with:
    ci_mode: strict
    fail_on: critical
    pr_comment: 'true'

The job exits 20 (which the action surfaces as a job failure) only when at least one unsuppressed critical finding exists. Suppressed findings never fail CI.

Strict on critical and high, with baseline diff

For repos that already have known findings they're choosing not to fix yet, save a baseline once and fail only on new findings:

agents-shipgate baseline save -c shipgate.yaml \
  --out .agents-shipgate/baseline.json
git add .agents-shipgate/baseline.json && git commit -m "Baseline shipgate findings"
- uses: ThreeMoonsLab/agents-shipgate@v0.2.0
  with:
    ci_mode: strict
    fail_on: critical,high
    baseline: .agents-shipgate/baseline.json

See Baseline Workflow for the full pattern.

Multi-config workspace scan

If your monorepo has several shipgate.yaml files (one per agent), the action accepts a workspace root:

- uses: ThreeMoonsLab/agents-shipgate@v0.2.0
  with:
    config: '**/shipgate.yaml'
    ci_mode: advisory

Or invoke the CLI directly for richer control:

      - run: pipx install agents-shipgate==0.2.0
      - run: |
          agents-shipgate scan \
            --workspace . \
            --out agents-shipgate-reports \
            --ci-mode strict --fail-on critical

If one manifest has a parse error, the rest still scan; the highest exit code wins.

Pinning the version

For reproducible CI, pin both the action and the underlying CLI version:

- uses: ThreeMoonsLab/agents-shipgate@v0.2.0
  with:
    shipgate_version: '0.2.0'   # forces the action to install this exact PyPI version

When shipgate_version is empty, the action installs the CLI from the action source — convenient on @main, less reproducible.


GitLab CI

# .gitlab-ci.yml
shipgate:
  image: python:3.12-slim
  stage: review
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - pip install --quiet agents-shipgate==0.2.0
    - agents-shipgate scan -c shipgate.yaml --ci-mode advisory
  artifacts:
    when: always
    expire_in: 30 days
    paths:
      - agents-shipgate-reports/

For strict gates, switch to --ci-mode strict --fail-on critical,high and let the nonzero exit fail the job.


CircleCI

# .circleci/config.yml
version: 2.1
jobs:
  shipgate:
    docker:
      - image: cimg/python:3.12
    steps:
      - checkout
      - run: pip install --quiet agents-shipgate==0.2.0
      - run: agents-shipgate scan -c shipgate.yaml --ci-mode advisory
      - store_artifacts:
          path: agents-shipgate-reports
workflows:
  pr:
    jobs:
      - shipgate

Jenkins (declarative)

pipeline {
  agent { docker { image 'python:3.12-slim' } }
  stages {
    stage('Shipgate') {
      steps {
        sh 'pip install --quiet agents-shipgate==0.2.0'
        sh 'agents-shipgate scan -c shipgate.yaml --ci-mode advisory'
      }
      post {
        always {
          archiveArtifacts artifacts: 'agents-shipgate-reports/**', fingerprint: true
        }
      }
    }
  }
}

Rolling out strict mode

Going from "informational" to "blocking" without surprising the team:

  1. Land the workflow in advisory mode. Watch PR comments for a sprint or two. Tune risk_overrides and checks.ignore based on real false positives. Open issues for the rest.
  2. Save a baseline. agents-shipgate baseline save — captures everything currently active. Commit it.
  3. Switch to ci_mode: strict with the baseline applied. Now CI only fails on net-new findings. Existing findings stay in the report but don't block.
  4. Pick severity thresholds incrementally. Start with fail_on: critical. Move to [critical, high] after one or two rounds of cleanup.
  5. Sunset the baseline when the active list is small enough to fix. Delete .agents-shipgate/baseline.json and let strict mode see all findings directly.

This is the same pattern that's worked for code linters — the goal is to never surprise a contributor with an unrelated failure on their PR.


Reading the action outputs

The action exposes these outputs you can wire into downstream steps:

Output Example Notes
status release_blockers_detected One of release_blockers_detected, warnings_detected, human_review_recommended, no_release_blockers_detected
critical_count 2 Unsuppressed only
high_count 13
medium_count 1
baseline_new_count 0 When a baseline is applied
report_json agents-shipgate-reports/report.json Path
report_markdown agents-shipgate-reports/report.md Path
exit_code 20 Exact CLI exit code, even on advisory runs

Example: post a Slack alert only when criticals appeared:

      - id: scan
        uses: ThreeMoonsLab/agents-shipgate@v0.2.0
      - if: steps.scan.outputs.critical_count != '0'
        run: |
          curl -X POST -H 'Content-type: application/json' \
            -d "{\"text\":\"Shipgate criticals on ${{ github.event.pull_request.html_url }}\"}" \
            ${{ secrets.SLACK_WEBHOOK }}

Clone this wiki locally