CI/CD Integration

Automatically scan your code on every push, PR, or release.

Smart Default: Incremental Scanning

By default, Bugrit scans only changed files in your PR or commit. This means:

1-2 credits

per PR instead of 10-20

<30 seconds

scan time for most PRs

No noise

only issues you introduced

Need a full repo scan? Add scanMode: "full" to your request.

🤖 Vibe Coding Prompts

Choose your path and copy the prompt to your AI assistant:

Scan only changed files - fast and cheap

Read the Bugrit CI/CD docs at https://bugrit.com/docs/integrations/ci-cd

Create a GitHub Action that scans ONLY CHANGED FILES on every PR:

1. Trigger on: pull_request to main
2. Get list of changed files: git diff --name-only origin/main...HEAD
3. Count lines in changed files only
4. POST to /api/v1/scans with:
   - scanMode: "incremental" (default, can omit)
   - changedFiles: array of changed file paths
   - estimatedLines: line count of changed files only
5. Poll until scan completes
6. Add PR comment with scan summary
7. FAIL if critical issues found

This uses ~1-2 credits per PR instead of 10-20 for full scan.
Use secrets.BUGRIT_API_KEY and secrets.BUGRIT_APP_ID.

Works with Claude, ChatGPT, Cursor, Copilot, Cody, and other AI coding assistants

💡 Why Incremental by Default?

Full repo scans on every PR are wasteful. You don't need to re-scan 50,000 lines when you only changed 200.

  • Save credits: 1-2 credits per PR vs 10-20 for full scan
  • Faster feedback: Results in 30 seconds, not 2-5 minutes
  • Less noise: Only see issues YOU introduced, not legacy debt
  • Full scans when needed: Use scanMode: "full" for releases

Scan Modes

ModeWhen to UseCredits
incremental (default)Every PR, every commit1-2 credits
fullReleases, weekly audits, new repos10-20 credits

Required Secrets

  • BUGRIT_API_KEY - From Settings → API Keys
  • BUGRIT_APP_ID - From your application dashboard
Configuration Examples

GitHub Actions - Incremental (Recommended)

# .github/workflows/bugrit-pr.yml
name: Bugrit PR Scan

on:
  pull_request:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Need full history for diff

      - name: Get changed files
        id: changed
        run: |
          CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.(ts|tsx|js|jsx|py|go|rs|java)$' || true)
          echo "files<<EOF" >> $GITHUB_OUTPUT
          echo "$CHANGED" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

          if [ -n "$CHANGED" ]; then
            LINES=$(echo "$CHANGED" | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}')
          else
            LINES=0
          fi
          echo "lines=$LINES" >> $GITHUB_OUTPUT

      - name: Trigger Incremental Scan
        if: steps.changed.outputs.lines > 0
        run: |
          # Convert newline-separated files to JSON array
          FILES_JSON=$(echo '${{ steps.changed.outputs.files }}' | jq -R -s -c 'split("\n") | map(select(length > 0))')

          curl -X POST https://bugrit.com/api/v1/scans \
            -H "Authorization: Bearer ${{ secrets.BUGRIT_API_KEY }}" \
            -H "Content-Type: application/json" \
            -d '{
              "applicationId": "'${{ secrets.BUGRIT_APP_ID }}'",
              "sourceType": "github",
              "repoUrl": "https://github.com/'${{ github.repository }}'",
              "branch": "'${{ github.head_ref }}'",
              "scanMode": "incremental",
              "changedFiles": '$FILES_JSON',
              "estimatedLines": '${{ steps.changed.outputs.lines }}'
            }' | tee response.json

          echo "SCAN_ID=$(jq -r '.scan.id' response.json)" >> $GITHUB_ENV

      - name: Wait and Check
        if: steps.changed.outputs.lines > 0
        run: |
          while true; do
            RESULT=$(curl -s -H "Authorization: Bearer ${{ secrets.BUGRIT_API_KEY }}" \
              "https://bugrit.com/api/v1/scans/$SCAN_ID")
            STATUS=$(echo $RESULT | jq -r '.scan.status')
            [ "$STATUS" = "completed" ] && break
            [ "$STATUS" = "failed" ] && exit 1
            sleep 5
          done

          CRITICAL=$(echo $RESULT | jq -r '.scan.summary.critical')
          [ "$CRITICAL" -gt 0 ] && exit 1 || exit 0

GitHub Actions - Full Scan (For Releases)

# .github/workflows/bugrit-release.yml
name: Bugrit Release Scan

on:
  release:
    types: [published]
  schedule:
    - cron: '0 0 * * 0'  # Weekly full audit

jobs:
  full-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Trigger Full Scan
        run: |
          curl -X POST https://bugrit.com/api/v1/scans \
            -H "Authorization: Bearer ${{ secrets.BUGRIT_API_KEY }}" \
            -H "Content-Type: application/json" \
            -d '{
              "applicationId": "'${{ secrets.BUGRIT_APP_ID }}'",
              "sourceType": "github",
              "repoUrl": "https://github.com/'${{ github.repository }}'",
              "branch": "main",
              "scanMode": "full"
            }' | tee response.json

API Request Body

FieldTypeDescription
scanModestring"incremental" (default) or "full"
changedFilesstring[]Array of file paths (for incremental)
estimatedLinesnumberLines in changed files (for billing)
baseBranchstringBranch to diff against (default: main)