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"; const { AUTH_TOKEN } = process.env; const authMiddleware = async (request, reply) => { if (request.headers.authorization !== `Bearer ${AUTH_TOKEN}`) { return reply.code(401).send("Unauthorized"); } }; const execAsync = promisify(exec); const fastify = Fastify({ logger: true }); fastify.register(fastifyStatic, { root: path.join(process.cwd(), "dist"), prefix: "/", }); fastify.post( "/webhook/rebuild", { preHandler: authMiddleware }, async (request, reply) => { try { const { repository: { clone_url: repoUrl, default_branch: branch }, } = request.body; 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 remote set-url origin ${repoUrl}`); await execAsync("git fetch origin"); // we won't be able to reply later, so do it here // this doesn't necessarily imply a successful build though // TODO: healthcheck reply.status(200).send("fetched successfully"); await execAsync(`git reset --hard origin/${branch}`); const { stdout, stderr } = await execAsync("yarn run build"); console.log(stdout); console.error(stderr); } catch (error) { console.error(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); } });