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>
84 lines
3.7 KiB
JavaScript
84 lines
3.7 KiB
JavaScript
import { buildChangeApproval, buildRequestApproval } from './approvalCards.js';
|
|
|
|
export function createJiraProcessor({ config, requests, jiraService, webexService, log }) {
|
|
const { logger, logWarn, logError } = log;
|
|
const approvalRoomId = config.rooms.approval;
|
|
|
|
function handleApprovalNotifications(issueKey, jiraTicket, buildApprovalFn) {
|
|
buildApprovalFn(jiraTicket, log)
|
|
.then(approvalCard => jiraService.buildApprovers(issueKey).then(approvers => ({ approvalCard, approvers })))
|
|
.then(({ approvalCard, approvers }) => {
|
|
const cardPayload = {
|
|
text: approvalCard.message,
|
|
attachments: [{ contentType: 'application/vnd.microsoft.card.adaptive', content: approvalCard.card }],
|
|
};
|
|
for (const approver of approvers) {
|
|
logger('processJiraTicket', `Notifying ${issueKey} --> ${approver}`);
|
|
webexService.sendTicketCard(issueKey, { toPersonEmail: approver, ...cardPayload });
|
|
}
|
|
if (approvers.length > 0) {
|
|
webexService.sendTicketCard(issueKey, { roomId: approvalRoomId, ...cardPayload });
|
|
}
|
|
})
|
|
.catch(error => logError('processJiraTicket', `Failed approval notifications for ${issueKey}`, error));
|
|
}
|
|
|
|
function processJiraTicket(jiraTicket) {
|
|
if (!jiraTicket?.issue?.key) {
|
|
logError('processJiraTicket', 'Missing issue key in webhook payload');
|
|
return;
|
|
}
|
|
|
|
const issueKey = jiraTicket.issue.key;
|
|
let requestType;
|
|
let transitionId;
|
|
|
|
logger('processJiraTicket', `Processing ${issueKey}.`);
|
|
|
|
if (jiraTicket.transition) {
|
|
logger('processJiraTicket', `${issueKey} Transition: ${jiraTicket.transition.transitionId}.`);
|
|
const requestTypeField = jiraTicket.issue.fields?.customfield_10010;
|
|
if (requestTypeField?.requestType?.id) {
|
|
requestType = requestTypeField.requestType.id;
|
|
transitionId = jiraTicket.transition.transitionId;
|
|
} else {
|
|
logWarn('processJiraTicket', `${issueKey} - missing requestType: ${JSON.stringify(requestTypeField)}`);
|
|
}
|
|
}
|
|
|
|
if (!issueKey || !requestType || !requests[requestType]) {
|
|
return;
|
|
}
|
|
|
|
logger('processJiraTicket', `${issueKey} RequestType: ${requestType} Requests?: ${JSON.stringify(requests[requestType])}`);
|
|
|
|
if (requests[requestType].transitions[transitionId]) {
|
|
if (jiraTicket.issue.fields.project.key == 'CHANGE') {
|
|
logger('processJiraTicket', `${issueKey} is a CHANGE.`);
|
|
handleApprovalNotifications(issueKey, jiraTicket, buildChangeApproval);
|
|
} else if (jiraTicket.issue.fields.project.key == 'REQUEST') {
|
|
logger('processJiraTicket', `${issueKey} is a REQUEST.`);
|
|
handleApprovalNotifications(issueKey, jiraTicket, buildRequestApproval);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!jiraTicket.changelog) {
|
|
return;
|
|
}
|
|
|
|
const approvalStatuses = ['Pending Approval', 'Emergency Approval', 'Waiting for approval'];
|
|
for (const change of jiraTicket.changelog.items) {
|
|
if (change.field != 'Approvers' || !approvalStatuses.includes(jiraTicket.issue.fields.status.name)) {
|
|
continue;
|
|
}
|
|
if (jiraTicket.issue.fields.project.key == 'CHANGE') {
|
|
handleApprovalNotifications(issueKey, jiraTicket, buildChangeApproval);
|
|
} else {
|
|
handleApprovalNotifications(issueKey, jiraTicket, buildRequestApproval);
|
|
}
|
|
}
|
|
}
|
|
|
|
return { processJiraTicket };
|
|
}
|