Github Code Review

Ревью PR: диффы, инлайн-комментарии через gh или REST.

Метаданные навыка

ИсточникВстроенный (установлен по умолчанию)
Путьskills/github/github-code-review
Версия1.1.0
АвторHermes Agent
ЛицензияMIT
Платформыlinux, macos, windows
ТегиGitHub, Code-Review, Pull-Requests, Git, Quality
Связанные навыкиgithub-auth, github-pr-workflow

Справочник: полный SKILL.md

инфо

Ниже — полное определение навыка, которое Hermes загружает при его активации. Именно этот текст агент получает как инструкции во время работы.

GitHub Code Review

Проводи ревью локальных изменений до пуша или проверяй открытые PR на GitHub. Большая часть навыка работает на чистом git — разделение на gh/curl важно только для операций уровня PR.

Требования

  • Аутентификация в GitHub (см. навык github-auth)
  • Работа внутри git-репозитория

Настройка (для взаимодействия с PR)

if command -v gh &>/dev/null && gh auth status &>/dev/null; then
  AUTH="gh"
else
  AUTH="git"
  if [ -z "$GITHUB_TOKEN" ]; then
    if [ -f ~/.hermes/.env ] && grep -q "^GITHUB_TOKEN=" ~/.hermes/.env; then
      GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" ~/.hermes/.env | head -1 | cut -d= -f2 | tr -d '\n\r')
    elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then
      GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|')
    fi
  fi
fi

REMOTE_URL=$(git remote get-url origin)
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')
OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)
REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)

1. Ревью локальных изменений (до пуша)

Чистый git — работает везде, API не нужен.

Получить дифф

# Staged-изменения (то, что попадёт в коммит)
git diff --staged

# Все изменения относительно main (то, что войдёт в PR)
git diff main...HEAD

# Только имена файлов
git diff main...HEAD --name-only

# Краткая сводка (вставки/удаления по файлам)
git diff main...HEAD --stat

Стратегия ревью

  1. Сначала общая картина:
git diff main...HEAD --stat
git log main..HEAD --oneline
  1. Файл за файлом — используй read_file для полного контекста и дифф для просмотра изменений:
git diff main...HEAD -- src/auth/login.py
  1. Проверь типичные проблемы:
# Отладочные вызовы, TODO, console.log — всё, что не должно попасть в продакшн
git diff main...HEAD | grep -n "print(\|console\.log\|TODO\|FIXME\|HACK\|XXX\|debugger"

# Случайно добавленные большие файлы
git diff main...HEAD --stat | sort -t'|' -k2 -rn | head -10

# Паттерны секретов и учётных данных
git diff main...HEAD | grep -in "password\|secret\|api_key\|token.*=\|private_key"

# Маркеры конфликтов слияния
git diff main...HEAD | grep -n "<<<<<<\|>>>>>>\|======="
  1. Представь структурированный отчёт пользователю.

Формат вывода ревью

При ревью локальных изменений оформляй вывод в таком виде:

## Code Review Summary

### Critical
- **src/auth.py:45** — SQL injection: user input passed directly to query.
  Suggestion: Use parameterized queries.

### Warnings
- **src/models/user.py:23** — Password stored in plaintext. Use bcrypt or argon2.
- **src/api/routes.py:112** — No rate limiting on login endpoint.

### Suggestions
- **src/utils/helpers.py:8** — Duplicates logic in `src/core/utils.py:34`. Consolidate.
- **tests/test_auth.py** — Missing edge case: expired token test.

### Looks Good
- Clean separation of concerns in the middleware layer
- Good test coverage for the happy path

2. Ревью Pull Request на GitHub

Просмотр деталей PR

Через gh:

gh pr view 123
gh pr diff 123
gh pr diff 123 --name-only

Через git + curl:

PR_NUMBER=123

# Получить детали PR
curl -s \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \
  | python3 -c "
