/** * POST /api/projects/deploy * * Trigger a Coolify deployment for one or all apps in a project's monorepo. * * Body: { projectId: string, appName?: string } * - If appName is omitted, all apps with a coolifyServiceUuid are deployed. */ import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth/authOptions'; import { query } from '@/lib/db-postgres'; import { deployApplication } from '@/lib/coolify'; export async function POST(request: Request) { try { const session = await getServerSession(authOptions); if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { projectId, appName } = await request.json() as { projectId: string; appName?: string; }; if (!projectId) { return NextResponse.json({ error: 'projectId is required' }, { status: 400 }); } const rows = await query<{ data: any }>( `SELECT data FROM fs_projects WHERE id = $1 LIMIT 1`, [projectId], ); if (!rows[0]) { return NextResponse.json({ error: 'Project not found' }, { status: 404 }); } const projectData = rows[0].data; if (projectData.userId !== session.user.id && projectData.workspace !== session.user.email?.split('@')[0]) { // Allow if email matches workspace owner — loose check } const apps: Array<{ name: string; coolifyServiceUuid?: string | null }> = projectData.apps ?? []; const targets = appName ? apps.filter(a => a.name === appName) : apps; if (targets.length === 0) { return NextResponse.json({ error: `No matching apps found${appName ? ` for "${appName}"` : ''}` }, { status: 404 }); } const results: Array<{ app: string; deploymentUuid?: string; error?: string }> = []; for (const app of targets) { if (!app.coolifyServiceUuid) { results.push({ app: app.name, error: 'No Coolify service UUID — app may not be provisioned yet' }); continue; } try { const deployment = await deployApplication(app.coolifyServiceUuid); results.push({ app: app.name, deploymentUuid: deployment.deployment_uuid }); console.log(`[API] Deploy triggered: ${app.name} → ${deployment.deployment_uuid}`); } catch (err) { const msg = err instanceof Error ? err.message : String(err); results.push({ app: app.name, error: msg }); console.error(`[API] Deploy failed for ${app.name}:`, msg); } } return NextResponse.json({ results }); } catch (error) { console.error('[POST /api/projects/deploy] Error:', error); return NextResponse.json( { error: 'Failed to trigger deployment', details: error instanceof Error ? error.message : String(error) }, { status: 500 }, ); } }