Praktische Referenz für die Integration von Claude Code in GitHub Actions Workflows. Setup, Konfiguration, Use Cases, Kosten-Management und Troubleshooting.

Setup & Grundkonfiguration

Installation der Action

Die offizielle Action ist verfügbar im GitHub Marketplace:

# .github/workflows/claude-code-review.yml
name: Claude Code Review

on:
  pull_request:
    types: [opened, synchronize]

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

      - name: Claude Code Review
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 20

Secrets Setup

Die API-Keys müssen in GitHub Secrets gespeichert werden:

# 1. Secrets im Repository hinzufügen
# Settings → Secrets and variables → Actions → New repository secret

# Name: ANTHROPIC_API_KEY
# Value: sk-ant-v1-...

In GitHub UI:

  1. Repository öffnen
  2. Settings → Security → Secrets and variables → Actions
  3. "New repository secret" klicken
  4. Name: ANTHROPIC_API_KEY
  5. Value: API Key von https://console.anthropic.com/account/keys

CLAUDE.md im CI-Context

---
name: Code Review Agent
description: >
  Spezialisiert auf sicherheit, Performance und Wartbarkeit.
  Trigger: code-review, security-check, performance-audit
version: 1.0.0
---

# Code Review für CI/CD

## Kontext

Du arbeitet in GitHub Actions mit begrenztem Context und Timeout von 300 Sekunden.

## Regeln

- Fokus auf: Security, Performance, Best Practices
- Max 5 kritische Probleme pro Review
- Verwende Standard-Report-Format (GH Comments)
- Kein Auto-Approve — nur Feedback

Use Cases

1. Automatischer Code Review auf Pull Requests

name: Auto Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Claude Code Review
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 15
          custom-instructions: |
            Überprüfe diesen PR auf:
            1. Security Vulnerabilities
            2. Performance Issues
            3. Code Style Violations
            4. Missing Tests
            5. API Breaking Changes
          output-format: github-comments

      - name: Post Review as Comment
        if: always()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const review = fs.readFileSync('claude-review.md', 'utf-8');

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: review
            });

2. Automatische PR-Beschreibungen

name: Generate PR Description

on:
  pull_request:
    types: [opened]

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

      - name: Analyse Changes
        id: changes
        run: |
          git diff origin/main..HEAD --stat > /tmp/changes.txt
          echo "changes=$(cat /tmp/changes.txt)" >> $GITHUB_OUTPUT

      - name: Generate Description
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet
          max-turns: 5
          custom-instructions: |
            Erstelle eine aussagekräftige PR-Beschreibung basierend auf:
            - Geänderten Dateien
            - Git Diff
            - Branch Name: ${{ github.head_ref }}

            Format:
            ## Changes
            (Kurze Zusammenfassung)

            ## Testing
            (Wie wurde getestet)

            ## Breaking Changes
            (Falls vorhanden)
          output-format: raw

      - name: Update PR Description
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const description = fs.readFileSync('claude-output.md', 'utf-8');

            github.rest.pulls.update({
              pull_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: description
            });

3. Issue Triage & Auto-Labeling

name: Issue Triage

on:
  issues:
    types: [opened, edited]

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Analyze Issue
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet
          max-turns: 3
          custom-instructions: |
            Analysiere dieses GitHub Issue und gebe folgende Labels zurück:
            - bug / feature / enhancement / documentation
            - priority: critical / high / medium / low
            - complexity: simple / moderate / complex

            Issue Title: ${{ github.event.issue.title }}
            Issue Body: ${{ github.event.issue.body }}

            Output Format (JSON):
            {
              "labels": ["label1", "label2"],
              "priority": "high",
              "suggest_assignee": true
            }
          output-format: json

      - name: Apply Labels
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const labels = JSON.parse(fs.readFileSync('claude-output.json', 'utf-8'));

            github.rest.issues.addLabels({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: labels.labels
            });

4. Test-Generierung aus Code

name: Generate Missing Tests

on:
  pull_request:
    paths:
      - 'src/**/*.ts'
      - 'src/**/*.js'

jobs:
  generate-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Find Untested Functions
        id: untested
        run: |
          # Finde Funktionen ohne Tests
          git diff origin/main..HEAD --name-only --diff-filter=AM | grep -E '\.(ts|js)$' > /tmp/new-files.txt
          echo "files=$(cat /tmp/new-files.txt)" >> $GITHUB_OUTPUT

      - name: Generate Tests
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 10
          custom-instructions: |
            Erstelle Vitest-Tests für folgende Funktionen:
            ${{ steps.untested.outputs.files }}

            Anforderungen:
            - Mindestens 80% Code Coverage
            - Teste Edge Cases
            - Benutze Mocking wo nötig
            - Formatierung: TypeScript/Vitest

          output-format: file
          output-path: test-suggestions.ts

      - name: Create Test Suggestion Comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const tests = fs.readFileSync('test-suggestions.ts', 'utf-8');

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '## Suggested Tests\n\n```typescript\n' + tests + '\n```'
            });

5. Security Scanning & Vulnerability Detection

name: Security Scan

on:
  pull_request:
  push:
    branches: [main, develop]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Scan for Security Issues
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 20
          custom-instructions: |
            Überprüfe diesen Code auf Security Issues:
            1. SQL Injection Vulnerabilities
            2. XSS/HTML Injection
            3. Authentication Bypass
            4. Exposed API Keys/Secrets
            5. Deserialization Vulnerabilities
            6. CSRF Issues
            7. Weak Cryptography
            8. Path Traversal Bugs

            Format: Markdown mit Severity Level (CRITICAL, HIGH, MEDIUM, LOW)
          output-format: github-comments

      - name: Fail on Critical Issues
        if: failure()
        run: |
          echo "::error::Critical security issues found!"
          exit 1

