docs: add Gitea integration documentation and createToken method

- Add GiteaClient.createToken() static method for Basic Auth token creation
- Add AccessToken interface with all Gitea 1.21+ fields
- Create docs/GITEA_INTEGRATION.md with complete usage guide
- Document API scopes (all, read:*, write:*)
- Add examples for agents integration

API scopes per Gitea 1.21+:
- 'all' for full access
- 'read:issue', 'write:issue' for issues
- 'read:repository', 'write:repository' for repos
- 'read:milestone', 'write:milestone' for milestones
This commit is contained in:
swp
2026-04-04 01:30:35 +01:00
parent 11a2741f46
commit 2519079e6e
2 changed files with 287 additions and 0 deletions

239
docs/GITEA_INTEGRATION.md Normal file
View File

@@ -0,0 +1,239 @@
# Gitea API Integration
Интеграция с Gitea API 1.21+ для автмоатического управления issues, milestones и логирования работы агентов.
## Установка
```bash
# Установите зависимости
bun install
# Или с npm
npm install
```
## Настройка
### Вариант 1: Токен через окружение
```bash
# Установите переменные окружения
export GITEA_API_URL="https://git.softuniq.eu/api/v1"
export GITEA_TOKEN=аш_токен_здесь"
```
### Вариант 2: Получение токена из логина/пароля
```bash
# Запустите скрипт для создания токена
./scripts/create-gitea-token.sh your_username your_password
# Скрипт выведет:
# export GITEA_TOKEN=abc123...
```
### Вариант 3: Программно через API
```typescript
import { GiteaClient } from './src/kilocode/agent-manager/gitea-client.js'
// Создать токен из логина/пароля
const { token } = await GiteaClient.createToken(
'your_username',
'your_password',
'Pipeline Token',
['all'] // или ['read:issue', 'write:issue', 'read:repository', 'write:repository']
)
// Использовать токен
const client = new GiteaClient({ token })
```
## Использование
### Создание Issues с Milestone
```typescript
import { GiteaClient } from './src/kilocode/agent-manager/gitea-client.js'
const client = new GiteaClient({
apiUrl: 'https://git.softuniq.eu/api/v1',
token: process.env.GITEA_TOKEN
})
client.setRepository('UniqueSoft', 'APAW')
// Создать milestone
const milestone = await client.createMilestone({
title: 'Sprint 1',
description: 'First sprint',
due_on: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString()
})
// Создать issue с milestone
const issue = await client.createIssue({
title: 'Implement authentication',
body: `## Чеклист
- [ ] Дизайн API
- [ ] Реализация
- [ ] Тесты`,
labels: ['status: new'],
milestone: milestone.id
})
// Добавить комментарий
await client.createComment(issue.number, {
body: `## ✅ Прогресс
### Выполнено
- ✅ API спроектирован
- ✅ Начата реализация
### В процессе
- 🔄 Написание тестов`
})
// Изменить статус
await client.setStatus(issue.number, 'implementing')
```
### Логирование производительности агентов
```typescript
import { logAgentPerformance, logPipelineStep } from './src/kilocode/agent-manager/gitea-client.js'
// Логировать шаг пайплайна
await logPipelineStep(client, issueNumber, '@lead-developer', 'started', 'Implementing authentication')
// Логировать результат работы агента
await logAgentPerformance(client, issueNumber, 'lead-developer', 8, 'Clean implementation, good test coverage')
```
### Работа с Labels
```typescript
// Получить все labels репозитория
const labels = await client.getRepoLabels()
// Добавить labels к issue
await client.addLabels(issueNumber, [1, 2, 3]) // по ID
await client.addLabels(issueNumber, ['bug', 'priority:high']) // по имени
// Заменить все labels
await client.replaceLabels(issueNumber, [1, 2])
// Удалить label
await client.removeLabel(issueNumber, 1)
// Установить статус (удаляет старые status: labels)
await client.setStatus(issueNumber, 'implementing')
```
## API Scopes
Gitea использует гранулярные scopes вместо старых `repo`, `issue`:
| Scope | Описание |
|-------|----------|
| `all` | Полный доступ |
| `read:issue` | Чтение issues |
| `write:issue` | Создание/изменение issues |
| `read:repository` | Чтение репозитория |
| `write:repository` | Изменение репозитория |
| `read:milestone` | Чтение milestones |
| `write:milestone` | Создание/изменение milestones |
## Скрипты тестирования
### Создание токена
```bash
./scripts/create-gitea-token.sh username password
```
### Полный тест (токен + milestone + issues + comments)
```bash
./scripts/full-gitea-test.sh username password
```
### Тест с существующим токеном
```bash
export GITEA_TOKEN=your_token
./scripts/test-gitea.sh
```
## Структура ответов API
### Milestone
```json
{
"id": 42,
"title": "Pipeline Integration Test",
"description": "...",
"state": "open",
"open_issues": 3,
"closed_issues": 0,
"created_at": "2026-04-04T00:27:11Z",
"due_on": "2026-04-11T00:27:03Z"
}
```
### Issue
```json
{
"number": 1,
"title": "Setup Gitea Client",
"body": "## Чеклист\n- [x] Задача 1\n- [ ] Задача 2",
"state": "open",
"labels": [{ "id": 1, "name": "status: new", "color": "0052cc" }],
"milestone": { "id": 42, "title": "..." },
"comments": 3
}
```
### Label
```json
{
"id": 1,
"name": "status: new",
"color": "0052cc",
"description": "New issue",
"exclusive": false,
"is_archived": false
}
```
## Интеграция с агентами
Агенты могут использовать GiteaClient для:
1. **Создание tasks**: `client.createIssue()`
2. **Обновление статуса**: `client.setStatus()`
3. **Логирование прогресса**: `client.createComment()`
4. **Работа с milestone**: `client.createMilestone()`
5. **Парсинг чеклистов**: Извлечение `- [x]` из issue body
### Pipeline Integration
```typescript
// В .kilo/commands/pipeline.md
import { GiteaClient, PipelineRunner } from './src/kilocode/index.js'
const runner = await createPipelineRunner({
giteaToken: process.env.GITEA_TOKEN
})
// Запустить пайплайн для issue
await runner.run({ issueNumber: 42 })
// Оценить производительность
await runner.logEvaluation(42, [
{ agent: 'lead-developer', score: 8, notes: 'Clean code' },
{ agent: 'code-skeptic', score: 7, notes: 'Found 2 issues' }
], 2, 1.5)
```

