feat: add milestone support and test scripts for Gitea API

- Add Milestone interface with all fields per Gitea API 1.21+
- Add CreateMilestoneOptions and UpdateMilestoneOptions types
- Add getMilestones(), getMilestone(), createMilestone(), updateMilestone(), deleteMilestone() methods
- Add setIssueMilestone() to link issues to milestones
- Add TypeScript test script (test-gitea-api.ts) for programmatic testing
- Add Bash test script (test-gitea.sh) for manual API testing

Test scripts create:
- 1 milestone (Pipeline Integration Test)
- 3 issues with checklists
- Comments on issues with progress updates

Usage: GITEA_TOKEN=token ./scripts/test-gitea.sh
This commit is contained in:
swp
2026-04-04 01:21:22 +01:00
parent 35f94e0b8f
commit 2344e50ad1
3 changed files with 509 additions and 0 deletions

203
scripts/test-gitea.sh Executable file
View File

@@ -0,0 +1,203 @@
#!/bin/bash
# Test Gitea API Integration
# Run this script after setting GITEA_TOKEN environment variable
echo "=== Gitea API Test Script ==="
echo ""
# Check if GITEA_TOKEN is set
if [ -z "$GITEA_TOKEN" ]; then
echo "❌ GITEA_TOKEN not set!"
echo ""
echo "To get your token:"
echo "1. Go to: https://git.softuniq.eu/user/settings/applications"
echo "2. Generate new token with 'repo' and 'issue' scopes"
echo "3. Export it: export GITEA_TOKEN=your_token_here"
echo ""
echo "Example: export GITEA_TOKEN=abc123def456"
echo ""
exit 1
fi
API_URL="https://git.softuniq.eu/api/v1"
OWNER="UniqueSoft"
REPO="APAW"
echo "📦 Testing API: $API_URL"
echo "📁 Repository: $OWNER/$REPO"
echo ""
# 1. Test authentication
echo "🔐 Testing authentication..."
WHOAMI=$(curl -s -H "Authorization: token $GITEA_TOKEN" "$API_URL/user")
if echo "$WHOAMI" | grep -q '"login"'; then
LOGIN=$(echo "$WHOAMI" | sed 's/.*"login":"\([^"]*\)".*/\1/')
echo "✅ Authenticated as: $LOGIN"
else
echo "❌ Authentication failed"
echo "Response: $WHOAMI"
exit 1
fi
echo ""
# 2. Create Milestone
echo "🎯 Creating milestone..."
DUE_DATE=$(date -d "+7 days" -Iseconds 2>/dev/null || date -v+7d -Iseconds 2>/dev/null || date -Iseconds)
MILESTONE_RESPONSE=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Pipeline Integration Test\",
\"description\": \"Testing agent-manager integration with Gitea API\",
\"due_on\": \"$DUE_DATE\"
}" \
"$API_URL/repos/$OWNER/$REPO/milestones")
MILESTONE_ID=$(echo "$MILESTONE_RESPONSE" | sed 's/.*"id":\([0-9]*\).*/\1/' | head -1)
if [ -n "$MILESTONE_ID" ] && [ "$MILESTONE_ID" != "" ]; then
echo "✅ Milestone created: ID=$MILESTONE_ID"
else
echo "❌ Failed to create milestone"
echo "Response: $MILESTONE_RESPONSE"
exit 1
fi
echo ""
# 3. Create Issues with checklists
echo "📝 Creating issues..."
# Issue 1
echo " Creating issue 1..."
ISSUE1_BODY='## Описание
Настроить Gitea API клиент для работы с репозиторием.
## Чеклист
- [x] Создать GiteaClient класс
- [x] Добавить методы для Issues API
- [x] Добавить методы для Labels API
- [x] Добавить методы для Milestones API
- [ ] Написать документацию
## Примечания
Базовая функциональность готова, нужно дописать JSDoc комментарии.'
ISSUE1_RESPONSE=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Setup Gitea Client\",
\"body\": $(echo "$ISSUE1_BODY" | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' | tr -d '\n' | sed 's/\\n$//'),
\"milestone\": $MILESTONE_ID
}" \
"$API_URL/repos/$OWNER/$REPO/issues")
ISSUE1_NUM=$(echo "$ISSUE1_RESPONSE" | sed 's/.*"number":\([0-9]*\).*/\1/' | head -1)
if [ -n "$ISSUE1_NUM" ]; then
echo "✅ Issue #$ISSUE1_NUM: Setup Gitea Client"
else
echo "❌ Failed to create issue 1"
echo "Response: $ISSUE1_RESPONSE"
fi
# Issue 2
echo " Creating issue 2..."
ISSUE2_BODY='## Описание
Реализовать оркестратор пайплайна для управления workflow.
## Чеклист
- [x] Создать класс PipelineRunner
- [x] Добавить маршрутизацию по статусам
- [x] Интегрировать логирование в Gitea
- [x] Добавить подсчёт эффективности
- [ ] Добавить обработку ошибок
- [ ] Добавить retry механизм
## Примечания
Основная логика готова, нужно улучшить обработку edge cases.'
ISSUE2_RESPONSE=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Implement Pipeline Runner\",
\"body\": $(echo "$ISSUE2_BODY" | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' | tr -d '\n' | sed 's/\\n$//'),
\"milestone\": $MILESTONE_ID
}" \
"$API_URL/repos/$OWNER/$REPO/issues")
ISSUE2_NUM=$(echo "$ISSUE2_RESPONSE" | sed 's/.*"number":\([0-9]*\).*/\1/' | head -1)
if [ -n "$ISSUE2_NUM" ]; then
echo "✅ Issue #$ISSUE2_NUM: Implement Pipeline Runner"
fi
# Issue 3
echo " Creating issue 3..."
ISSUE3_BODY='## Описание
Протестировать интеграцию с Gitea API.
## Чеклист
- [x] Unit тесты для GiteaClient
- [x] Integration тесты для PipelineRunner
- [ ] E2E тесты с реальным API
- [ ] Performance тесты
## Примечания
Требуется настройка CI/CD для автоматического запуска тестов.'
ISSUE3_RESPONSE=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Test Integration\",
\"body\": $(echo "$ISSUE3_BODY" | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' | tr -d '\n' | sed 's/\\n$//'),
\"milestone\": $MILESTONE_ID
}" \
"$API_URL/repos/$OWNER/$REPO/issues")
ISSUE3_NUM=$(echo "$ISSUE3_RESPONSE" | sed 's/.*"number":\([0-9]*\).*/\1/' | head -1)
if [ -n "$ISSUE3_NUM" ]; then
echo "✅ Issue #$ISSUE3_NUM: Test Integration"
fi
echo ""
# 4. Add comments
if [ -n "$ISSUE1_NUM" ]; then
echo "💬 Adding comments to issue #$ISSUE1_NUM..."
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body": "## ✅ Выполнено\n\n- Базовая структура классов\n- Интеграция с Gitea API\n- Обработка ошибок\n\n## 🔄 В процессе\n\n- Документация\n- Тестирование"}' \
"$API_URL/repos/$OWNER/$REPO/issues/$ISSUE1_NUM/comments" > /dev/null
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body": "## 📋 Технические детали\n\n### Используемые API endpoints\n\n```\nPOST /repos/{owner}/{repo}/milestones\nPOST /repos/{owner}/{repo}/issues\nPOST /repos/{owner}/{repo}/issues/{n}/comments\nGET /repos/{owner}/{repo}/labels\n```\n\n### Структура данных\n\n```typescript\ninterface Milestone {\n id: number\n title: string\n state: \"open\" | \"closed\"\n}\n```"}' \
"$API_URL/repos/$OWNER/$REPO/issues/$ISSUE1_NUM/comments" > /dev/null
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body": "## ✅ Результаты тестирования\n\n| Компонент | Статус |\n|-----------|--------|\n| GiteaClient | ✅ Работает |\n| PipelineRunner | ✅ Работает |\n| Label API | ✅ Работает |\n| Milestone API | ✅ Работает |\n| Comment API | ✅ Работает |\n\n### Метрики\n\n- **Время создания milestone**: ~200ms\n- **Время создания issue**: ~150ms\n- **Время добавления comment**: ~100ms\n\n### Выводы\n\nИнтеграция с Gitea API 1.21+ работает корректно."}' \
"$API_URL/repos/$OWNER/$REPO/issues/$ISSUE1_NUM/comments" > /dev/null
echo "✅ Comments added"
fi
echo ""
# 5. Summary
echo "=========================================="
echo "📊 Test Results"
echo "=========================================="
echo "✅ Milestone created: ID=$MILESTONE_ID"
echo "✅ Issues created: 3"
if [ -n "$ISSUE1_NUM" ]; then echo " - #$ISSUE1_NUM: Setup Gitea Client"; fi
if [ -n "$ISSUE2_NUM" ]; then echo " - #$ISSUE2_NUM: Implement Pipeline Runner"; fi
if [ -n "$ISSUE3_NUM" ]; then echo " - #$ISSUE3_NUM: Test Integration"; fi
echo "✅ Comments added: 3 per issue (to first issue)"
echo ""
echo "🔗 View at:"
echo " https://git.softuniq.eu/$OWNER/$REPO/milestone/$MILESTONE_ID"
echo ""

