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 = `## 🤖 AI Attribution Summary\n\n${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 contains 3 of 5 commits with AI-assisted changes.

Overview

MetricLinesPercentage
🟢 AI-generated14558.0%
🟡 AI-modified by human124.8%
🔵 Human-added4317.2%
⚪ Original/unchanged5020.0%
Total250100%

AI involvement: 62.8% of changed lines

Commits with AI Attribution

CommitMessageAIModifiedHumanFiles
abc1234Add user authentication453102
def5678Implement JWT tokens1009333

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 '.summary.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 '.summary.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