Files
whale-town-end/webhook-handler.js.example
moyin a907e64f40 feat: 添加生产环境部署配置
- 添加 Dockerfile 和 docker-compose.yml 支持容器化部署
- 添加 PM2 配置文件 ecosystem.config.js
- 添加部署脚本模板 deploy.sh.example
- 添加 Gitea webhook 处理器模板 webhook-handler.js.example
- 添加生产环境配置模板 .env.production.example
- 添加详细的部署指南 DEPLOYMENT.md
- 更新 .gitignore 排除敏感配置文件
2025-12-17 15:37:40 +08:00

86 lines
2.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const http = require('http');
const crypto = require('crypto');
const { exec } = require('child_process');
// 配置 - 复制此文件为 webhook-handler.js 并修改配置
const PORT = 9000;
const SECRET = 'your_webhook_secret_change_this'; // 与 Gitea 中配置的密钥一致
const DEPLOY_SCRIPT = '/var/www/pixel-game-server/deploy.sh'; // 修改为实际路径
// 验证 Gitea 签名
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload);
const calculatedSignature = hmac.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(calculatedSignature, 'hex')
);
}
// 创建 HTTP 服务器
const server = http.createServer((req, res) => {
if (req.method !== 'POST') {
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('Method Not Allowed');
return;
}
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
try {
// 验证签名
const signature = req.headers['x-gitea-signature'];
if (!signature || !verifySignature(body, signature.replace('sha256=', ''), SECRET)) {
console.log('签名验证失败');
res.writeHead(401, { 'Content-Type': 'text/plain' });
res.end('Unauthorized');
return;
}
const payload = JSON.parse(body);
// 检查是否是推送到 main 分支
if (payload.ref === 'refs/heads/main') {
console.log('收到 main 分支推送,开始部署...');
// 执行部署脚本
exec(`bash ${DEPLOY_SCRIPT}`, (error, stdout, stderr) => {
if (error) {
console.error('部署失败:', error);
console.error('stderr:', stderr);
} else {
console.log('部署成功:', stdout);
}
});
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Deployment triggered');
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Not main branch, ignored');
}
} catch (error) {
console.error('处理 webhook 失败:', error);
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Internal Server Error');
}
});
});
server.listen(PORT, () => {
console.log(`Webhook 处理器运行在端口 ${PORT}`);
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到 SIGTERM正在关闭服务器...');
server.close(() => {
console.log('服务器已关闭');
process.exit(0);
});
});