import express, {Application, ErrorRequestHandler, Request, Response} from 'express' import 'dotenv/config' import * as env from 'env-var' import {PushWebhook} from "./PushWebhook"; import {spawn} from "child_process"; const app: Application = express() const authHeader = env.get('AUTH-HEADER').required().asString() const port: number = env.get('PORT').default(3000).asPortNumber() const rootDir = env.get('ROOT_DIR').default('/data').asString() app.use(express.json()); const timeouts: Record = {} async function parsePushHook(webhook: PushWebhook) { const repository: string|undefined = webhook.event_data?.repository?.repo_full_name const {tag, resource_url} = webhook.event_data?.resources?.[0] ?? { } if (!repository || !tag || !resource_url) { return } clearTimeout(timeouts[repository]) timeouts[repository] = setTimeout(async () => { delete timeouts[repository] const filename = repository .replace(/[^\w\s/]/gi, '-') .replace(/\//gi, '_') try { const cp = spawn(`./${filename}.sh`, [tag, resource_url], { cwd: rootDir, stdio: ['inherit', 'inherit', 'inherit', 'ipc'] }); cp.on('message', data => console.log(data)) await new Promise((resolve, reject) => { cp.on('close', resolve) cp.on('error', reject) }) } catch (e) { console.error(e) } }, 3000) } app.post('/', async (req: Request, res: Response) => { if (authHeader !== req.header('authorization')) { res.status(403).json({msg: "Authorization header invalid!"}) return } const body: PushWebhook = req.body if (body?.type !== "PUSH_ARTIFACT") { res.status(400).json({msg: "Only push hooks are allowed!"}) return } parsePushHook(body) res.json({msg: "Success"}) }) const errorHandler: ErrorRequestHandler = (err, req, res, next) => { res.status(400).json({msg: 'error', err}) } app.use(errorHandler) app.listen(port, function () { console.log(`App is listening on port ${port}!`) })