Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CI/CD Integration

Integrate whogitit with your CI/CD pipeline to automatically add AI attribution summaries to pull requests.

GitHub Action

Basic Setup

Create .github/workflows/ai-attribution.yml:

name: AI Attribution Summary

on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  contents: read
  pull-requests: write

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: ${{ github.event.pull_request.head.sha }}

      - name: Fetch git notes
        run: |
          git fetch origin refs/notes/whogitit:refs/notes/whogitit || true
        continue-on-error: true

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-whogitit-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-whogitit-

      - name: Install whogitit
        run: |
          if ! command -v whogitit &> /dev/null; then
            cargo install --git https://github.com/dotsetlabs/whogitit
          fi

      - name: Generate summary
        id: summary
        run: |
          BASE_SHA="${{ github.event.pull_request.base.sha }}"

          # Generate markdown summary
          SUMMARY=$(whogitit summary --base "$BASE_SHA" --format markdown 2>/dev/null || echo "")

          if [ -n "$SUMMARY" ]; then
            # Save to file for the comment step
            echo "$SUMMARY" > attribution-summary.md
            echo "has_attribution=true" >> $GITHUB_OUTPUT
          else
            echo "has_attribution=false" >> $GITHUB_OUTPUT
          fi

      - name: Comment on PR
        if: steps.summary.outputs.has_attribution == 'true'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const summary = fs.readFileSync('attribution-summary.md', 'utf8');

            // Find existing comment
            const { data: comments } = await github.rest.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
            });

            const botComment = comments.find(c =>
              c.user.type === 'Bot' &&
              c.body.includes('AI Attribution Summary')
            );

            const body = `${summary}\n\n---\n*Generated by [whogitit](https://github.com/dotsetlabs/whogitit)*`;

            if (botComment) {
              await github.rest.issues.updateComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                comment_id: botComment.id,
                body: body
              });
            } else {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.issue.number,
                body: body
              });
            }

Example PR Comment

The action posts a comment like:


🤖 AI Attribution Summary

This PR adds +200 lines with AI attribution across 3 files.

Additions Breakdown

MetricLines% of Additions
🟢 AI-generated+14572.5%
🟡 AI-modified by human+126.0%
🔵 Human-written+4321.5%
Total additions+200100%

AI involvement: 78.5% of additions are AI-generated

Files Changed

File+AddedAIHumanAI %Status
src/auth.rs+8072890%New
src/main.rs+45321371%Modified
src/jwt.rs+75532271%New

Commits with AI Attribution

CommitMessageAIModifiedHumanFiles
abc1234Add user authentication72352
def5678Implement JWT tokens859262

Prompts Used (2)

Add user authentication with bcrypt password hashing...
Add user authentication with bcrypt password hashing. Create a User struct
with email and password_hash fields. Implement register and login functions
that return Result types.

Caching Strategy

The workflow caches:

  • Cargo registry and indices
  • Compiled binaries
  • whogitit itself

This significantly speeds up subsequent runs.

Handling Missing Notes

Git notes may not exist if:

  • The contributor didn’t push notes
  • Notes haven’t been fetched yet
  • The commits have no AI attribution

The workflow handles this gracefully:

- name: Fetch git notes
  run: git fetch origin refs/notes/whogitit:refs/notes/whogitit || true
  continue-on-error: true

Branch Protection

Consider adding AI attribution requirements:

# In a separate check job
- name: Check AI disclosure
  run: |
    AI_PERCENT=$(whogitit summary --base main --format json | jq '.ai_percentage')
    if (( $(echo "$AI_PERCENT > 80" | bc -l) )); then
      echo "::warning::This PR has >80% AI-generated code. Ensure thorough review."
    fi

GitLab CI

For GitLab, create .gitlab-ci.yml:

ai-attribution:
  stage: review
  image: rust:latest
  only:
    - merge_requests
  before_script:
    - cargo install --git https://github.com/dotsetlabs/whogitit
    - git fetch origin refs/notes/whogitit:refs/notes/whogitit || true
  script:
    - |
      SUMMARY=$(whogitit summary --base $CI_MERGE_REQUEST_TARGET_BRANCH_NAME --format markdown)
      if [ -n "$SUMMARY" ]; then
        echo "$SUMMARY" > attribution.md
        # Post to MR via GitLab API
      fi
  artifacts:
    paths:
      - attribution.md

Jenkins

For Jenkins pipelines:

pipeline {
    agent any
    stages {
        stage('AI Attribution') {
            when {
                changeRequest()
            }
            steps {
                sh '''
                    git fetch origin refs/notes/whogitit:refs/notes/whogitit || true
                    whogitit summary --base origin/main --format markdown > attribution.md
                '''
                script {
                    def summary = readFile('attribution.md')
                    if (summary.trim()) {
                        // Post comment via GitHub/GitLab API
                    }
                }
            }
        }
    }
}

Custom Integrations

Slack Notification

#!/bin/bash
SUMMARY=$(whogitit summary --base main --format json)
AI_PERCENT=$(echo "$SUMMARY" | jq '.ai_percentage')

if (( $(echo "$AI_PERCENT > 50" | bc -l) )); then
  curl -X POST "$SLACK_WEBHOOK" \
    -H 'Content-type: application/json' \
    -d "{\"text\": \"PR #$PR_NUMBER has ${AI_PERCENT}% AI-generated code\"}"
fi

Export for Analytics

# In CI, export attribution data for each release
whogitit export \
  --since "$LAST_RELEASE_DATE" \
  --format json \
  -o "attribution-$VERSION.json"

# Upload to S3 or analytics platform
aws s3 cp "attribution-$VERSION.json" "s3://metrics/ai-attribution/"

See Also