From 061fa2a233ae87cfad8b1f5ef85bd6a3225f1de0 Mon Sep 17 00:00:00 2001 From: Hamzat Victor Date: Thu, 22 Jan 2026 17:43:02 +0200 Subject: [PATCH 1/2] feat: kill dev/preview servers after the project is closed(#53) --- lib/package.json | 1 + lib/services/Project.ts | 56 +++++++++++++++++++++++++++++++++++++++++ package-lock.json | 1 + server/src/index.ts | 7 +++--- 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/lib/package.json b/lib/package.json index 4c905144..a685bbeb 100644 --- a/lib/package.json +++ b/lib/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@clerk/backend": "^1.34.0", + "@gitwit/templates": "*", "@gitwit/db": "*", "@octokit/core": "^7.0.3", "dotenv": "^16.6.1", diff --git a/lib/services/Project.ts b/lib/services/Project.ts index b2fc2be4..1773433c 100644 --- a/lib/services/Project.ts +++ b/lib/services/Project.ts @@ -1,3 +1,4 @@ +import { templateConfigs } from "@gitwit/templates" import { Sandbox as Container } from "e2b" import { CONTAINER_TIMEOUT } from "../utils/constants" import { FileManager } from "./FileManager" @@ -24,6 +25,61 @@ export class Project { this.projectId = projectId } + /** + * Kill all known dev server processes in the container (e.g. npm run dev, yarn dev, pnpm dev, vite, next, etc.) + */ + async killDevServers(): Promise { + if (!this.container) return + // Gather all dev server patterns (template + common) + const patterns = [ + this.type && templateConfigs[this.type]?.runCommand, + "vite", + "next", + "nodemon", + "webpack serve", + "parcel", + "gulp", + "python -m http.server", + "node ", + "npm ", + ].filter(Boolean) + + let psOutput = "" + try { + const result = await this.container.commands.run("ps aux") + psOutput = result.stdout || "" + } catch {} + + const lines = psOutput.split("\n") + const killed: string[] = [] + const seenPids = new Set() + + for (const line of lines) { + for (const pattern of patterns) { + if (pattern && line.includes(pattern)) { + const parts = line.trim().split(/\s+/) + const pid = parts[1] + if (pid && pid !== "PID" && !seenPids.has(pid)) { + try { + await this.container.commands.run(`kill -9 ${pid}`) + killed.push(`${pattern} (pid ${pid})`) + seenPids.add(pid) + } catch {} + } + } + } + } + + if (killed.length) { + console.log( + `[killDevServers] Killed processes for project ${this.projectId}:\n${killed.join("\n")}`, + ) + } else { + console.log( + `[killDevServers] No dev server processes found to kill for project ${this.projectId}`, + ) + } + } async createContainer(): Promise { console.log("Creating container for ", this.projectId) const templateTypes = ["vanillajs", "reactjs", "nextjs", "streamlit", "php"] diff --git a/package-lock.json b/package-lock.json index 0e897dd3..ff554c8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "dependencies": { "@clerk/backend": "^1.34.0", "@gitwit/db": "*", + "@gitwit/templates": "*", "@octokit/core": "^7.0.3", "dotenv": "^16.6.1", "drizzle-orm": "^0.44.2", diff --git a/server/src/index.ts b/server/src/index.ts index ae5c2fe6..5914436e 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -80,7 +80,7 @@ const gitClient = process.env.DOKKU_HOST && process.env.DOKKU_KEY ? new SecureGitClient( `dokku@${process.env.DOKKU_HOST}`, - process.env.DOKKU_KEY + process.env.DOKKU_KEY, ) : null @@ -123,7 +123,7 @@ io.on("connection", async (socket) => { { dokkuClient, gitClient, - } + }, ) // For each event handler, listen on the socket for that event @@ -138,7 +138,7 @@ io.on("connection", async (socket) => { } catch (e: any) { handleErrors(`Error processing event "${event}":`, e, socket) } - } + }, ) }) @@ -149,6 +149,7 @@ io.on("connection", async (socket) => { try { // Deregister the connection connections.removeConnectionForProject(socket, data.projectId) + await project.killDevServers() } catch (e: any) { handleErrors("Error disconnecting:", e, socket) } From 2e04e0f79b9284a71d2a93f78f36d36b47d6a99a Mon Sep 17 00:00:00 2001 From: Hamzat Victor Date: Thu, 22 Jan 2026 17:43:14 +0200 Subject: [PATCH 2/2] fix: update dev scripts to ensure proper execution order and dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fe2de640..9054ddb9 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "db:studio": "npm run studio -w db", "db:studio:prod": "NODE_ENV=production npm run studio -w db", "dev:deps": "concurrently -k -n LIB,DB -c yellow,magenta \"npm run dev -w lib\" \"npm run dev -w db\"", - "dev": "npm run build:deps && concurrently -k -n WEB,SERVER,AI -c blue,green,cyan \"npm run dev -w web\" \"npm run dev -w server\" \"npm run dev -w ai\"", - "dev:web": "npm run build:deps && npm run dev -w web", - "dev:server": "npm run build:deps && npm run dev -w server", + "dev": "concurrently -k -n LIB,DB,WEB,SERVER,AI -c yellow,magenta,blue,green,cyan \"npm run dev -w lib\" \"npm run dev -w db\" \"npm run dev -w web\" \"npm run dev -w server\" \"npm run dev -w ai\"", + "dev:web": "concurrently -k -n LIB,DB,WEB -c yellow,magenta,blue \"npm run dev -w lib\" \"npm run dev -w db\" \"npm run dev -w web\"", + "dev:server": "concurrently -k -n LIB,DB,SERVER -c yellow,magenta,green \"npm run dev -w lib\" \"npm run dev -w db\" \"npm run dev -w server\"", "dev:watch": "concurrently -k -n LIB,DB,WEB,SERVER -c yellow,magenta,blue,green \"npm run dev -w lib\" \"npm run dev -w db\" \"npm run dev -w web\" \"npm run dev -w server\"", "start": "concurrently -k \"npm start -w web\" \"npm start -w server\"", "start:web": "npm start -w web",