From f9bbfc7f0a913d80d18e1ed62c37e2f9f2d2343f Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 2 Jan 2026 22:31:39 +0100 Subject: [PATCH] Deployment api --- src/app/api/deploy/route.ts | 52 ++++++++++++++++++++++++++++++++++++ src/app/deployments/page.tsx | 7 +++-- src/lib/dockship/deploy.ts | 22 +++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/app/api/deploy/route.ts create mode 100644 src/lib/dockship/deploy.ts diff --git a/src/app/api/deploy/route.ts b/src/app/api/deploy/route.ts new file mode 100644 index 0000000..4506d48 --- /dev/null +++ b/src/app/api/deploy/route.ts @@ -0,0 +1,52 @@ +import { NextRequest, NextResponse } from "next/server"; +import testAuth from "../auth"; +import { StatusCodes } from "http-status-codes"; +import { getDeployments } from "@/core/deployment"; +import { getApplications } from "@/core/application"; + +export async function GET(req: NextRequest): Promise { + const auth = await testAuth(req); + + if (auth) { + return NextResponse.json( + { message: auth }, + { status: StatusCodes.UNAUTHORIZED } + ); + } + + const apps = await getApplications(); + + const applications = await getDeployments(apps); + + return NextResponse.json({ + message: "ok", + applications, + }); +} + +export async function POST(req: NextRequest): Promise { + const auth = await testAuth(req); + const { name, repo, nodeId }: { name: string; repo: string; nodeId: string } = + await req.json(); + + if (auth) { + return NextResponse.json( + { message: auth }, + { status: StatusCodes.UNAUTHORIZED } + ); + } + + if (!name || !repo || !nodeId) { + return NextResponse.json( + { message: "Body missing name, repo, nodeId" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + const res = await installApp(name, repo, nodeId); + + return NextResponse.json({ + message: "ok", + ...res, + }); +} diff --git a/src/app/deployments/page.tsx b/src/app/deployments/page.tsx index 1d16d08..88efa13 100644 --- a/src/app/deployments/page.tsx +++ b/src/app/deployments/page.tsx @@ -14,7 +14,7 @@ import { } from "lucide-react"; import { useEffect, useState } from "react"; import { Application, Deployment } from "@/lib/types"; -import { getDeployments } from "@/core/deployment"; +import { getDeployments } from "@/lib/dockship/deploy"; import { getApplications } from "@/lib/dockship/application"; import { cn } from "@/lib/utils"; @@ -24,9 +24,8 @@ export default function DeploymentsPage() { useEffect(() => { const fetch = async () => { - const apps = await getApplications(); - setApplications(apps); - setDeployments((await getDeployments(apps)).filter((d) => d !== null)); + setApplications(await getApplications()); + setDeployments((await getDeployments()).filter((d) => d !== null)); }; fetch(); }, []); diff --git a/src/lib/dockship/deploy.ts b/src/lib/dockship/deploy.ts new file mode 100644 index 0000000..5176b54 --- /dev/null +++ b/src/lib/dockship/deploy.ts @@ -0,0 +1,22 @@ +"use server"; + +import { Deployment } from "@/lib/types"; +import { getNodes } from "./node"; +import axios from "axios"; + +export async function getDeployments(): Promise<(null | Deployment)[]> { + const nodes = await getNodes(); + + return ( + await Promise.all( + nodes.map( + async (n) => + await ( + await axios.get(`http://${n.ip}:3000/api/deploy`, { + headers: { Authorization: `ApiKey ${n.key}` }, + }) + ).data.applications + ) + ) + ).flat(); +}