import Fastify from "fastify"; import fastifyStatic from "@fastify/static"; import { exec } from "node:child_process"; import { promisify } from "node:util"; import path from "node:path"; import crypto from "node:crypto"; const { WEBHOOK_SECRET } = process.env; const execAsync = promisify(exec); const fastify = Fastify({ logger: true }); fastify.register(fastifyStatic, { root: path.join(process.cwd(), "dist"), prefix: "/", }); const verifySignature = (payload, signature) => { const hmac = crypto.createHmac("sha256", WEBHOOK_SECRET); const digest = "sha256=" + hmac.update(payload).digest("hex"); return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature)); }; const updateRepo = async (repoUrl) => { try { const { code } = await execAsync("git rev-parse --git-dir") .then(() => ({ code: 0 })) .catch((error) => ({ code: error.code })); if (code !== 0) { await execAsync("git init"); await execAsync(`git remote add origin ${repoUrl}`); } await execAsync("git fetch origin"); await execAsync("git reset --hard origin/main"); await execAsync("npm run build"); } catch (error) { console.error("Failed to update repository:", error); throw error; } }; fastify.post("/webhook/rebuild", async (request, reply) => { const signature = request.headers["x-gitea-signature"]; if (!signature || !verifySignature(JSON.stringify(request.body), signature)) { return reply.status(401).send("Invalid signature"); } try { const repoUrl = request.body.repository.clone_url; await updateRepo(repoUrl); reply.status(200).send("Updated successfully"); } catch (error) { reply.status(500).send("Update failed"); } }); fastify.listen({ port: 3000, host: "0.0.0.0" }, (err) => { if (err) { fastify.log.error(err); process.exit(1); } });