65 lines
2.0 KiB
JavaScript
65 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|
// Tiny webhook receiver: validates the shared secret, then shells out to rebuild.sh.
|
|
// Run on the homeserver (NOT inside docker) on port 4321.
|
|
//
|
|
// WEBHOOK_PORT=4321 REPO_DIR=/opt/softvowels REBUILD_TOKEN=change-me node scripts/webhook.js
|
|
//
|
|
// Or via the included systemd unit (see scripts/softvowels-webhook.service).
|
|
|
|
import { createServer } from 'node:http';
|
|
import { spawn } from 'node:child_process';
|
|
import { writeFileSync } from 'node:fs';
|
|
|
|
const PORT = Number(process.env.WEBHOOK_PORT || 4321);
|
|
const TOKEN = process.env.REBUILD_TOKEN || process.env.ASTRO_REVALIDATE_TOKEN;
|
|
const REPO = process.env.REPO_DIR || '/opt/softvowels';
|
|
const SCRIPT = process.env.REBUILD_SCRIPT || `${REPO}/scripts/rebuild.sh`;
|
|
const LOG = process.env.LOG_FILE || '/var/log/softvowels-rebuild.log';
|
|
|
|
if (!TOKEN) {
|
|
console.error('REBUILD_TOKEN is required');
|
|
process.exit(1);
|
|
}
|
|
|
|
function log(line) {
|
|
const ts = new Date().toISOString();
|
|
const msg = `[${ts}] ${line}\n`;
|
|
try {
|
|
writeFileSync(LOG, msg, { flag: 'a' });
|
|
} catch {
|
|
/* noop */
|
|
}
|
|
process.stdout.write(msg);
|
|
}
|
|
|
|
function triggerRebuild(collection, op) {
|
|
log(`Trigger rebuild for ${collection}.${op}`);
|
|
const child = spawn('bash', [SCRIPT], { detached: true, stdio: 'ignore' });
|
|
child.unref();
|
|
}
|
|
|
|
const server = createServer((req, res) => {
|
|
if (req.method !== 'POST' || req.url === '/') {
|
|
res.writeHead(405);
|
|
res.end('Method Not Allowed');
|
|
return;
|
|
}
|
|
const url = new URL(req.url, 'http://x');
|
|
const secret = url.searchParams.get('secret');
|
|
const collection = url.searchParams.get('collection') ?? 'unknown';
|
|
const op = url.searchParams.get('op') ?? 'change';
|
|
if (secret !== TOKEN) {
|
|
log(`Bad secret from ${req.socket.remoteAddress}`);
|
|
res.writeHead(401);
|
|
res.end('Unauthorized');
|
|
return;
|
|
}
|
|
triggerRebuild(collection, op);
|
|
res.writeHead(202, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ ok: true, queued: true }));
|
|
});
|
|
|
|
server.listen(PORT, '127.0.0.1', () => {
|
|
log(`Webhook listening on http://127.0.0.1:${PORT}/__revalidate`);
|
|
});
|