View File

@@ -11,6 +11,22 @@ export interface GiteaConfig {
repo: string
}
// AccessToken for authentication
export interface AccessToken {
id: number
name: string
sha1: string
token_last_eight: string
created_at: string
last_used_at?: string
scopes: string[]
}
export interface CreateTokenOptions {
name: string
scopes?: string[]
}
// Label structure per Gitea API 1.21+
export interface Label {
id: number
@@ -111,6 +127,38 @@ export class GiteaClient {
this.repo = config?.repo || ""
}
/**
* Create a token using Basic Auth (username/password)
* Requires GITEA_USERNAME and GITEA_PASSWORD env vars
*/
static async createToken(
username: string,
password: string,
name: string,
scopes: string[] = ["all"],
apiUrl: string = GITEA_API_URL
): Promise<{ token: string; id: number }> {
const response = await fetch(`${apiUrl}/users/${username}/tokens`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Basic " + Buffer.from(`${username}:${password}`).toString("base64")
},
body: JSON.stringify({ name, scopes })
})
if (!response.ok) {
const error = await response.text()
throw new Error(`Failed to create token: ${response.status} - ${error}`)
}
const data = await response.json()
return {
token: data.sha1,
id: data.id
}
}
setRepository(owner: string, repo: string): void {
this.owner = owner
this.repo = repo