| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- #!/usr/bin/env node
- // webhook-server.js — nhận webhook từ Gogs và trigger deploy
- // Run: node webhook-server.js [port]
- //
- // Gogs webhook URL: http://<pi-ip>:9000/webhook
- const http = require('http')
- const PORT = process.env['WEBHOOK_PORT'] || 9000
- const DEPLOY_SCRIPT = process.env['DEPLOY_SCRIPT'] || '/opt/timelapse/scripts/deploy.sh'
- const WEBHOOK_SECRET = process.env['WEBHOOK_SECRET'] || ''
- function verifySignature(body, signature) {
- if (!WEBHOOK_SECRET) return true
- const crypto = require('crypto')
- const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET)
- hmac.update(body)
- const expected = 'sha256=' + hmac.digest('hex')
- return crypto.timingSafeEqual(Buffer.from(signature || ''), Buffer.from(expected))
- }
- const server = http.createServer((req, res) => {
- if (req.method !== 'POST' || req.url !== '/webhook') {
- res.writeHead(404)
- res.end('Not found')
- return
- }
- let body = ''
- req.on('data', chunk => { body += chunk.toString() })
- req.on('end', () => {
- const signature = req.headers['x-gogs-signature'] || req.headers['x-hub-signature-256'] || ''
- if (!verifySignature(body, signature)) {
- res.writeHead(401)
- res.end('Unauthorized')
- return
- }
- let payload
- try { payload = JSON.parse(body) } catch { payload = {} }
- const branch = payload.ref ? payload.ref.replace('refs/heads/', '') : 'main'
- console.log(`[${new Date().toISOString()}] Webhook received — branch: ${branch}`)
- res.writeHead(200, { 'Content-Type': 'application/json' })
- res.end(JSON.stringify({ ok: true, branch }))
- // Trigger deploy async
- const { spawn } = require('child_process')
- const deploy = spawn('bash', [DEPLOY_SCRIPT, branch], {
- cwd: '/opt/timelapse',
- env: { ...process.env, DEPLOY_BRANCH: branch },
- })
- deploy.stdout.on('data', d => process.stdout.write(d))
- deploy.stderr.on('data', d => process.stderr.write(d))
- deploy.on('exit', code => {
- console.log(`[${new Date().toISOString()}] Deploy exited with code ${code}`)
- })
- })
- })
- server.listen(PORT, () => {
- console.log(`Webhook server listening on http://0.0.0.0:${PORT}/webhook`)
- })
|