Stabilize logging, correlation IDs, service-account Jira auth, and direct approver reminder DMs while splitting the monolith into focused modules with Compose-based deployment. Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
2.5 KiB
JavaScript
68 lines
2.5 KiB
JavaScript
import { validateJiraWebhook, validateSupportWebhook } from '../lib/validate.js';
|
|
|
|
const WEBHOOK_LOG_PROVIDERS = {
|
|
'jira-request': 'jira',
|
|
request: 'request',
|
|
};
|
|
|
|
export function createWebhookRoutes({ config, jiraProcessor, webexService, log }) {
|
|
const { logger, logWarn, safeProcess, logFile, runWithCorrelationId, createCorrelationId } = log;
|
|
|
|
function healthCheck(req, res) {
|
|
res.status(200).json({ status: 'alive' });
|
|
}
|
|
|
|
function handleJiraWebhook(routeName, req, res) {
|
|
res.status(201).send();
|
|
const validation = validateJiraWebhook(req.body);
|
|
const correlationMeta = { routeName, issueKey: validation.issueKey || req.body?.issue?.key };
|
|
|
|
if (!validation.valid) {
|
|
runWithCorrelationId(createCorrelationId(correlationMeta), () => {
|
|
logWarn(routeName, `Invalid webhook payload: ${validation.error}`);
|
|
});
|
|
return;
|
|
}
|
|
|
|
safeProcess(routeName, () => {
|
|
logFile(WEBHOOK_LOG_PROVIDERS[routeName] || routeName, req.body);
|
|
jiraProcessor.processJiraTicket(req.body);
|
|
}, correlationMeta);
|
|
}
|
|
|
|
function registerRoutes(app) {
|
|
app.get('/healthCheck', healthCheck);
|
|
app.get('/heathCheck', healthCheck);
|
|
|
|
app.post('/jira-request', (req, res) => handleJiraWebhook('jira-request', req, res));
|
|
app.post('/request', (req, res) => handleJiraWebhook('request', req, res));
|
|
|
|
app.post('/support', (req, res) => {
|
|
res.status(201).send();
|
|
const validation = validateSupportWebhook(req.body);
|
|
const correlationMeta = { routeName: 'support', issueKey: validation.issueKey || req.body?.issue?.key };
|
|
|
|
if (!validation.valid) {
|
|
runWithCorrelationId(createCorrelationId(correlationMeta), () => {
|
|
logWarn('support', `Invalid webhook payload: ${validation.error}`);
|
|
});
|
|
return;
|
|
}
|
|
|
|
safeProcess('support', () => {
|
|
logFile('support', req.body);
|
|
logger('support', `Received support webhook for ${validation.issueKey}`);
|
|
webexService.processHighSeverity(req.body, config.rooms.support);
|
|
}, correlationMeta);
|
|
});
|
|
|
|
app.use((err, req, res, next) => {
|
|
log.logError('express', `${req.method} ${req.path}`, err);
|
|
if (!res.headersSent) {
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
}
|
|
|
|
return { registerRoutes };
|
|
}
|