Skip to content

Commit 316ad9d

Browse files
committed
Add an option to allow waiting until an analysis has been processed before finishing the Action.
1 parent 2ecc17d commit 316ad9d

8 files changed

Lines changed: 133 additions & 8 deletions

File tree

analyze/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ inputs:
5252
description: Whether to upload the resulting CodeQL database
5353
required: false
5454
default: "true"
55+
wait-for-processing:
56+
description: If true, the Action will wait for the uploaded SARIF to be processed before completing.
57+
required: false
5558
token:
5659
default: ${{ github.token }}
5760
matrix:

lib/upload-lib.js

Lines changed: 51 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: 65 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
@@ -390,10 +398,66 @@ async function uploadFiles(
390398
logger.debug(`Number of results in upload: ${numResultInSarif}`);
391399

392400
// Make the upload
393-
await uploadPayload(payload, repositoryNwo, apiDetails, logger);
401+
const sarifID = await uploadPayload(
402+
payload,
403+
repositoryNwo,
404+
apiDetails,
405+
logger
406+
);
394407

395408
logger.endGroup();
396409

410+
if (waitForProcessing) {
411+
logger.startGroup("Waiting for processing to finish");
412+
const client = api.getApiClient(apiDetails);
413+
414+
const statusCheckingStarted = Date.now();
415+
// eslint-disable-next-line no-constant-condition
416+
while (true) {
417+
if (
418+
Date.now() >
419+
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
420+
) {
421+
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
422+
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
423+
logger.warning(
424+
"Timed out waiting for analysis to finish processing. Continuing."
425+
);
426+
break;
427+
}
428+
// 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.
429+
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
430+
try {
431+
const response = await client.request(
432+
"GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id",
433+
{
434+
owner: repositoryNwo.owner,
435+
repo: repositoryNwo.repo,
436+
sarif_id: sarifID,
437+
}
438+
);
439+
const status = response.data.processing_status;
440+
logger.info(`Status is ${status}.`);
441+
if (status === "complete") {
442+
break;
443+
}
444+
} catch (e) {
445+
if (util.isHTTPError(e)) {
446+
switch (e.status) {
447+
case 404:
448+
logger.info("Analysis is not found yet...");
449+
break;
450+
default:
451+
throw e;
452+
}
453+
} else {
454+
throw e;
455+
}
456+
}
457+
}
458+
logger.endGroup();
459+
}
460+
397461
return {
398462
raw_upload_size_bytes: rawUploadSizeBytes,
399463
zipped_upload_size_bytes: zippedUploadSizeBytes,

src/util.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,7 @@ export async function bundleDb(
564564
}
565565
return databaseBundlePath;
566566
}
567+
568+
export async function delay(milliseconds: number) {
569+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
570+
}

upload-sarif/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ inputs:
2020
category:
2121
description: String used by Code Scanning for matching the analyses
2222
required: false
23+
wait-for-processing:
24+
description: If true, the Action will wait for the uploaded SARIF to be processed before completing.
25+
required: false
2326
runs:
2427
using: 'node12'
2528
main: '../lib/upload-sarif-action.js'

0 commit comments

Comments
 (0)