🔄

AI-агент в GitHub Actions: CI/CD с интеллектом

Интеграция AI в пайплайны GitHub Actions: авто-ревью кода через Claude API, генерация описаний PR, умные тесты и автоматическая документация.

advanced ⏱ 18 мин
AI-агент в GitHub Actions CI/CD пайплайне 📥 Pull Request opened / sync Workflow Trigger pull_request_target + paths filter 🧠 Code Review AI Claude API diff-анализ 📝 PR Description Авто-генерация описания 🧪 Smart Tests Генерация + анализ 💬 PR Comment Review suggestions + labels + summary reaction "request changes" → новый коммит → re-run GitHub Context: { pull_request, issue, comment, labels, files_changed } Secrets: ANTHROPIC_API_KEY, OPENAI_API_KEY, GITHUB_TOKEN

# 1. Базовый workflow: триггер и checkout

Создаём workflow-файл в .github/workflows/. Используем pull_request_target для доступа к секретам (нужен для API-ключей). Фильтруем по путям — AI-анализ запускается только при изменении кода в src/ и tests/. Настраиваем права GITHUB_TOKEN.

# .github/workflows/ai-review.yml
name: AI Code Review & Smart CI

on:
  pull_request_target:
    types: [opened, synchronize, reopened]
    paths:
      - 'src/**'
      - 'tests/**'
      - '*.py'
      - '*.ts'

permissions:
  contents: read
  pull-requests: write
  issues: write

jobs:
  ai-review:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    env:
      ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0
    

# 2. Получение diff и отправка Claude

В следующем шаге получаем git diff между базовой веткой и PR. Передаём его Claude с промптом на ревью. Модель анализирует изменения и возвращает структурированный отчёт с замечаниями, предложениями и оценкой безопасности.

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: pip install anthropic PyGithub

      - name: AI Code Review
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          BASE_REF: ${{ github.event.pull_request.base.sha }}
        run: python scripts/ai_review.py
    

# 3. Python-скрипт: AI-ревью с комментариями в PR

Сам скрипт ai_review.py получает diff, отправляет Claude, парсит ответ и публикует комментарии прямо в PR через GitHub API. Для каждого найденного замечания создаётся отдельный thread с указанием файла и строки.

# scripts/ai_review.py
import os, json, subprocess
from anthropic import Anthropic
from github import Github

# Получаем diff между базовой веткой и PR
diff = subprocess.run(
    ["git", "diff", os.environ["BASE_REF"]],
    capture_output=True, text=True
).stdout

# Если diff слишком большой — обрезаем до первых 15000 символов
if len(diff) > 15000:
    diff = diff[:15000] + "\n... (обрезано)"

# Отправляем Claude на ревью
client = Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=2048,
    system="Ты — senior code reviewer. Найди баги, уязвимости, "
           "нарушения best practices. Ответь JSON-массивом замечаний.",
    messages=[{
        "role": "user",
        "content": f"Проревьюируй этот diff:\n{diff}"
    }]
)

# Парсим ответ и публикуем комментарии в PR
review_data = json.loads(response.content[0].text)
gh = Github(os.environ["GITHUB_TOKEN"])
repo = gh.get_repo(os.environ["GITHUB_REPOSITORY"])
pr = repo.get_pull(int(os.environ["PR_NUMBER"]))

for item in review_data:
    pr.create_issue_comment(
        f"🤖 **AI Review:** {item['severity']} — {item['message']}\n"
        f"📁 `{item.get('file', 'N/A')}:{item.get('line', '?')}`\n"
        f"💡 {item.get('suggestion', '')}"
    )

print(f"✅ Опубликовано {len(review_data)} замечаний")
    

# 4. Авто-генерация описания PR

Второй job в workflow — генерация читаемого описания PR. Анализируем список изменённых файлов и сообщения коммитов, отправляем Claude и обновляем тело PR через API. Это экономит разработчикам время на документирование изменений.

# scripts/generate_pr_description.py
import os, subprocess, json
from anthropic import Anthropic
from github import Github

# Собираем контекст: изменённые файлы + коммиты
files_changed = subprocess.run(
    ["git", "diff", "--name-only", os.environ["BASE_REF"]],
    capture_output=True, text=True
).stdout

commits = subprocess.run(
    ["git", "log", "--oneline", f"{os.environ['BASE_REF']}..HEAD"],
    capture_output=True, text=True
).stdout

client = Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    system="Сгенерируй описание Pull Request на русском. Формат: заголовок, описание, список изменений, как тестировать.",
    messages=[{"role": "user", "content": 
        f"Изменённые файлы:\n{files_changed}\n\nКоммиты:\n{commits}"
    }]
)

description = response.content[0].text
gh = Github(os.environ["GITHUB_TOKEN"])
repo = gh.get_repo(os.environ["GITHUB_REPOSITORY"])
pr = repo.get_pull(int(os.environ["PR_NUMBER"]))

current_body = pr.body or ""
pr.edit(body=f"{current_body}\n\n---\n🤖 **AI-Generated Summary:**\n{description}")
print("✅ PR описание обновлено")
    

# 5. Умная генерация тестов

AI анализирует изменённый код и автоматически генерирует релевантные тесты. Система определяет, какие функции изменились, и создаёт юнит-тесты с граничными случаями. Результат добавляется комментарием в PR для ручного ревью перед мержем.

# scripts/generate_tests.py
import os, subprocess, re
from anthropic import Anthropic
from github import Github

# Получаем все изменённые .py файлы
changed_files = subprocess.run(
    ["git", "diff", "--name-only", os.environ["BASE_REF"], "--", "*.py"],
    capture_output=True, text=True
).stdout.strip().split("\n")

client = Anthropic()
all_tests = []

for filepath in changed_files:
    if not filepath or "test_" in filepath:
        continue

    with open(filepath) as f:
        source = f.read()

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=2048,
        system="Сгенерируй pytest-тесты для этого кода. Включи граничные случаи и mock-объекты. Выведи только код.",
        messages=[{"role": "user", "content": source}]
    )

    test_code = response.content[0].text
    all_tests.append(f"### 🧪 Tests for `{filepath}`\n```python\n{test_code}\n```")

# Публикуем в PR
gh = Github(os.environ["GITHUB_TOKEN"])
repo = gh.get_repo(os.environ["GITHUB_REPOSITORY"])
pr = repo.get_pull(int(os.environ["PR_NUMBER"]))
pr.create_issue_comment("## 🤖 AI-Generated Tests\n\n" + "\n\n".join(all_tests))
    
✅ Итог

Интеграция AI в GitHub Actions превращает пайплайн из пассивного исполнителя в активного участника разработки. Автоматическое ревью ловит баги до того, как их заметят люди. Генерация описаний PR и тестов экономит часы рутинной работы. Ключевое преимущество — agent работает асинхронно и не блокирует разработчика. Достаточно добавить API-ключ в Secrets репозитория и workflow-файл в .github/workflows.

🔗 Полезные ссылки

📖 GitHub Actions Docs 🤖 Claude API 🐙 PyGithub