Skip to content

Commit

Permalink
ARC-2643 allow multi workflow entries in audit log during backfill (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
gxueatlassian authored Nov 28, 2023
1 parent f3ca644 commit 3d3521f
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/github/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const processBranch = async (
operationType: "NORMAL",
auditLogsource: "WEBHOOK",
entityAction: "BRANCH_CREATE",
subscriptionId: subscription?.id
subscriptionId: subscription?.id || 0
});

emitWebhookProcessedMetrics(
Expand Down
2 changes: 1 addition & 1 deletion src/github/pull-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const pullRequestWebhookHandler = async (context: WebhookContext, jiraCli
operationType: "NORMAL",
auditLogsource: "WEBHOOK",
entityAction: context?.name === "pull_request_review" ? "PR_REVIEW" : `PR_${context?.action?.toUpperCase()}`,
subscriptionId: subscription?.id
subscriptionId: subscription.id
});
const { webhookReceived, name, log } = context;

Expand Down
2 changes: 1 addition & 1 deletion src/github/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const workflowWebhookHandler = async (context: WebhookContext, jiraClient
operationType: "NORMAL",
auditLogsource: "WEBHOOK",
entityAction: `WORKFLOW_RUN_${context.action}`.toUpperCase(),
subscriptionId: subscription?.id
subscriptionId: subscription.id
});
const { webhookReceived, name, log } = context;

Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/jira.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,6 @@ export interface JiraSubmitOptions {
preventTransitions: boolean;
operationType: JiraOperationType;
auditLogsource: AuditLogSourceType;
entityAction?: AuditEntityType;
subscriptionId?: number;
entityAction: AuditEntityType;
subscriptionId: number;
}
102 changes: 82 additions & 20 deletions src/jira/client/jira-client-audit-log-helper.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { processBatchedBulkUpdateResp, processWorkflowSubmitResp } from "./jira-client-audit-log-helper";
import { getLogger } from "config/logger";
import { JiraSubmitOptions } from "interfaces/jira";