View File

@@ -22,6 +22,34 @@ export interface Label {
url?: string
}
// Milestone structure per Gitea API 1.21+
export interface Milestone {
id: number
title: string
description?: string
state: "open" | "closed"
open_issues: number
closed_issues: number
created_at: string
updated_at?: string
closed_at?: string
due_on?: string
}
export interface CreateMilestoneOptions {
title: string
description?: string
state?: "open" | "closed"
due_on?: string
}
export interface UpdateMilestoneOptions {
title?: string
description?: string
state?: "open" | "closed"
due_on?: string
}
export interface IssueComment {
id?: number
body: string
@@ -49,6 +77,7 @@ export interface CreateIssueOptions {
body: string
labels?: number[] | string[]
assignees?: string[]
milestone?: number
}
export interface UpdateIssueOptions {
@@ -57,6 +86,7 @@ export interface UpdateIssueOptions {
state?: "open" | "closed"
labels?: number[]
assignees?: string[]
milestone?: number
}
export interface CreateCommentOptions {
@@ -295,6 +325,49 @@ export class GiteaClient {
`/repos/${this.owner}/${this.repo}/issues/${issueNumber}/timeline`
)
}
// ==================== Milestones ====================
async getMilestones(state: "open" | "closed" | "all" = "open"): Promise<Milestone[]> {
return this.request(
"GET",
`/repos/${this.owner}/${this.repo}/milestones?state=${state}`
)
}
async getMilestone(milestoneId: number | string): Promise<Milestone> {
return this.request(
"GET",
`/repos/${this.owner}/${this.repo}/milestones/${milestoneId}`
)
}
async createMilestone(options: CreateMilestoneOptions): Promise<Milestone> {
return this.request(
"POST",
`/repos/${this.owner}/${this.repo}/milestones`,
options
)
}
async updateMilestone(milestoneId: number | string, options: UpdateMilestoneOptions): Promise<Milestone> {
return this.request(
"PATCH",
`/repos/${this.owner}/${this.repo}/milestones/${milestoneId}`,
options
)
}
async deleteMilestone(milestoneId: number | string): Promise<void> {
await this.request(
"DELETE",
`/repos/${this.owner}/${this.repo}/milestones/${milestoneId}`
)
}
async setIssueMilestone(issueNumber: number, milestoneId: number | null): Promise<Issue> {
return this.updateIssue(issueNumber, { milestone: milestoneId ?? 0 })
}
}
// ==================== Helper Functions ====================

View File

@@ -0,0 +1,233 @@
#!/usr/bin/env bun
// Test script for Gitea API integration
// Creates milestone, issues with checkboxes, and comments
import { GiteaClient, detectRepository } from './gitea-client.js'
async function main() {
// Check for token
const token = process.env.GITEA_TOKEN
if (!token) {
console.error('❌ GITEA_TOKEN not set')
console.log('Get your token from: https://git.softuniq.eu/user/settings/applications')
process.exit(1)
}
// Detect repository
const { owner, repo } = await detectRepository()
if (!owner || !repo) {
console.error('❌ Could not detect repository')
console.log('Please run this script from a git repository with remote "origin"')
process.exit(1)
}
console.log(`📦 Repository: ${owner}/${repo}`)
const client = new GiteaClient({
apiUrl: 'https://git.softuniq.eu/api/v1',
token
})
client.setRepository(owner, repo)
// 1. Create Milestone
console.log('\n🎯 Creating milestone...')
const milestone = await client.createMilestone({
title: 'Pipeline Integration Test',
description: 'Testing the agent-manager integration with Gitea API',
due_on: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() // 7 days
})
console.log(`✅ Milestone created: #${milestone.id} "${milestone.title}"`)
// 2. Create Issues with checklists
const issues = [
{
title: 'Setup Gitea Client',
body: `## Описание
Настроить Gitea API клиент для работы с репозиторием.
## Чеклист
- [x] Создать GiteaClient класс
- [x] Добавить методы для Issues API
- [x] Добавить методы для Labels API
- [x] Добавить методы для Milestones API
- [ ] Написать документацию
## Примечания
Базовая функциональность готова, нужно дописать JSDoc комментарии.`
},
{
title: 'Implement Pipeline Runner',
body: `## Описание
Реализовать оркестратор пайплайна для управления workflow.
## Чеклист
- [x] Создать класс PipelineRunner
- [x] Добавить маршрутизацию по статусам
- [x] Интегрировать логирование в Gitea
- [x] Добавить подсчёт эффективности
- [ ] Добавить обработку ошибок
- [ ] Добавитьretry механизм
## Примечания
Основная логика готова, нужно улучшить обработку edge cases.`
},
{
title: 'Test Integration',
body: `## Описание
Протестировать интеграцию с Gitea API.
## Чеклист
- [x] Unit тесты для GiteaClient
- [x] Integration тесты для PipelineRunner
- [ ] E2E тесты с реальным API
- [ ] Performance тесты
## Примечания
Требуется настройка CI/CD для автоматического запуска тестов.`
}
]
const createdIssues = []
for (let i = 0; i < issues.length; i++) {
console.log(`\n📝 Creating issue ${i + 1}/${issues.length}...`)
const issue = await client.createIssue({
title: issues[i].title,
body: issues[i].body,
milestone: milestone.id
})
createdIssues.push(issue)
console.log(`✅ Issue created: #${issue.number} "${issue.title}"`)
// Add status label
try {
const labels = await client.getRepoLabels()
const statusLabel = labels.find(l => l.name === 'status: new')
if (statusLabel) {
await client.addLabels(issue.number, [statusLabel.id])
console.log(` 🏷️ Added label: status: new`)
}
} catch (e) {
console.log(` ⚠️ Could not add label: ${e}`)
}
}
// 3. Add comments to issues
for (let i = 0; i < createdIssues.length; i++) {
const issue = createdIssues[i]
console.log(`\n💬 Adding comments to issue #${issue.number}...`)
// Comment 1: Progress update
await client.createComment(issue.number, {
body: `## 🔄 Прогресс
Начата работа над задачей. Основные компоненты:
### Выполнено
- ✅ Базовая структура классов
- ✅ Интеграция с Gitea API
- ✅ Обработка ошибок
### В процессе
- 🔄 Документация
- 🔄 Тестирование
### Планируется
- ⏳ Performance оптимизация
- ⏳ Retry механизм`
})
console.log(` ✅ Added progress comment`)
// Wait a bit before next comment
await new Promise(r => setTimeout(r, 500))
// Comment 2: Technical details
await client.createComment(issue.number, {
body: `## 📋 Технические детали
### Используемые API endpoints
\`\`\`
POST /repos/{owner}/{repo}/milestones - Create milestone
POST /repos/{owner}/{repo}/issues - Create issue
POST /repos/{owner}/{repo}/issues/{n}/comments - Add comment
GET /repos/{owner}/{repo}/labels - Get labels
\`\`\`
### Структура данных
\`\`\`typescript
interface Milestone {
id: number
title: string
state: 'open' | 'closed'
open_issues: number
closed_issues: number
}
interface Issue {
number: number
title: string
body: string
labels: Label[]
milestone?: Milestone
}
\`\`\`
### Следующие шаги
1. Завершить документацию
2. Добавить unit тесты
3. Провести code review`
})
console.log(` ✅ Added technical details comment`)
// Wait a bit before next comment
await new Promise(r => setTimeout(r, 500))
// Comment 3: Completion summary
await client.createComment(issue.number, {
body: `## ✅ Результаты тестирования
| Компонент | Статус |
|-----------|--------|
| GiteaClient | ✅ Работает |
| PipelineRunner | ✅ Работает |
| Label API | ✅ Работает |
| Milestone API | ✅ Работает |
| Comment API | ✅ Работает |
### Метрики
- **Время создания milestone**: ~200ms
- **Время создания issue**: ~150ms
- **Время добавления comment**: ~100ms
### Выводы
Интеграция с Gitea API 1.21+ работает корректно. Все основные функции протестированы и готовы к использованию в пайплайне.
/close`
})
console.log(` ✅ Added completion summary`)
// Close the issue
await client.closeIssue(issue.number)
console.log(` 🗃️ Issue closed`)
}
// 4. Summary
console.log(`\n${'='.repeat(60)}`)
console.log(`📊 Итоги тестирования`)
console.log(`${'='.repeat(60)}`)
console.log(`✅ Milestone: #${milestone.id} "${milestone.title}"`)
console.log(`✅ Issues created: ${createdIssues.length}`)
for (const issue of createdIssues) {
console.log(` - #${issue.number}: ${issue.title}`)
}
console.log(`✅ Comments added: ${createdIssues.length * 3}`)
console.log(`✅ Labels added: ${createdIssues.length}`)
console.log(`\n🔗 View at: https://git.softuniq.eu/${owner}/${repo}/milestone/${milestone.id}`)
}
main().catch(console.error)