Add S3/MinIO storage for deployment previews

- Add S3 client helper (src/lib/s3.ts) with upload/download functions
- Add /api/deployments/[uuid]/preview endpoint for presigned URLs
- Update DeploymentDashboard to fetch and display preview images
- Install @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner

Storage: MinIO bucket nuc-portal-previews with dedicated service account

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-06 18:11:50 +01:00
parent efc7a8392b
commit 91624fd6de
5 changed files with 2022 additions and 4 deletions

View File

@@ -0,0 +1,54 @@
import { NextResponse } from 'next/server';
import { getPreviewUrl, previewExists } from '@/lib/s3';
import { fetchDeploymentDetail } from '@/lib/coolify-db';
export async function GET(
_request: Request,
{ params }: { params: Promise<{ uuid: string }> }
) {
const { uuid } = await params;
try {
// Get deployment to find application UUID
const deployment = await fetchDeploymentDetail(uuid);
if (!deployment) {
return NextResponse.json({ error: 'Deployment not found' }, { status: 404 });
}
const appUuid = deployment.application_uuid;
// Check if preview exists
const exists = await previewExists(appUuid, uuid);
if (!exists) {
return NextResponse.json({
exists: false,
message: 'Preview not available',
hint: 'Screenshot will be captured after successful deployment',
});
}
// Get presigned URL (valid for 1 hour)
const url = await getPreviewUrl(appUuid, uuid);
if (!url) {
return NextResponse.json(
{ error: 'Failed to generate preview URL' },
{ status: 500 }
);
}
return NextResponse.json({
exists: true,
url,
expiresIn: 3600,
});
} catch (error) {
console.error('Preview fetch error:', error);
return NextResponse.json(
{ error: 'Failed to fetch preview', details: String(error) },
{ status: 500 }
);
}
}