Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
144 lines
3.6 KiB
TypeScript
144 lines
3.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
|
|
// Woodpecker API configuration
|
|
const WOODPECKER_URL = process.env.WOODPECKER_URL || 'http://woodpecker-server:8000'
|
|
const WOODPECKER_TOKEN = process.env.WOODPECKER_TOKEN || ''
|
|
|
|
interface PipelineStep {
|
|
name: string
|
|
state: 'pending' | 'running' | 'success' | 'failure' | 'skipped'
|
|
exit_code: number
|
|
}
|
|
|
|
interface Pipeline {
|
|
id: number
|
|
number: number
|
|
status: 'pending' | 'running' | 'success' | 'failure'
|
|
event: string
|
|
branch: string
|
|
commit: string
|
|
message: string
|
|
author: string
|
|
created: number
|
|
started: number
|
|
finished: number
|
|
steps: PipelineStep[]
|
|
}
|
|
|
|
interface CICDStatusResponse {
|
|
status: 'online' | 'offline'
|
|
pipelines: Pipeline[]
|
|
lastUpdate: string
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const searchParams = request.nextUrl.searchParams
|
|
const repoId = searchParams.get('repo') || '1'
|
|
const limit = parseInt(searchParams.get('limit') || '5')
|
|
|
|
try {
|
|
// Fetch pipelines from Woodpecker API
|
|
const response = await fetch(
|
|
`${WOODPECKER_URL}/api/repos/${repoId}/pipelines?per_page=${limit}`,
|
|
{
|
|
headers: {
|
|
'Authorization': `Bearer ${WOODPECKER_TOKEN}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
cache: 'no-store',
|
|
}
|
|
)
|
|
|
|
if (!response.ok) {
|
|
// If Woodpecker is not available, return offline status
|
|
return NextResponse.json({
|
|
status: 'offline',
|
|
pipelines: [],
|
|
lastUpdate: new Date().toISOString(),
|
|
error: 'Woodpecker API nicht erreichbar'
|
|
} as CICDStatusResponse)
|
|
}
|
|
|
|
const rawPipelines = await response.json()
|
|
|
|
// Transform pipelines to our format
|
|
const pipelines: Pipeline[] = rawPipelines.map((p: any) => ({
|
|
id: p.id,
|
|
number: p.number,
|
|
status: p.status,
|
|
event: p.event,
|
|
branch: p.branch,
|
|
commit: p.commit?.substring(0, 7) || '',
|
|
message: p.message || '',
|
|
author: p.author,
|
|
created: p.created,
|
|
started: p.started,
|
|
finished: p.finished,
|
|
steps: p.workflows?.[0]?.children?.map((c: any) => ({
|
|
name: c.name,
|
|
state: c.state,
|
|
exit_code: c.exit_code
|
|
})) || []
|
|
}))
|
|
|
|
return NextResponse.json({
|
|
status: 'online',
|
|
pipelines,
|
|
lastUpdate: new Date().toISOString()
|
|
} as CICDStatusResponse)
|
|
|
|
} catch (error) {
|
|
console.error('CI/CD Status API error:', error)
|
|
return NextResponse.json({
|
|
status: 'offline',
|
|
pipelines: [],
|
|
lastUpdate: new Date().toISOString(),
|
|
error: 'Fehler beim Abrufen des CI/CD Status'
|
|
} as CICDStatusResponse)
|
|
}
|
|
}
|
|
|
|
// Trigger a new pipeline
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
const { repoId = '1', branch = 'main' } = body
|
|
|
|
const response = await fetch(
|
|
`${WOODPECKER_URL}/api/repos/${repoId}/pipelines`,
|
|
{
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${WOODPECKER_TOKEN}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ branch }),
|
|
}
|
|
)
|
|
|
|
if (!response.ok) {
|
|
return NextResponse.json(
|
|
{ error: 'Pipeline konnte nicht gestartet werden' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
|
|
const pipeline = await response.json()
|
|
return NextResponse.json({
|
|
success: true,
|
|
pipeline: {
|
|
id: pipeline.id,
|
|
number: pipeline.number,
|
|
status: pipeline.status
|
|
}
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('Pipeline trigger error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Fehler beim Starten der Pipeline' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|