fix(deploy): improve webhook auto-release reliability and deploy.sh defaults
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,7 +14,7 @@ function loadEnv() {
|
||||
const envPath = join(__dirname, 'auto-release.env');
|
||||
if (!existsSync(envPath)) return;
|
||||
for (const line of readFileSync(envPath, 'utf8').split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
const trimmed = line.replace(/\r$/, '').trim();
|
||||
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||
const eq = trimmed.indexOf('=');
|
||||
if (eq === -1) continue;
|
||||
@@ -31,10 +31,14 @@ loadEnv();
|
||||
|
||||
const PORT = Number(process.env.DEPLOY_WEBHOOK_PORT || 8095);
|
||||
const HOST = process.env.DEPLOY_WEBHOOK_HOST || '127.0.0.1';
|
||||
const SECRET = process.env.DEPLOY_WEBHOOK_SECRET || '';
|
||||
const SECRET = (process.env.DEPLOY_WEBHOOK_SECRET || '').replace(/\r$/, '').trim();
|
||||
const ALLOWED_REF = process.env.DEPLOY_GIT_REF || 'refs/heads/dev';
|
||||
const APP_ROOT = process.env.APP_ROOT || '/opt/dukang-haoke';
|
||||
const RELEASE_SCRIPT = join(APP_ROOT, 'deploy', 'auto-release.sh');
|
||||
const DEBOUNCE_MS = Number(process.env.DEPLOY_WEBHOOK_DEBOUNCE_MS || 15000);
|
||||
|
||||
let lastTriggerAt = 0;
|
||||
let lastTriggerRef = '';
|
||||
|
||||
function readBody(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -61,12 +65,21 @@ function json(res, status, data) {
|
||||
}
|
||||
|
||||
function triggerRelease(trigger) {
|
||||
const now = Date.now();
|
||||
if (now - lastTriggerAt < DEBOUNCE_MS && lastTriggerRef === trigger) {
|
||||
console.log(`[webhook] debounced duplicate trigger ref=${trigger}`);
|
||||
return false;
|
||||
}
|
||||
lastTriggerAt = now;
|
||||
lastTriggerRef = trigger;
|
||||
console.log(`[webhook] trigger deploy ref=${trigger}`);
|
||||
const child = spawn('bash', [RELEASE_SCRIPT], {
|
||||
detached: true,
|
||||
stdio: 'ignore',
|
||||
env: { ...process.env, DEPLOY_TRIGGER: trigger },
|
||||
});
|
||||
child.unref();
|
||||
return true;
|
||||
}
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
@@ -86,6 +99,7 @@ const server = http.createServer(async (req, res) => {
|
||||
|
||||
const token = getToken(req);
|
||||
if (token !== SECRET) {
|
||||
console.log(`[webhook] rejected invalid token from ${req.headers['x-real-ip'] || req.socket.remoteAddress || 'unknown'}`);
|
||||
return json(res, 403, { ok: false, message: 'invalid token' });
|
||||
}
|
||||
|
||||
@@ -99,6 +113,7 @@ const server = http.createServer(async (req, res) => {
|
||||
|
||||
const ref = payload.ref || payload.object_attributes?.ref || '';
|
||||
if (ref && ref !== ALLOWED_REF) {
|
||||
console.log(`[webhook] ignored ref=${ref} (allowed=${ALLOWED_REF})`);
|
||||
return json(res, 200, {
|
||||
ok: true,
|
||||
skipped: true,
|
||||
@@ -106,11 +121,12 @@ const server = http.createServer(async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
triggerRelease(ref || 'manual');
|
||||
const started = triggerRelease(ref || 'manual');
|
||||
return json(res, 202, {
|
||||
ok: true,
|
||||
accepted: true,
|
||||
message: 'deploy started',
|
||||
started,
|
||||
message: started ? 'deploy started' : 'deploy debounced (duplicate webhook)',
|
||||
ref: ref || ALLOWED_REF,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user