137 lines
4.4 KiB
JavaScript
137 lines
4.4 KiB
JavaScript
// Webhook receiver for Gitea push events
|
|
// This service listens for webhook events from Gitea and triggers a deployment
|
|
// when changes are pushed to the monitored branches
|
|
|
|
const express = require('express');
|
|
const http = require('http');
|
|
const crypto = require('crypto');
|
|
const { exec } = require('child_process');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
// Configuration (can be moved to environment variables)
|
|
const config = {
|
|
port: process.env.WEBHOOK_PORT || 9000,
|
|
secret: process.env.WEBHOOK_SECRET || 'change-this-secret-in-production',
|
|
deployScript: process.env.DEPLOY_SCRIPT || path.join(__dirname, 'webhook-deploy.sh'),
|
|
logFile: process.env.LOG_FILE || path.join(__dirname, '../logs/webhook.log'),
|
|
allowedBranches: (process.env.ALLOWED_BRANCHES || 'main,master').split(','),
|
|
allowedRepositories: (process.env.ALLOWED_REPOSITORIES || 'mwhitnessing').split(',')
|
|
};
|
|
|
|
// Create logs directory if it doesn't exist
|
|
const logsDir = path.dirname(config.logFile);
|
|
if (!fs.existsSync(logsDir)) {
|
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
}
|
|
|
|
// Create Express app
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
// Helper function to log messages
|
|
function log(message) {
|
|
const timestamp = new Date().toISOString();
|
|
const logMessage = `[${timestamp}] ${message}\n`;
|
|
console.log(logMessage.trim());
|
|
fs.appendFileSync(config.logFile, logMessage);
|
|
}
|
|
|
|
// Verify Gitea webhook signature
|
|
function verifySignature(req) {
|
|
const signature = req.headers['x-gitea-signature'];
|
|
if (!signature) {
|
|
return false;
|
|
}
|
|
|
|
const hmac = crypto.createHmac('sha256', config.secret);
|
|
const computedSignature = hmac.update(JSON.stringify(req.body)).digest('hex');
|
|
|
|
return crypto.timingSafeEqual(
|
|
Buffer.from(signature),
|
|
Buffer.from(computedSignature)
|
|
);
|
|
}
|
|
|
|
// Handle Gitea push webhook
|
|
app.post('/webhook', (req, res) => {
|
|
// Log receipt of webhook
|
|
log('Received webhook request');
|
|
|
|
try {
|
|
// Check if webhook signature is valid
|
|
if (!verifySignature(req)) {
|
|
log('Invalid webhook signature');
|
|
return res.status(403).send('Invalid signature');
|
|
}
|
|
|
|
// Extract relevant information from the webhook payload
|
|
const { ref, repository } = req.body;
|
|
|
|
// Check if this is a branch we care about
|
|
const branchName = ref.replace('refs/heads/', '');
|
|
if (!config.allowedBranches.includes(branchName)) {
|
|
log(`Ignoring push to branch: ${branchName}`);
|
|
return res.status(200).send('Ignored branch');
|
|
}
|
|
|
|
// Check if this is a repository we care about
|
|
const repoName = repository.name;
|
|
if (!config.allowedRepositories.includes(repoName)) {
|
|
log(`Ignoring push to repository: ${repoName}`);
|
|
return res.status(200).send('Ignored repository');
|
|
}
|
|
|
|
// Log the event
|
|
log(`Received push event for ${repoName}/${branchName}`);
|
|
|
|
// Respond to webhook immediately
|
|
res.status(200).send('Processing deployment');
|
|
|
|
// Execute the deployment script with the branch name
|
|
const command = `${config.deployScript} ${branchName}`;
|
|
log(`Executing: ${command}`);
|
|
|
|
exec(command, (error, stdout, stderr) => {
|
|
if (error) {
|
|
log(`Deployment error: ${error.message}`);
|
|
return;
|
|
}
|
|
if (stderr) {
|
|
log(`Deployment stderr: ${stderr}`);
|
|
}
|
|
log(`Deployment stdout: ${stdout}`);
|
|
log('Deployment completed successfully');
|
|
});
|
|
} catch (error) {
|
|
log(`Error processing webhook: ${error.message}`);
|
|
if (!res.headersSent) {
|
|
res.status(500).send('Error processing webhook');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Start the server
|
|
const server = http.createServer(app);
|
|
server.listen(config.port, () => {
|
|
log(`Webhook receiver listening on port ${config.port}`);
|
|
log(`Monitoring branches: ${config.allowedBranches.join(', ')}`);
|
|
log(`Monitoring repositories: ${config.allowedRepositories.join(', ')}`);
|
|
});
|
|
|
|
// Handle server shutdown
|
|
process.on('SIGTERM', () => {
|
|
log('Shutting down webhook receiver...');
|
|
server.close(() => {
|
|
log('Webhook receiver stopped');
|
|
process.exit(0);
|
|
});
|
|
});
|
|
|
|
process.on('SIGINT', () => {
|
|
log('Shutting down webhook receiver...');
|
|
server.close(() => {
|
|
log('Webhook receiver stopped');
|
|
process.exit(0);
|
|
});
|
|
});
|