Skip to content

Commit dd9d5e4

Browse files
committed
Add an option to allow waiting until an analysis has been processed before finishing the Action.
1 parent a56f725 commit dd9d5e4

8 files changed

Lines changed: 115 additions & 8 deletions

File tree

analyze/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ inputs:
4242
description: Whether to upload the resulting CodeQL database
4343
required: false
4444
default: "true"
45+
wait-for-processing:
46+
description: If true, the Action will wait for the uploaded SARIF to be processed before completing.
47+
required: false
4548
token:
4649
default: ${{ github.token }}
4750
matrix:

lib/upload-lib.js

Lines changed: 41 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/upload-lib.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/util.js

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/util.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/upload-lib.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ async function uploadPayload(
110110

111111
logger.debug(`response status: ${response.status}`);
112112
logger.info("Successfully uploaded results");
113+
114+
return response.data.id;
113115
}
114116

115117
export interface UploadStatusReport {
@@ -159,6 +161,7 @@ export async function uploadFromActions(
159161
actionsUtil.getWorkflowRunID(),
160162
actionsUtil.getRequiredInput("checkout_path"),
161163
actionsUtil.getRequiredInput("matrix"),
164+
actionsUtil.getOptionalInput("wait-for-processing") === "true",
162165
gitHubVersion,
163166
apiDetails,
164167
logger
@@ -190,6 +193,7 @@ export async function uploadFromRunner(
190193
undefined,
191194
sourceRoot,
192195
undefined,
196+
false,
193197
gitHubVersion,
194198
apiDetails,
195199
logger
@@ -323,6 +327,9 @@ export function buildPayload(
323327
}
324328
}
325329

330+
const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
331+
const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
332+
326333
// Uploads the given set of sarif files.
327334
// Returns true iff the upload occurred and succeeded
328335
async function uploadFiles(
@@ -336,6 +343,7 @@ async function uploadFiles(
336343
workflowRunID: number | undefined,
337344
sourceRoot: string,
338345
environment: string | undefined,
346+
waitForProcessing: boolean,
339347
gitHubVersion: util.GitHubVersion,
340348
apiDetails: api.GitHubApiDetails,
341349
logger: Logger
@@ -399,10 +407,58 @@ async function uploadFiles(
399407
logger.debug(`Number of results in upload: ${numResultInSarif}`);
400408

401409
// Make the upload
402-
await uploadPayload(payload, repositoryNwo, apiDetails, logger);
410+
const sarifID = await uploadPayload(
411+
payload,
412+
repositoryNwo,
413+
apiDetails,
414+
logger
415+
);
403416

404417
logger.endGroup();
405418

419+
if (waitForProcessing) {
420+
logger.startGroup("Waiting for processing to finish");
421+
logger.info(`SARIF has identifier ${sarifID}.`)
422+
const client = api.getApiClient(apiDetails);
423+
424+
const statusCheckingStarted = Date.now();
425+
// eslint-disable-next-line no-constant-condition
426+
while (true) {
427+
if (
428+
Date.now() >
429+
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
430+
) {
431+
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
432+
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
433+
logger.warning(
434+
"Timed out waiting for analysis to finish processing. Continuing."
435+
);
436+
break;
437+
}
438+
// We put the delay at the start of the loop, since it's unlikely that the analysis will have succeeded immediately. We might as well wait preemptively.
439+
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
440+
const response = await client.request(
441+
"GET /repos/:owner/:repo/code-scanning/analyses",
442+
{
443+
owner: repositoryNwo.owner,
444+
repo: repositoryNwo.repo,
445+
sarif_id: sarifID,
446+
}
447+
);
448+
if (response.data.length === 0) {
449+
logger.info(`Analysis is still being processed...`);
450+
}
451+
else {
452+
const analysis = response.data[0];
453+
if (analysis.error) {
454+
throw new Error(`Processing of the uploaded SARIF file failed: ${analysis.error}`)
455+
}
456+
break;
457+
}
458+
}
459+
logger.endGroup();
460+
}
461+
406462
return {
407463
raw_upload_size_bytes: rawUploadSizeBytes,
408464
zipped_upload_size_bytes: zippedUploadSizeBytes,

src/util.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,7 @@ export async function codeQlVersionAbove(
516516
): Promise<boolean> {
517517
return semver.gte(await codeql.getVersion(), requiredVersion);
518518
}
519+
520+
export async function delay(milliseconds: number) {
521+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
522+
}

upload-sarif/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ inputs:
1717
category:
1818
description: String used by Code Scanning for matching the analyses
1919
required: false
20+
wait-for-processing:
21+
description: If true, the Action will wait for the uploaded SARIF to be processed before completing.
22+
required: false
2023
runs:
2124
using: 'node12'
2225
main: '../lib/upload-sarif-action.js'

0 commit comments

Comments
 (0)