From 182c59e6a742c90fde96313d9fc48bdb69a98207 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 29 Dec 2025 21:09:11 +0100 Subject: [PATCH] Test deployment --- src/components/dialogs/DeployApplication.tsx | 13 ++-- src/core/application.ts | 72 ++++++++++++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/core/application.ts diff --git a/src/components/dialogs/DeployApplication.tsx b/src/components/dialogs/DeployApplication.tsx index 98ce304..2fef292 100644 --- a/src/components/dialogs/DeployApplication.tsx +++ b/src/components/dialogs/DeployApplication.tsx @@ -13,15 +13,10 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Textarea } from "../ui/textarea"; -import { - authNode, - getLiveNodes, - getNodes, - setNodes as updateNodes, -} from "@/core/node"; +import { getLiveNodes } from "@/core/node"; import { Combobox } from "../ui/combobox"; import { Node, NodeLiveData } from "@/lib/types"; +import { deployNewApp } from "@/core/application"; export default function DeployApplication({ children, @@ -40,7 +35,9 @@ export default function DeployApplication({ fetchNodes(); }, []); - const deploy = () => {}; + const deploy = async () => { + console.log(await deployNewApp(name, repo, node)); + }; return ( diff --git a/src/core/application.ts b/src/core/application.ts new file mode 100644 index 0000000..710446a --- /dev/null +++ b/src/core/application.ts @@ -0,0 +1,72 @@ +"use server"; + +import { verifySession } from "./auth/session"; +import { randomUUID } from "crypto"; +import fs from "fs/promises"; +import path from "path"; +import { exec } from "child_process"; +import util from "util"; + +const execAsync = util.promisify(exec); + +const DATA_DIR = path.join(process.cwd(), "data", "apps"); + +export async function deployNewApp(name: string, repo: string, nodeId: string) { + if (await verifySession()) { + throw new Error("Unauthorized"); + } + + // Create app ID + const appId = `app_${randomUUID()}`; + const appDir = path.join(DATA_DIR, appId); + const repoDir = path.join(appDir, "repo"); + + // Create directories + await fs.mkdir(repoDir, { recursive: true }); + + // Write app.json + const appConfig = { + id: appId, + name, + repo, + nodeId, + createdAt: new Date().toISOString(), + }; + + await fs.writeFile( + path.join(appDir, "app.json"), + JSON.stringify(appConfig, null, 2) + ); + + // Clone repository + try { + await execAsync(`git clone ${repo} ${repoDir}`); + } catch (err) { + throw new Error("Failed to clone repository"); + } + + // Validate Dockerfile + const dockerfilePath = path.join(repoDir, "Dockerfile"); + + try { + await fs.access(dockerfilePath); + } catch { + throw new Error("Dockerfile not found in repository root"); + } + + const imageTag = `dockship/${appId}:latest`; + + try { + await execAsync(`docker build -t ${imageTag} .`, { + cwd: repoDir, + }); + } catch { + throw new Error("Docker build failed"); + } + + return { + success: true, + appId, + image: imageTag, + }; +}