describe("processBatchedBulkUpdateResp", () => {
const mockLogger = getLogger("mock-logger");
Expand Down Expand Up @@ -421,17 +422,17 @@ describe("processBatchedBulkUpdateResp", () => {
describe("processWorkflowSubmitResp", () => {
const mockLogger = getLogger("mock-logger");
it("should return isSuccess as false when status code is anything other than 202", () => {
const reqBuildData = {
const reqBuildDataArray = [{
schemaVersion: "1.0",
pipelineId: 77164279,
pipelineId: "77164279",
buildNumber: 6,
updateSequenceNumber: 1700991428371,
displayName: "CI",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-5"]
};
}];
const response = {
status: 400,
data: {
Expand All @@ -440,10 +441,10 @@ describe("processWorkflowSubmitResp", () => {
rejectedBuilds: []
}
};
const options = { preventTransitions:false, operationType: "WEBHOOK", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };
const options: JiraSubmitOptions = { preventTransitions:false, operationType: "NORMAL", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };

const result = processWorkflowSubmitResp({
reqBuildData,
reqBuildDataArray,
response,
options,
logger: mockLogger
Expand All @@ -454,17 +455,17 @@ describe("processWorkflowSubmitResp", () => {
});
});
it("should return isSuccess as false when status code is 202 but there is no acceptedBuilds", () => {
const reqBuildData = {
const reqBuildDataArray = [{
schemaVersion: "1.0",
pipelineId: 77164279,
pipelineId: "77164279",
buildNumber: 6,
updateSequenceNumber: 1700991428371,
displayName: "CI",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-5"]
};
}];
const response = {
status: 202,
data: {
Expand All @@ -473,10 +474,10 @@ describe("processWorkflowSubmitResp", () => {
rejectedBuilds: []
}
};
const options = { preventTransitions:false, operationType: "WEBHOOK", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };
const options: JiraSubmitOptions = { preventTransitions:false, operationType: "NORMAL", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };

const result = processWorkflowSubmitResp({
reqBuildData,
reqBuildDataArray,
response,
options,
logger: mockLogger
Expand All @@ -487,17 +488,17 @@ describe("processWorkflowSubmitResp", () => {
});
});
it("should return isSuccess as true when status code is 202 and there are/is acceptedBuilds but the result has rejectedBuilds as well", () => {
const reqBuildData = {
const reqBuildDataArray = [{
schemaVersion: "1.0",
pipelineId: 77164279,
pipelineId: "77164279",
buildNumber: 6,
updateSequenceNumber: 1700991428371,
displayName: "CI",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-5"]
};
}];
const response = {
status: 202,
data: {
Expand All @@ -506,10 +507,10 @@ describe("processWorkflowSubmitResp", () => {
rejectedBuilds: [{ pipelineId: "11223434", buildNumber: 10 }]
}
};
const options = { preventTransitions:false, operationType: "WEBHOOK", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };
const options: JiraSubmitOptions = { preventTransitions:false, operationType: "NORMAL", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };

const result = processWorkflowSubmitResp({
reqBuildData,
reqBuildDataArray,
response,
options,
logger: mockLogger
Expand All @@ -529,17 +530,17 @@ describe("processWorkflowSubmitResp", () => {
});
});
it("should extract the build with 2 issue keys linked - audit info for logging", () => {
const reqBuildData = {
const reqBuildDataArray = [{
schemaVersion: "1.0",
pipelineId: 77164279,
pipelineId: "77164279",
buildNumber: 6,
updateSequenceNumber: 1700991428371,
displayName: "CI",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-5", "KAM-6"]
};
}];
const response = {
status: 202,
data: {
Expand All @@ -548,10 +549,10 @@ describe("processWorkflowSubmitResp", () => {
rejectedBuilds: []
}
};
const options = { preventTransitions:false, operationType: "WEBHOOK", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };
const options: JiraSubmitOptions = { preventTransitions:false, operationType: "NORMAL", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };

const result = processWorkflowSubmitResp({
reqBuildData,
reqBuildDataArray,
response,
options,
logger: mockLogger
Expand Down Expand Up @@ -579,4 +580,65 @@ describe("processWorkflowSubmitResp", () => {
}]
});
});
it("should extract the two builds with 1 issue keys linked - audit info for logging", () => {
const reqBuildDataArray = [{
schemaVersion: "1.0",
pipelineId: "77164279",
buildNumber: 6,
updateSequenceNumber: 1700991428371,
displayName: "CI",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-5"]
}, {
schemaVersion: "1.0",
pipelineId: "77164280",
buildNumber: 7,
updateSequenceNumber: 1700991428372,
displayName: "CI2",
url: "https://github.com/kamaOrgOne/repo_react/actions/runs/6994742701",
state: "successful",
lastUpdated: "2023-11-26T09:37:07Z",
issueKeys: ["KAM-6"]
}];
const response = {
status: 202,
data: {
unknownIssueKeys: [],
acceptedBuilds: [{ pipelineId: "77164279", buildNumber: 6 }, { pipelineId: "77164280", buildNumber: 7 }],
rejectedBuilds: []
}
};
const options: JiraSubmitOptions = { preventTransitions:false, operationType: "NORMAL", auditLogsource: "WEBHOOK", entityAction: "WORKFLOW_RUN", subscriptionId: 1122334455 };

const result = processWorkflowSubmitResp({
reqBuildDataArray,
response,
options,
logger: mockLogger
});

expect(result).toEqual({
isSuccess: true,
auditInfo:[{
"createdAt": expect.anything(),
"entityAction": "WORKFLOW_RUN",
"entityId": "6_77164279",
"entityType": "builds",
"issueKey": "KAM-5",
"source": "WEBHOOK",
"subscriptionId": 1122334455
},
{
"createdAt": expect.anything(),
"entityAction": "WORKFLOW_RUN",
"entityId": "7_77164280",
"entityType": "builds",
"issueKey": "KAM-6",
"source": "WEBHOOK",
"subscriptionId": 1122334455
}]
});
});
});
74 changes: 49 additions & 25 deletions src/jira/client/jira-client-audit-log-helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { AuditInfo, saveAuditLog } from "../../services/audit-log-service";
import { isArray, isObject } from "lodash";
import {
JiraBuild,
JiraSubmitOptions
} from "interfaces/jira";
import Logger from "bunyan";

const getAuditInfo = ({
acceptedGithubEntities,
Expand Down Expand Up @@ -99,10 +104,15 @@ export const processBatchedBulkUpdateResp = ({
};

export const processWorkflowSubmitResp = ({
reqBuildData,
reqBuildDataArray,
response,
options,
logger
}: {
reqBuildDataArray: JiraBuild[],
response: { status: number, data: any },
options: JiraSubmitOptions,
logger: Logger
}): {
isSuccess: boolean;
auditInfo?: Array<AuditInfo>;
Expand All @@ -116,27 +126,29 @@ export const processWorkflowSubmitResp = ({
acceptedBuilds.length > 0;
const auditInfo: Array<AuditInfo> = [];
if (isSuccess && hasAcceptedBuilds) {
const reqBuildNo = reqBuildData.buildNumber;
const reqBuildPipelineId = reqBuildData.pipelineId;
const createdAt = new Date();
const acceptedBuildFound = acceptedBuilds.some(acceptedBuild => acceptedBuild?.buildNumber.toString() === reqBuildNo.toString() && acceptedBuild.pipelineId.toString() === reqBuildPipelineId.toString());
if (acceptedBuildFound) {
const issueKeys = reqBuildData?.issueKeys;
issueKeys.map((issueKey) => {
const obj: AuditInfo = {
createdAt,
entityId: `${reqBuildNo}_${reqBuildPipelineId}`,
entityType: "builds",
issueKey,
subscriptionId: options?.subscriptionId,
source: options?.auditLogsource || "WEBHOOK",
entityAction: options?.entityAction || "null"
};
if (obj.subscriptionId && obj.entityId) {
auditInfo.push(obj);
}
});
}
reqBuildDataArray.forEach((reqBuildData) => {
const reqBuildNo = reqBuildData.buildNumber;
const reqBuildPipelineId = reqBuildData.pipelineId;
const createdAt = new Date();
const acceptedBuildFound = acceptedBuilds.some(acceptedBuild => acceptedBuild?.buildNumber.toString() === reqBuildNo.toString() && acceptedBuild.pipelineId.toString() === reqBuildPipelineId.toString());
if (acceptedBuildFound) {
const issueKeys = reqBuildData?.issueKeys;
issueKeys.map((issueKey) => {
const obj: AuditInfo = {
createdAt,
entityId: `${reqBuildNo}_${reqBuildPipelineId}`,
entityType: "builds",
issueKey,
subscriptionId: options.subscriptionId,
source: options.auditLogsource || "WEBHOOK",
entityAction: options.entityAction || "null"
};
if (obj.subscriptionId && obj.entityId) {
auditInfo.push(obj);
}
});
}
});
return { isSuccess: true, auditInfo };
}
return { isSuccess: false };
Expand Down Expand Up @@ -168,12 +180,24 @@ export const processAuditLogsForDevInfoBulkUpdate = ({ reqRepoData, response, op
}
};

export const processAuditLogsForWorkflowSubmit = ({ reqBuildData, response, options, logger }) => {
export const processAuditLogsForWorkflowSubmit = (
{ reqBuildDataArray, response, options, logger }: {
reqBuildDataArray: JiraBuild[],
response: { status: number, data: any },
options: JiraSubmitOptions,
logger: Logger
}
) => {
try {

if (!options) {
logger.debug("Skip sending to audit log as options are undefined");
}

const { isSuccess, auditInfo } = processWorkflowSubmitResp({
reqBuildData,
reqBuildDataArray,
response,
options,
options: options,
logger
});
if (isSuccess) {
Expand Down
2 changes: 1 addition & 1 deletion src/jira/client/jira-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ describe("Test getting a jira client", () => {

const response = await client.workflow.submit({
builds: [{}]
});
}, {});

expect(response).toEqual({
status: 200,
Expand Down
9 changes: 5 additions & 4 deletions src/jira/client/jira-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { createHashWithSharedSecret } from "utils/encryption";
import {
JiraAssociation,
JiraBuildBulkSubmitData,
JiraBuild,
JiraCommit,
JiraDeploymentBulkSubmitData,
JiraIssue,
Expand Down Expand Up @@ -72,7 +73,7 @@ export interface JiraClient {
},
},
workflow: {
submit: (data: JiraBuildBulkSubmitData, repositoryId: number, options?: JiraSubmitOptions) => Promise<any>;
submit: (data: JiraBuildBulkSubmitData, repositoryId: number, options: JiraSubmitOptions) => Promise<any>;
},
deployment: {
submit: (
Expand Down Expand Up @@ -382,7 +383,7 @@ export const getJiraClient = async (
}
},
workflow: {
submit: async (data: JiraBuildBulkSubmitData, repositoryId: number, options?: JiraSubmitOptions) => {
submit: async (data: JiraBuildBulkSubmitData, repositoryId: number, options: JiraSubmitOptions) => {
updateIssueKeysFor(data.builds, uniq);
if (!withinIssueKeyLimit(data.builds)) {
logger.warn({
Expand Down Expand Up @@ -411,9 +412,9 @@ export const getJiraClient = async (
status: response.status,
data:response.data
};
const reqBuildData = data?.builds[0];
const reqBuildDataArray: JiraBuild[] = data?.builds || [];
if (await booleanFlag(BooleanFlags.USE_DYNAMODB_TO_PERSIST_AUDIT_LOG, jiraHost)) {
processAuditLogsForWorkflowSubmit({ reqBuildData, response:responseData, options, logger });
processAuditLogsForWorkflowSubmit({ reqBuildDataArray, response:responseData, options, logger });
}
return response;
}
Expand Down

0 comments on commit 3d3521f

Please sign in to comment.