6. Changelog & Release Notes Generator

name: Generate Changelog

on:
  push:
    tags:
      - 'v*'

jobs:
  changelog:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get Changes
        id: changes
        run: |
          git log $(git describe --tags --abbrev=0)..HEAD --oneline > /tmp/commits.txt
          echo "commits=$(cat /tmp/commits.txt)" >> $GITHUB_OUTPUT

      - name: Generate Changelog
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet
          max-turns: 5
          custom-instructions: |
            Erstelle Changelog/Release Notes aus diesen Commits:
            ${{ steps.changes.outputs.commits }}

            Format (Markdown):
            ## Features
            - Item 1
            - Item 2

            ## Bug Fixes
            - Fix 1

            ## Breaking Changes
            - If any

            ## Upgrade Guide
            - Step 1
            - Step 2
          output-format: raw

      - name: Create Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          body_path: claude-output.md
          draft: false
          prerelease: false

Konfigurationsoptionen

Action Input Parameter

with:
  # Required
  api-key: ${{ secrets.ANTHROPIC_API_KEY }}

  # Optional - Default: claude-opus
  model: claude-opus | claude-sonnet | claude-haiku

  # Optional - Default: 20
  max-turns: 10

  # Optional - Zusätzliche Anweisungen
  custom-instructions: |
    Mach X, Y, Z

  # Optional - Default: raw
  output-format: raw | json | github-comments | file

  # Optional - Für file output
  output-path: ./results.md

  # Optional - Timeout in Sekunden (default: 600)
  timeout: 300

  # Optional - Temperature (0.0 - 1.0)
  temperature: 0.7

Model Auswahl nach Task

Task Empfehlung Grund
Code Review opus Komplexe Analyse
Test Generation opus Umfangreiche Coverage
PR Description sonnet Schnell + ausreichend
Issue Triage haiku Einfache Kategorisierung
Security Scan opus Gründliche Analyse
Simple Linting haiku Schnell + kostengünstig

Kosten-Management

Cost Optimization Strategy

name: Cost-Optimized Workflow

on:
  pull_request:
    types: [opened, synchronize]

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

      # Stage 1: Quick check mit Haiku (cheap)
      - name: Quick Lint Check
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-haiku
          max-turns: 3
          timeout: 60

      # Stage 2: Full review mit Sonnet nur wenn Flag gesetzt
      - name: Full Code Review
        if: contains(github.event.pull_request.labels.*.name, 'needs-full-review')
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 15
          timeout: 300

      # Stage 3: Security scan nur auf main/protected branches
      - name: Security Scan
        if: github.ref == 'refs/heads/main'
        uses: anthropics/claude-code-action@v1
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-opus
          max-turns: 20

Token Budgeting

# Python script für Budget-Tracking
import json
import os
from datetime import datetime

def track_token_usage(run_id, model, tokens_used):
    """Track Claude API token usage per workflow run"""
    budget_file = "/tmp/claude-budget.json"

    # Model pricing (Stand März 2026)
    pricing = {
        "claude-opus": {"input": 0.015, "output": 0.075},
        "claude-sonnet": {"input": 0.003, "output": 0.015},
        "claude-haiku": {"input": 0.00080, "output": 0.004}
    }

    entry = {
        "timestamp": datetime.now().isoformat(),
        "run_id": run_id,
        "model": model,
        "tokens_used": tokens_used,
        "cost_usd": (tokens_used * pricing[model]["input"]) / 1000
    }

    # Append to log
    if os.path.exists(budget_file):
        with open(budget_file, 'r') as f:
            budget = json.load(f)
    else:
        budget = []

    budget.append(entry)

    with open(budget_file, 'w') as f:
        json.dump(budget, f)

    # Weekly summary
    weekly_cost = sum(e["cost_usd"] for e in budget
                      if (datetime.now() - datetime.fromisoformat(e["timestamp"])).days < 7)

    print(f"Weekly cost: ${weekly_cost:.2f}")

Fehlerbehandlung

Common Issues & Fixes

1. API Key Not Found

# Problem: secret nicht gesetzt
# Lösung: GitHub Secrets prüfen

- name: Debug Secret
  run: |
    if [ -z "${{ secrets.ANTHROPIC_API_KEY }}" ]; then
      echo "ERROR: ANTHROPIC_API_KEY not set"
      exit 1
    fi
    echo "API Key configured"

2. Timeout

# Problem: Workflow überschreitet Zeit
# Lösung: max-turns reduzieren oder timeout erhöhen

- name: Claude Code Action
  uses: anthropics/claude-code-action@v1
  with:
    api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    max-turns: 5          # Reduce from 20
    timeout: 120          # Increase from 60

3. Context Size Exceeded

# Problem: PR ist zu groß für ein Call
# Lösung: Auf spezifische Files filtern

- name: Review Only Changed Files
  uses: anthropics/claude-code-action@v1
  with:
    api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    custom-instructions: |
      Überprüfe nur diese Dateien:
      - ${{ steps.files.outputs.changed }}

Best Practices

1. Caching für häufige Analysen

- name: Cache Analysis Results
  uses: actions/cache@v3
  with:
    path: ./analysis-cache
    key: claude-analysis-${{ hashFiles('src/**') }}

2. Parallel Reviews bei großen PRs

strategy:
  matrix:
    chunk: [1, 2, 3]
steps:
  - name: Review Chunk ${{ matrix.chunk }}
    uses: anthropics/claude-code-action@v1

3. Notifications bei kritischen Issues

- name: Notify on Critical Issues
  if: contains(env.REVIEW_RESULT, 'CRITICAL')
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.addLabels({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        labels: ['security-issue', 'needs-attention']
      });