feat: Add review events persistence, version display, and auto-versioning system
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
# ✨ Новые возможности ревью
|
||||
|
||||
## 🎯 Что добавлено
|
||||
|
||||
### 1. **Inline комментарии в PR** 💬
|
||||
|
||||
Теперь комментарии публикуются **на конкретных строках кода**!
|
||||
|
||||
**Было:**
|
||||
- Один общий комментарий в PR
|
||||
|
||||
**Стало:**
|
||||
- Комментарии прямо на проблемных строках
|
||||
- Видно в какой строке какого файла ошибка
|
||||
- Удобнее исправлять
|
||||
|
||||
**Пример в Gitea:**
|
||||
```
|
||||
src/pages/search-character.tsx
|
||||
Строка 58: 'Content-Type': 'shmapplication/json'
|
||||
↑
|
||||
[AI Comment] ❌ ERROR: Опечатка в строке: 'shmapplication/json'
|
||||
должно быть 'application/json'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. **Автоматический статус PR** 🚦
|
||||
|
||||
Агент **сам устанавливает статус** PR в зависимости от найденных проблем:
|
||||
|
||||
- ✅ **APPROVE** - Если проблем не найдено
|
||||
- 💬 **COMMENT** - Если найдены только WARNING/INFO
|
||||
- ❌ **REQUEST_CHANGES** - Если найдены ERROR (критичные проблемы)
|
||||
|
||||
**В Gitea:**
|
||||
```
|
||||
PR Status: Changes Requested ❌
|
||||
AI Code Review: 4 критичные проблемы найдены
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. **Markdown summary** 📄
|
||||
|
||||
Красивый общий комментарий в markdown с:
|
||||
|
||||
#### **Если есть проблемы:**
|
||||
|
||||
```markdown
|
||||
## 🤖 AI Code Review
|
||||
|
||||
### 📊 Статистика
|
||||
|
||||
- **Всего проблем:** 4
|
||||
- ❌ **Критичных:** 4
|
||||
|
||||
### 🔍 Детали
|
||||
|
||||
#### ❌ Критичные проблемы
|
||||
|
||||
- **src/pages/search-character.tsx:58**
|
||||
Опечатка в строке: 'shmapplication/json' должно быть 'application/json'
|
||||
|
||||
- **src/pages/search-character.tsx:104**
|
||||
Незакрытая скобка в JSX: {searchValueError && ( ... }
|
||||
|
||||
### 💡 Рекомендации
|
||||
|
||||
Пожалуйста, исправьте найденные проблемы перед мержем в main.
|
||||
Детальные комментарии оставлены inline на соответствующих строках кода.
|
||||
```
|
||||
|
||||
#### **Если проблем нет:**
|
||||
|
||||
```markdown
|
||||
## 🤖 AI Code Review
|
||||
|
||||
✅ **Отличная работа!** Серьезных проблем не обнаружено.
|
||||
|
||||
Код выглядит хорошо и соответствует стандартам.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. **Фильтрация `<think>` блоков** 🧹
|
||||
|
||||
Если LLM создает блоки `<think>...</think>` (рассуждения), они **автоматически удаляются**:
|
||||
|
||||
**Ответ LLM:**
|
||||
```
|
||||
<think>
|
||||
Сначала проверю синтаксис... затем логику...
|
||||
</think>
|
||||
Опечатка в Content-Type: 'shmapplication/json'
|
||||
```
|
||||
|
||||
**В Gitea видно:**
|
||||
```
|
||||
Опечатка в Content-Type: 'shmapplication/json'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Как это работает
|
||||
|
||||
### 1. Генерация комментариев
|
||||
|
||||
```python
|
||||
# backend/app/agents/reviewer.py
|
||||
|
||||
# Для каждого файла AI генерирует комментарии
|
||||
comments = await analyzer.analyze_diff(
|
||||
file_path=file_path,
|
||||
diff=patch,
|
||||
pr_title=pr_info.get("title"),
|
||||
pr_description=pr_info.get("description")
|
||||
)
|
||||
|
||||
# Результат:
|
||||
[
|
||||
{
|
||||
"file_path": "src/pages/search-character.tsx",
|
||||
"line": 58,
|
||||
"severity": "ERROR",
|
||||
"message": "Опечатка: 'shmapplication/json'"
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
### 2. Генерация summary
|
||||
|
||||
```python
|
||||
# Создаем markdown summary
|
||||
summary = await analyzer.generate_summary(
|
||||
all_comments=db_comments,
|
||||
pr_title=pr_info.get("title"),
|
||||
pr_description=pr_info.get("description")
|
||||
)
|
||||
|
||||
# summary - это markdown текст
|
||||
```
|
||||
|
||||
### 3. Определение статуса
|
||||
|
||||
```python
|
||||
# Если есть ERROR - требуем изменения
|
||||
has_errors = any(c.get('severity') == 'ERROR' for c in comments)
|
||||
event = "REQUEST_CHANGES" if has_errors else "COMMENT"
|
||||
|
||||
# Если вообще проблем нет - approve
|
||||
if not comments:
|
||||
event = "APPROVE"
|
||||
```
|
||||
|
||||
### 4. Публикация в Gitea
|
||||
|
||||
```python
|
||||
# Одним запросом:
|
||||
# - Inline комментарии
|
||||
# - Общий summary
|
||||
# - Статус PR
|
||||
await git_service.create_review(
|
||||
pr_number=pr_number,
|
||||
comments=formatted_comments, # Inline комментарии
|
||||
body=summary, # Markdown summary
|
||||
event=event # APPROVE/COMMENT/REQUEST_CHANGES
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Gitea API
|
||||
|
||||
### Формат запроса:
|
||||
|
||||
```json
|
||||
POST /repos/{owner}/{repo}/pulls/{pr}/reviews
|
||||
|
||||
{
|
||||
"body": "## 🤖 AI Code Review\n...",
|
||||
"commit_id": "abc123...",
|
||||
"event": "REQUEST_CHANGES",
|
||||
"comments": [
|
||||
{
|
||||
"path": "src/pages/search-character.tsx",
|
||||
"body": "**ERROR**: Опечатка...",
|
||||
"new_position": 58
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Поля:
|
||||
|
||||
- **body** - общий markdown комментарий
|
||||
- **commit_id** - SHA последнего коммита
|
||||
- **event** - статус (APPROVE/COMMENT/REQUEST_CHANGES)
|
||||
- **comments** - массив inline комментариев
|
||||
- **path** - путь к файлу
|
||||
- **body** - текст комментария (markdown)
|
||||
- **new_position** - номер строки
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Что видит пользователь в Gitea
|
||||
|
||||
### В списке PR:
|
||||
|
||||
```
|
||||
PR #5: Добавление функционала аватара
|
||||
Status: ❌ Changes Requested
|
||||
Reviews: 🤖 AI Code Review (4 комментария)
|
||||
```
|
||||
|
||||
### В самом PR:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 🤖 AI Code Review │
|
||||
│ Status: ❌ Changes Requested │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ## 🤖 AI Code Review │
|
||||
│ │
|
||||
│ ### 📊 Статистика │
|
||||
│ - Всего проблем: 4 │
|
||||
│ - ❌ Критичных: 4 │
|
||||
│ │
|
||||
│ ### 🔍 Детали │
|
||||
│ ... │
|
||||
└─────────────────────────────────────────┘
|
||||
|
||||
Files Changed (1):
|
||||
|
||||
┌─────────────────────────────────────────┐
|
||||
│ src/pages/search-character.tsx │
|
||||
├─────────────────────────────────────────┤
|
||||
│ 55 | search: searchValue │
|
||||
│ 56 | }), │
|
||||
│ 57 | headers: { │
|
||||
│ 58 | 'Content-Type': 'shmap... │ 👈 [AI Comment]
|
||||
│ │ │ ❌ ERROR: Опечатка
|
||||
│ 59 | } │
|
||||
│ ... | │
|
||||
│ 104 | {searchValueError && ( │ 👈 [AI Comment]
|
||||
│ | │ ❌ ERROR: Незакрытая
|
||||
│ | │ скобка
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Преимущества
|
||||
|
||||
1. **Наглядность** - видно ЧТО и ГДЕ не так
|
||||
2. **Статус PR** - сразу понятно можно ли мержить
|
||||
3. **Markdown** - красивое форматирование
|
||||
4. **Inline** - комментарии прямо на коде
|
||||
5. **Чистота** - `<think>` блоки удаляются
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Как проверить
|
||||
|
||||
1. Запустите ревью на любом PR
|
||||
2. Дождитесь завершения
|
||||
3. Откройте PR в Gitea
|
||||
4. Проверьте:
|
||||
- ✅ Inline комментарии на строках
|
||||
- ✅ Общий markdown summary
|
||||
- ✅ Статус PR (Approved/Changes Requested)
|
||||
- ✅ Красивое форматирование
|
||||
|
||||
---
|
||||
|
||||
## 📝 Измененные файлы
|
||||
|
||||
- `backend/app/agents/reviewer.py`:
|
||||
- Генерация summary
|
||||
- Определение статуса
|
||||
- Фильтрация `<think>` блоков
|
||||
|
||||
- `backend/app/agents/tools.py`:
|
||||
- Метод `generate_summary()`
|
||||
|
||||
- `backend/app/services/gitea.py`:
|
||||
- Параметр `event` в `create_review()`
|
||||
- Детальное логирование
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Готово!
|
||||
|
||||
Теперь ревью полноценное:
|
||||
- ✅ Inline комментарии
|
||||
- ✅ Статус PR
|
||||
- ✅ Markdown summary
|
||||
- ✅ Чистый вывод
|
||||
|
||||
**Попробуйте!** 🎉
|
||||
|
||||
Reference in New Issue
Block a user