import sys, json
pr = json.load(sys.stdin)
print(f\"Title: {pr['title']}\")
print(f\"Author: {pr['user']['login']}\")
print(f\"Branch: {pr['head']['ref']} -> {pr['base']['ref']}\")
print(f\"State: {pr['state']}\")
print(f\"Body:\n{pr['body']}\")"

# Список изменённых файлов
curl -s \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/files \
  | python3 -c "
import sys, json
for f in json.load(sys.stdin):
    print(f\"{f['status']:10} +{f['additions']:-4} -{f['deletions']:-4}  {f['filename']}\")"

Чекаут PR локально для полного ревью

Работает на чистом gitgh не нужен:

# Забрать ветку PR и переключиться на неё
git fetch origin pull/123/head:pr-123
git checkout pr-123

# Теперь можно использовать read_file, search_files, запускать тесты и т.д.

# Посмотреть дифф относительно базовой ветки
git diff main...pr-123

Через gh (сокращённый вариант):

gh pr checkout 123

Оставить комментарий к PR

Общий комментарий — через gh:

gh pr comment 123 --body "Overall looks good, a few suggestions below."

Общий комментарий — через curl:

curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/issues/$PR_NUMBER/comments \
  -d '{"body": "Overall looks good, a few suggestions below."}'

Инлайн-комментарии к ревью

Одиночный инлайн-комментарий — через gh (через API):

HEAD_SHA=$(gh pr view 123 --json headRefOid --jq '.headRefOid')

gh api repos/$OWNER/$REPO/pulls/123/comments \
  --method POST \
  -f body="This could be simplified with a list comprehension." \
  -f path="src/auth/login.py" \
  -f commit_id="$HEAD_SHA" \
  -f line=45 \
  -f side="RIGHT"

Одиночный инлайн-комментарий — через curl:

# Получить SHA head-коммита
HEAD_SHA=$(curl -s \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")

curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments \
  -d "{
    \"body\": \"This could be simplified with a list comprehension.\",
    \"path\": \"src/auth/login.py\",
    \"commit_id\": \"$HEAD_SHA\",
    \"line\": 45,
    \"side\": \"RIGHT\"
  }"

Формальное ревью (Approve / Request Changes)

Через gh:

gh pr review 123 --approve --body "LGTM!"
gh pr review 123 --request-changes --body "See inline comments."
gh pr review 123 --comment --body "Some suggestions, nothing blocking."

Через curl — атомарное ревью с несколькими инлайн-комментариями:

HEAD_SHA=$(curl -s \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")

curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews \
  -d "{
    \"commit_id\": \"$HEAD_SHA\",
    \"event\": \"COMMENT\",
    \"body\": \"Code review from Hermes Agent\",
    \"comments\": [
      {\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"Use parameterized queries to prevent SQL injection.\"},
      {\"path\": \"src/models/user.py\", \"line\": 23, \"body\": \"Hash passwords with bcrypt before storing.\"},
      {\"path\": \"tests/test_auth.py\", \"line\": 1, \"body\": \"Add test for expired token edge case.\"}
    ]
  }"

Допустимые значения event: "APPROVE", "REQUEST_CHANGES", "COMMENT"

Поле line указывает номер строки в новой версии файла. Для удалённых строк используй "side": "LEFT".


3. Чеклист ревью

При ревью — локального или PR — проверяй по категориям:

Корректность

  • Код делает то, что от него ожидается?
  • Обработаны граничные случаи (пустые входные данные, null-значения, большие объёмы, параллельный доступ)?
  • Ошибочные пути обрабатываются корректно?

Безопасность

  • Никаких захардкоженных секретов, учётных данных, API-ключей
  • Валидация пользовательского ввода
  • Нет SQL-инъекций, XSS, path traversal
  • Там, где нужно, есть проверки аутентификации/авторизации

Качество кода

  • Понятные имена (переменных, функций, классов)
  • Без лишней сложности и преждевременных абстракций
  • DRY — дублирующаяся логика вынесена
  • Функции сфокусированы (принцип единственной ответственности)

Тестирование

  • Новые ветки кода покрыты тестами?
  • Охвачены и happy path, и ошибочные случаи?
  • Тесты читаемы и поддерживаемы?

Производительность

  • Нет N+1 запросов и лишних циклов
  • Кэширование применяется там, где оправдано
  • Нет блокирующих операций в асинхронном коде

Документация

  • Публичные API задокументированы
  • Нетривиальная логика снабжена комментариями с объяснением «почему»
  • README обновлён, если поведение изменилось

4. Рабочий процесс: ревью перед пушем

Когда пользователь просит «посмотреть код» или «проверить перед пушем»:

  1. git diff main...HEAD --stat — оцени объём изменений
  2. git diff main...HEAD — прочитай полный дифф
  3. Для каждого изменённого файла при необходимости используй read_file для более широкого контекста
  4. Пройдись по чеклисту выше
  5. Представь результаты в структурированном формате (Critical / Warnings / Suggestions / Looks Good)
  6. Если найдены критические проблемы — предложи исправить их до пуша

5. Рабочий процесс: ревью PR (сквозной)

Когда пользователь просит «посмотреть PR #N», «проверить этот PR» или даёт ссылку на PR, следуй этому порядку:

Шаг 1: Настроить окружение

source "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/gh-env.sh"
# Или выполнить блок инициализации из начала этого навыка

Шаг 2: Собрать контекст PR

Получи метаданные, описание и список изменённых файлов — сначала разберись с масштабом, потом углубляйся в код.

Через gh:

gh pr view 123
gh pr diff 123 --name-only
gh pr checks 123

Через curl:

PR_NUMBER=123

# Детали PR (заголовок, автор, описание, ветка)
curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER

# Изменённые файлы с количеством строк
curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER/files

Шаг 3: Забрать PR локально

Это даёт полный доступ к read_file, search_files и возможность запускать тесты.

git fetch origin pull/$PR_NUMBER/head:pr-$PR_NUMBER
git checkout pr-$PR_NUMBER

Шаг 4: Прочитать дифф и разобраться в изменениях

# Полный дифф относительно базовой ветки
git diff main...HEAD

# Или файл за файлом для больших PR
git diff main...HEAD --name-only
# Затем для каждого файла:
git diff main...HEAD -- path/to/file.py

Для каждого изменённого файла используй read_file — дифф в одиночку может не показать проблем, которые видны только в контексте окружающего кода.

Шаг 5: Запустить автоматические проверки локально (если применимо)

# Запустить тесты, если есть тест-сьют
python -m pytest 2>&1 | tail -20
# или: npm test, cargo test, go test ./..., и т.п.

# Запустить линтер, если настроен
ruff check . 2>&1 | head -30
# или: eslint, clippy, и т.п.

Шаг 6: Применить чеклист ревью (раздел 3)

Пройдись по каждой категории: Корректность, Безопасность, Качество кода, Тестирование, Производительность, Документация.

Шаг 7: Опубликовать ревью на GitHub

Собери замечания и отправь их как формальное ревью с инлайн-комментариями.

Через gh:

# Если проблем нет — одобрить
gh pr review $PR_NUMBER --approve --body "Reviewed by Hermes Agent. Code looks clean — good test coverage, no security concerns."

# Если есть замечания — запросить изменения с инлайн-комментариями
gh pr review $PR_NUMBER --request-changes --body "Found a few issues — see inline comments."

Через curl — атомарное ревью с несколькими инлайн-комментариями:

HEAD_SHA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")

# Сформировать JSON ревью — event: APPROVE, REQUEST_CHANGES или COMMENT
curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER/reviews \
  -d "{
    \"commit_id\": \"$HEAD_SHA\",
    \"event\": \"REQUEST_CHANGES\",
    \"body\": \"## Hermes Agent Review\n\nFound 2 issues, 1 suggestion. See inline comments.\",
    \"comments\": [
      {\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"🔴 **Critical:** User input passed directly to SQL query — use parameterized queries.\"},
      {\"path\": \"src/models.py\", \"line\": 23, \"body\": \"⚠️ **Warning:** Password stored without hashing.\"},
      {\"path\": \"src/utils.py\", \"line\": 8, \"body\": \"💡 **Suggestion:** This duplicates logic in core/utils.py:34.\"}
    ]
  }"

Шаг 8: Опубликовать сводный комментарий

Помимо инлайн-комментариев, оставь общий комментарий верхнего уровня — автор PR должен видеть полную картину с первого взгляда. Используй шаблон из references/review-output-template.md.

Через gh:

gh pr comment $PR_NUMBER --body "$(cat <<'EOF'
## Code Review Summary

**Verdict: Changes Requested** (2 issues, 1 suggestion)

### 🔴 Critical
- **src/auth.py:45** — SQL injection vulnerability

### ⚠️ Warnings
- **src/models.py:23** — Plaintext password storage

### 💡 Suggestions
- **src/utils.py:8** — Duplicated logic, consider consolidating

### ✅ Looks Good
- Clean API design
- Good error handling in the middleware layer

---
*Reviewed by Hermes Agent*
EOF
)"

Шаг 9: Очистка

git checkout main
git branch -D pr-$PR_NUMBER

Решение: Approve / Request Changes / Comment

  • Approve — нет критических или предупреждающих замечаний, только незначительные предложения или всё чисто
  • Request Changes — есть критические или предупреждающие проблемы, которые нужно исправить до слияния
  • Comment — наблюдения и предложения без блокеров (используй, если не уверен или PR в статусе draft)
ESC