Split out waiting for processing.
This commit is contained in:
parent
e0b9b9a248
commit
4eef7ef32c
9 changed files with 185 additions and 134 deletions
15
lib/analyze-action.js
generated
15
lib/analyze-action.js
generated
|
|
@ -50,7 +50,7 @@ async function sendStatusReport(startedAt, stats, error) {
|
||||||
exports.sendStatusReport = sendStatusReport;
|
exports.sendStatusReport = sendStatusReport;
|
||||||
async function run() {
|
async function run() {
|
||||||
const startedAt = new Date();
|
const startedAt = new Date();
|
||||||
let uploadStats = undefined;
|
let uploadResult = undefined;
|
||||||
let runStats = undefined;
|
let runStats = undefined;
|
||||||
let config = undefined;
|
let config = undefined;
|
||||||
util.initializeEnvironment(util.Mode.actions, pkg.version);
|
util.initializeEnvironment(util.Mode.actions, pkg.version);
|
||||||
|
|
@ -105,13 +105,17 @@ async function run() {
|
||||||
}
|
}
|
||||||
core.setOutput("db-locations", dbLocations);
|
core.setOutput("db-locations", dbLocations);
|
||||||
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
||||||
uploadStats = await upload_lib.uploadFromActions(outputDir, config.gitHubVersion, apiDetails, logger);
|
uploadResult = await upload_lib.uploadFromActions(outputDir, config.gitHubVersion, apiDetails, logger);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger.info("Not uploading results");
|
logger.info("Not uploading results");
|
||||||
}
|
}
|
||||||
const repositoryNwo = (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY"));
|
const repositoryNwo = (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY"));
|
||||||
await (0, database_upload_1.uploadDatabases)(repositoryNwo, config, apiDetails, logger); // Possibly upload the database bundles for remote queries
|
await (0, database_upload_1.uploadDatabases)(repositoryNwo, config, apiDetails, logger); // Possibly upload the database bundles for remote queries
|
||||||
|
if (uploadResult !== undefined &&
|
||||||
|
actionsUtil.getRequiredInput("wait-for-processing") === "true") {
|
||||||
|
await upload_lib.waitForProcessing((0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), uploadResult.sarifID, apiDetails, (0, logging_1.getActionsLogger)());
|
||||||
|
}
|
||||||
if (config.debugMode) {
|
if (config.debugMode) {
|
||||||
// Upload the database bundles as an Actions artifact for debugging
|
// Upload the database bundles as an Actions artifact for debugging
|
||||||
const toUpload = [];
|
const toUpload = [];
|
||||||
|
|
@ -156,8 +160,11 @@ async function run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runStats && uploadStats) {
|
if (runStats && uploadResult) {
|
||||||
await sendStatusReport(startedAt, { ...runStats, ...uploadStats });
|
await sendStatusReport(startedAt, {
|
||||||
|
...runStats,
|
||||||
|
...uploadResult.statusReport,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (runStats) {
|
else if (runStats) {
|
||||||
await sendStatusReport(startedAt, { ...runStats });
|
await sendStatusReport(startedAt, { ...runStats });
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
117
lib/upload-lib.js
generated
117
lib/upload-lib.js
generated
|
|
@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.validateUniqueCategory = exports.buildPayload = exports.validateSarifFileSchema = exports.countResultsInSarif = exports.uploadFromRunner = exports.uploadFromActions = exports.findSarifFilesInDir = exports.populateRunAutomationDetails = exports.combineSarifFiles = void 0;
|
exports.validateUniqueCategory = exports.waitForProcessing = exports.buildPayload = exports.validateSarifFileSchema = exports.countResultsInSarif = exports.uploadFromRunner = exports.uploadFromActions = exports.findSarifFilesInDir = exports.populateRunAutomationDetails = exports.combineSarifFiles = void 0;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const zlib_1 = __importDefault(require("zlib"));
|
const zlib_1 = __importDefault(require("zlib"));
|
||||||
|
|
@ -130,14 +130,14 @@ exports.findSarifFilesInDir = findSarifFilesInDir;
|
||||||
// depending on what the path happens to refer to.
|
// depending on what the path happens to refer to.
|
||||||
// Returns true iff the upload occurred and succeeded
|
// Returns true iff the upload occurred and succeeded
|
||||||
async function uploadFromActions(sarifPath, gitHubVersion, apiDetails, logger) {
|
async function uploadFromActions(sarifPath, gitHubVersion, apiDetails, logger) {
|
||||||
return await uploadFiles(getSarifFilePaths(sarifPath), (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), await actionsUtil.getCommitOid(), await actionsUtil.getRef(), await actionsUtil.getAnalysisKey(), actionsUtil.getOptionalInput("category"), util.getRequiredEnvParam("GITHUB_WORKFLOW"), actionsUtil.getWorkflowRunID(), actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getRequiredInput("matrix"), actionsUtil.getRequiredInput("wait-for-processing") === "true", gitHubVersion, apiDetails, logger);
|
return await uploadFiles(getSarifFilePaths(sarifPath), (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), await actionsUtil.getCommitOid(), await actionsUtil.getRef(), await actionsUtil.getAnalysisKey(), actionsUtil.getOptionalInput("category"), util.getRequiredEnvParam("GITHUB_WORKFLOW"), actionsUtil.getWorkflowRunID(), actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getRequiredInput("matrix"), gitHubVersion, apiDetails, logger);
|
||||||
}
|
}
|
||||||
exports.uploadFromActions = uploadFromActions;
|
exports.uploadFromActions = uploadFromActions;
|
||||||
// Uploads a single sarif file or a directory of sarif files
|
// Uploads a single sarif file or a directory of sarif files
|
||||||
// depending on what the path happens to refer to.
|
// depending on what the path happens to refer to.
|
||||||
// Returns true iff the upload occurred and succeeded
|
// Returns true iff the upload occurred and succeeded
|
||||||
async function uploadFromRunner(sarifPath, repositoryNwo, commitOid, ref, category, sourceRoot, gitHubVersion, apiDetails, logger) {
|
async function uploadFromRunner(sarifPath, repositoryNwo, commitOid, ref, category, sourceRoot, gitHubVersion, apiDetails, logger) {
|
||||||
return await uploadFiles(getSarifFilePaths(sarifPath), repositoryNwo, commitOid, ref, undefined, category, undefined, undefined, sourceRoot, undefined, false, gitHubVersion, apiDetails, logger);
|
return await uploadFiles(getSarifFilePaths(sarifPath), repositoryNwo, commitOid, ref, undefined, category, undefined, undefined, sourceRoot, undefined, gitHubVersion, apiDetails, logger);
|
||||||
}
|
}
|
||||||
exports.uploadFromRunner = uploadFromRunner;
|
exports.uploadFromRunner = uploadFromRunner;
|
||||||
function getSarifFilePaths(sarifPath) {
|
function getSarifFilePaths(sarifPath) {
|
||||||
|
|
@ -239,11 +239,9 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.buildPayload = buildPayload;
|
exports.buildPayload = buildPayload;
|
||||||
const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
|
|
||||||
const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
|
|
||||||
// Uploads the given set of sarif files.
|
// Uploads the given set of sarif files.
|
||||||
// Returns true iff the upload occurred and succeeded
|
// Returns true iff the upload occurred and succeeded
|
||||||
async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKey, category, analysisName, workflowRunID, sourceRoot, environment, waitForProcessing, gitHubVersion, apiDetails, logger) {
|
async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKey, category, analysisName, workflowRunID, sourceRoot, environment, gitHubVersion, apiDetails, logger) {
|
||||||
logger.startGroup("Uploading results");
|
logger.startGroup("Uploading results");
|
||||||
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
||||||
validateUniqueCategory(category);
|
validateUniqueCategory(category);
|
||||||
|
|
@ -268,59 +266,66 @@ async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKe
|
||||||
// Make the upload
|
// Make the upload
|
||||||
const sarifID = await uploadPayload(payload, repositoryNwo, apiDetails, logger);
|
const sarifID = await uploadPayload(payload, repositoryNwo, apiDetails, logger);
|
||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
if (waitForProcessing) {
|
|
||||||
logger.startGroup("Waiting for processing to finish");
|
|
||||||
const client = api.getApiClient(apiDetails);
|
|
||||||
const statusCheckingStarted = Date.now();
|
|
||||||
// eslint-disable-next-line no-constant-condition
|
|
||||||
while (true) {
|
|
||||||
if (Date.now() >
|
|
||||||
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS) {
|
|
||||||
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
|
|
||||||
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
|
|
||||||
logger.warning("Timed out waiting for analysis to finish processing. Continuing.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 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.
|
|
||||||
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
|
|
||||||
try {
|
|
||||||
const response = await client.request("GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id", {
|
|
||||||
owner: repositoryNwo.owner,
|
|
||||||
repo: repositoryNwo.repo,
|
|
||||||
sarif_id: sarifID,
|
|
||||||
});
|
|
||||||
const status = response.data.processing_status;
|
|
||||||
logger.info(`Analysis upload status is ${status}.`);
|
|
||||||
if (status === "complete") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (status === "failed") {
|
|
||||||
throw new Error(`Code Scanning could not process the submitted SARIF file:\n${response.data.errors}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
if (util.isHTTPError(e)) {
|
|
||||||
switch (e.status) {
|
|
||||||
case 404:
|
|
||||||
logger.debug("Analysis is not found yet...");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.endGroup();
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
raw_upload_size_bytes: rawUploadSizeBytes,
|
statusReport: {
|
||||||
zipped_upload_size_bytes: zippedUploadSizeBytes,
|
raw_upload_size_bytes: rawUploadSizeBytes,
|
||||||
num_results_in_sarif: numResultInSarif,
|
zipped_upload_size_bytes: zippedUploadSizeBytes,
|
||||||
|
num_results_in_sarif: numResultInSarif,
|
||||||
|
},
|
||||||
|
sarifID,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
|
||||||
|
const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
|
||||||
|
// Waits until either the analysis is successfully processed, a processing error is reported, or STATUS_CHECK_TIMEOUT_MILLISECONDS elapses.
|
||||||
|
async function waitForProcessing(repositoryNwo, sarifID, apiDetails, logger) {
|
||||||
|
logger.startGroup("Waiting for processing to finish");
|
||||||
|
const client = api.getApiClient(apiDetails);
|
||||||
|
const statusCheckingStarted = Date.now();
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
if (Date.now() >
|
||||||
|
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS) {
|
||||||
|
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
|
||||||
|
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
|
||||||
|
logger.warning("Timed out waiting for analysis to finish processing. Continuing.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 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.
|
||||||
|
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
|
||||||
|
try {
|
||||||
|
const response = await client.request("GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id", {
|
||||||
|
owner: repositoryNwo.owner,
|
||||||
|
repo: repositoryNwo.repo,
|
||||||
|
sarif_id: sarifID,
|
||||||
|
});
|
||||||
|
const status = response.data.processing_status;
|
||||||
|
logger.info(`Analysis upload status is ${status}.`);
|
||||||
|
if (status === "complete") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (status === "failed") {
|
||||||
|
throw new Error(`Code Scanning could not process the submitted SARIF file:\n${response.data.errors}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (util.isHTTPError(e)) {
|
||||||
|
switch (e.status) {
|
||||||
|
case 404:
|
||||||
|
logger.debug("Analysis is not found yet...");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.endGroup();
|
||||||
|
}
|
||||||
|
exports.waitForProcessing = waitForProcessing;
|
||||||
function validateUniqueCategory(category) {
|
function validateUniqueCategory(category) {
|
||||||
if (util.isActions()) {
|
if (util.isActions()) {
|
||||||
// This check only works on actions as env vars don't persist between calls to the runner
|
// This check only works on actions as env vars don't persist between calls to the runner
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
8
lib/upload-sarif-action.js
generated
8
lib/upload-sarif-action.js
generated
|
|
@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const actionsUtil = __importStar(require("./actions-util"));
|
const actionsUtil = __importStar(require("./actions-util"));
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
|
const repository_1 = require("./repository");
|
||||||
const upload_lib = __importStar(require("./upload-lib"));
|
const upload_lib = __importStar(require("./upload-lib"));
|
||||||
const util_1 = require("./util");
|
const util_1 = require("./util");
|
||||||
// eslint-disable-next-line import/no-commonjs
|
// eslint-disable-next-line import/no-commonjs
|
||||||
|
|
@ -46,8 +47,11 @@ async function run() {
|
||||||
url: (0, util_1.getRequiredEnvParam)("GITHUB_SERVER_URL"),
|
url: (0, util_1.getRequiredEnvParam)("GITHUB_SERVER_URL"),
|
||||||
};
|
};
|
||||||
const gitHubVersion = await (0, util_1.getGitHubVersion)(apiDetails);
|
const gitHubVersion = await (0, util_1.getGitHubVersion)(apiDetails);
|
||||||
const uploadStats = await upload_lib.uploadFromActions(actionsUtil.getRequiredInput("sarif_file"), gitHubVersion, apiDetails, (0, logging_1.getActionsLogger)());
|
const uploadResult = await upload_lib.uploadFromActions(actionsUtil.getRequiredInput("sarif_file"), gitHubVersion, apiDetails, (0, logging_1.getActionsLogger)());
|
||||||
await sendSuccessStatusReport(startedAt, uploadStats);
|
if (actionsUtil.getRequiredInput("wait-for-processing") === "true") {
|
||||||
|
await upload_lib.waitForProcessing((0, repository_1.parseRepositoryNwo)((0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY")), uploadResult.sarifID, apiDetails, (0, logging_1.getActionsLogger)());
|
||||||
|
}
|
||||||
|
await sendSuccessStatusReport(startedAt, uploadResult.statusReport);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,oDAAsC;AAEtC,4DAA8C;AAC9C,uCAA6C;AAC7C,yDAA2C;AAC3C,iCAKgB;AAEhB,8CAA8C;AAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAMvC,KAAK,UAAU,uBAAuB,CACpC,SAAe,EACf,WAA0C;IAE1C,MAAM,gBAAgB,GAAG,MAAM,WAAW,CAAC,sBAAsB,CAC/D,cAAc,EACd,SAAS,EACT,SAAS,CACV,CAAC;IACF,MAAM,YAAY,GAA4B;QAC5C,GAAG,gBAAgB;QACnB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;AACnD,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,IAAA,4BAAqB,EAAC,WAAI,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,IACE,CAAC,CAAC,MAAM,WAAW,CAAC,gBAAgB,CAClC,MAAM,WAAW,CAAC,sBAAsB,CACtC,cAAc,EACd,UAAU,EACV,SAAS,CACV,CACF,CAAC,EACF;QACA,OAAO;KACR;IAED,IAAI;QACF,MAAM,UAAU,GAAG;YACjB,IAAI,EAAE,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAC3C,GAAG,EAAE,IAAA,0BAAmB,EAAC,mBAAmB,CAAC;SAC9C,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,IAAA,uBAAgB,EAAC,UAAU,CAAC,CAAC;QAEzD,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,iBAAiB,CACpD,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAC1C,aAAa,EACb,UAAU,EACV,IAAA,0BAAgB,GAAE,CACnB,CAAC;QACF,MAAM,uBAAuB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;KACvD;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,WAAW,CAAC,gBAAgB,CAChC,MAAM,WAAW,CAAC,sBAAsB,CACtC,cAAc,EACd,SAAS,EACT,SAAS,EACT,OAAO,EACP,KAAK,CACN,CACF,CAAC;QACF,OAAO;KACR;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI;QACF,MAAM,GAAG,EAAE,CAAC;KACb;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,SAAS,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KACpB;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
|
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,oDAAsC;AAEtC,4DAA8C;AAC9C,uCAA6C;AAC7C,6CAAkD;AAClD,yDAA2C;AAC3C,iCAKgB;AAEhB,8CAA8C;AAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAMvC,KAAK,UAAU,uBAAuB,CACpC,SAAe,EACf,WAA0C;IAE1C,MAAM,gBAAgB,GAAG,MAAM,WAAW,CAAC,sBAAsB,CAC/D,cAAc,EACd,SAAS,EACT,SAAS,CACV,CAAC;IACF,MAAM,YAAY,GAA4B;QAC5C,GAAG,gBAAgB;QACnB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;AACnD,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,IAAA,4BAAqB,EAAC,WAAI,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,IACE,CAAC,CAAC,MAAM,WAAW,CAAC,gBAAgB,CAClC,MAAM,WAAW,CAAC,sBAAsB,CACtC,cAAc,EACd,UAAU,EACV,SAAS,CACV,CACF,CAAC,EACF;QACA,OAAO;KACR;IAED,IAAI;QACF,MAAM,UAAU,GAAG;YACjB,IAAI,EAAE,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAC3C,GAAG,EAAE,IAAA,0BAAmB,EAAC,mBAAmB,CAAC;SAC9C,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,IAAA,uBAAgB,EAAC,UAAU,CAAC,CAAC;QAEzD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,iBAAiB,CACrD,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAC1C,aAAa,EACb,UAAU,EACV,IAAA,0BAAgB,GAAE,CACnB,CAAC;QACF,IAAI,WAAW,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,MAAM,EAAE;YAClE,MAAM,UAAU,CAAC,iBAAiB,CAChC,IAAA,+BAAkB,EAAC,IAAA,0BAAmB,EAAC,mBAAmB,CAAC,CAAC,EAC5D,YAAY,CAAC,OAAO,EACpB,UAAU,EACV,IAAA,0BAAgB,GAAE,CACnB,CAAC;SACH;QACD,MAAM,uBAAuB,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;KACrE;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,WAAW,CAAC,gBAAgB,CAChC,MAAM,WAAW,CAAC,sBAAsB,CACtC,cAAc,EACd,SAAS,EACT,SAAS,EACT,OAAO,EACP,KAAK,CACN,CACF,CAAC;QACF,OAAO;KACR;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI;QACF,MAAM,GAAG,EAAE,CAAC;KACb;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,SAAS,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KACpB;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
|
||||||
|
|
@ -18,7 +18,7 @@ import { uploadDatabases } from "./database-upload";
|
||||||
import { getActionsLogger } from "./logging";
|
import { getActionsLogger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import * as upload_lib from "./upload-lib";
|
import * as upload_lib from "./upload-lib";
|
||||||
import { UploadStatusReport } from "./upload-lib";
|
import { UploadResult } from "./upload-lib";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import { bundleDb, codeQlVersionAbove, DEBUG_ARTIFACT_NAME } from "./util";
|
import { bundleDb, codeQlVersionAbove, DEBUG_ARTIFACT_NAME } from "./util";
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ export async function sendStatusReport(
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const startedAt = new Date();
|
const startedAt = new Date();
|
||||||
let uploadStats: UploadStatusReport | undefined = undefined;
|
let uploadResult: UploadResult | undefined = undefined;
|
||||||
let runStats: QueriesStatusReport | undefined = undefined;
|
let runStats: QueriesStatusReport | undefined = undefined;
|
||||||
let config: Config | undefined = undefined;
|
let config: Config | undefined = undefined;
|
||||||
util.initializeEnvironment(util.Mode.actions, pkg.version);
|
util.initializeEnvironment(util.Mode.actions, pkg.version);
|
||||||
|
|
@ -163,7 +163,7 @@ async function run() {
|
||||||
core.setOutput("db-locations", dbLocations);
|
core.setOutput("db-locations", dbLocations);
|
||||||
|
|
||||||
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
||||||
uploadStats = await upload_lib.uploadFromActions(
|
uploadResult = await upload_lib.uploadFromActions(
|
||||||
outputDir,
|
outputDir,
|
||||||
config.gitHubVersion,
|
config.gitHubVersion,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
|
|
@ -178,6 +178,18 @@ async function run() {
|
||||||
);
|
);
|
||||||
await uploadDatabases(repositoryNwo, config, apiDetails, logger); // Possibly upload the database bundles for remote queries
|
await uploadDatabases(repositoryNwo, config, apiDetails, logger); // Possibly upload the database bundles for remote queries
|
||||||
|
|
||||||
|
if (
|
||||||
|
uploadResult !== undefined &&
|
||||||
|
actionsUtil.getRequiredInput("wait-for-processing") === "true"
|
||||||
|
) {
|
||||||
|
await upload_lib.waitForProcessing(
|
||||||
|
parseRepositoryNwo(util.getRequiredEnvParam("GITHUB_REPOSITORY")),
|
||||||
|
uploadResult.sarifID,
|
||||||
|
apiDetails,
|
||||||
|
getActionsLogger()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (config.debugMode) {
|
if (config.debugMode) {
|
||||||
// Upload the database bundles as an Actions artifact for debugging
|
// Upload the database bundles as an Actions artifact for debugging
|
||||||
const toUpload: string[] = [];
|
const toUpload: string[] = [];
|
||||||
|
|
@ -227,8 +239,11 @@ async function run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runStats && uploadStats) {
|
if (runStats && uploadResult) {
|
||||||
await sendStatusReport(startedAt, { ...runStats, ...uploadStats });
|
await sendStatusReport(startedAt, {
|
||||||
|
...runStats,
|
||||||
|
...uploadResult.statusReport,
|
||||||
|
});
|
||||||
} else if (runStats) {
|
} else if (runStats) {
|
||||||
await sendStatusReport(startedAt, { ...runStats });
|
await sendStatusReport(startedAt, { ...runStats });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,11 @@ export interface UploadStatusReport {
|
||||||
num_results_in_sarif?: number;
|
num_results_in_sarif?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UploadResult {
|
||||||
|
statusReport: UploadStatusReport;
|
||||||
|
sarifID: string;
|
||||||
|
}
|
||||||
|
|
||||||
// Recursively walks a directory and returns all SARIF files it finds.
|
// Recursively walks a directory and returns all SARIF files it finds.
|
||||||
// Does not follow symlinks.
|
// Does not follow symlinks.
|
||||||
export function findSarifFilesInDir(sarifPath: string): string[] {
|
export function findSarifFilesInDir(sarifPath: string): string[] {
|
||||||
|
|
@ -149,7 +154,7 @@ export async function uploadFromActions(
|
||||||
gitHubVersion: util.GitHubVersion,
|
gitHubVersion: util.GitHubVersion,
|
||||||
apiDetails: api.GitHubApiDetails,
|
apiDetails: api.GitHubApiDetails,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<UploadStatusReport> {
|
): Promise<UploadResult> {
|
||||||
return await uploadFiles(
|
return await uploadFiles(
|
||||||
getSarifFilePaths(sarifPath),
|
getSarifFilePaths(sarifPath),
|
||||||
parseRepositoryNwo(util.getRequiredEnvParam("GITHUB_REPOSITORY")),
|
parseRepositoryNwo(util.getRequiredEnvParam("GITHUB_REPOSITORY")),
|
||||||
|
|
@ -161,7 +166,6 @@ export async function uploadFromActions(
|
||||||
actionsUtil.getWorkflowRunID(),
|
actionsUtil.getWorkflowRunID(),
|
||||||
actionsUtil.getRequiredInput("checkout_path"),
|
actionsUtil.getRequiredInput("checkout_path"),
|
||||||
actionsUtil.getRequiredInput("matrix"),
|
actionsUtil.getRequiredInput("matrix"),
|
||||||
actionsUtil.getRequiredInput("wait-for-processing") === "true",
|
|
||||||
gitHubVersion,
|
gitHubVersion,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
logger
|
logger
|
||||||
|
|
@ -181,7 +185,7 @@ export async function uploadFromRunner(
|
||||||
gitHubVersion: util.GitHubVersion,
|
gitHubVersion: util.GitHubVersion,
|
||||||
apiDetails: api.GitHubApiDetails,
|
apiDetails: api.GitHubApiDetails,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<UploadStatusReport> {
|
): Promise<UploadResult> {
|
||||||
return await uploadFiles(
|
return await uploadFiles(
|
||||||
getSarifFilePaths(sarifPath),
|
getSarifFilePaths(sarifPath),
|
||||||
repositoryNwo,
|
repositoryNwo,
|
||||||
|
|
@ -193,7 +197,6 @@ export async function uploadFromRunner(
|
||||||
undefined,
|
undefined,
|
||||||
sourceRoot,
|
sourceRoot,
|
||||||
undefined,
|
undefined,
|
||||||
false,
|
|
||||||
gitHubVersion,
|
gitHubVersion,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
logger
|
logger
|
||||||
|
|
@ -327,9 +330,6 @@ export function buildPayload(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
|
|
||||||
const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
|
|
||||||
|
|
||||||
// Uploads the given set of sarif files.
|
// Uploads the given set of sarif files.
|
||||||
// Returns true iff the upload occurred and succeeded
|
// Returns true iff the upload occurred and succeeded
|
||||||
async function uploadFiles(
|
async function uploadFiles(
|
||||||
|
|
@ -343,11 +343,10 @@ async function uploadFiles(
|
||||||
workflowRunID: number | undefined,
|
workflowRunID: number | undefined,
|
||||||
sourceRoot: string,
|
sourceRoot: string,
|
||||||
environment: string | undefined,
|
environment: string | undefined,
|
||||||
waitForProcessing: boolean,
|
|
||||||
gitHubVersion: util.GitHubVersion,
|
gitHubVersion: util.GitHubVersion,
|
||||||
apiDetails: api.GitHubApiDetails,
|
apiDetails: api.GitHubApiDetails,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<UploadStatusReport> {
|
): Promise<UploadResult> {
|
||||||
logger.startGroup("Uploading results");
|
logger.startGroup("Uploading results");
|
||||||
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
||||||
|
|
||||||
|
|
@ -407,66 +406,78 @@ async function uploadFiles(
|
||||||
|
|
||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
|
|
||||||
if (waitForProcessing) {
|
return {
|
||||||
logger.startGroup("Waiting for processing to finish");
|
statusReport: {
|
||||||
const client = api.getApiClient(apiDetails);
|
raw_upload_size_bytes: rawUploadSizeBytes,
|
||||||
|
zipped_upload_size_bytes: zippedUploadSizeBytes,
|
||||||
|
num_results_in_sarif: numResultInSarif,
|
||||||
|
},
|
||||||
|
sarifID,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const statusCheckingStarted = Date.now();
|
const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
|
||||||
// eslint-disable-next-line no-constant-condition
|
const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
|
||||||
while (true) {
|
|
||||||
if (
|
// Waits until either the analysis is successfully processed, a processing error is reported, or STATUS_CHECK_TIMEOUT_MILLISECONDS elapses.
|
||||||
Date.now() >
|
export async function waitForProcessing(
|
||||||
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
|
repositoryNwo: RepositoryNwo,
|
||||||
) {
|
sarifID: string,
|
||||||
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
|
apiDetails: api.GitHubApiDetails,
|
||||||
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
|
logger: Logger
|
||||||
logger.warning(
|
): Promise<void> {
|
||||||
"Timed out waiting for analysis to finish processing. Continuing."
|
logger.startGroup("Waiting for processing to finish");
|
||||||
);
|
const client = api.getApiClient(apiDetails);
|
||||||
|
|
||||||
|
const statusCheckingStarted = Date.now();
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
if (
|
||||||
|
Date.now() >
|
||||||
|
statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
|
||||||
|
) {
|
||||||
|
// If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
|
||||||
|
// It's possible the analysis will eventually finish processing, but it's not worth spending more Actions time waiting.
|
||||||
|
logger.warning(
|
||||||
|
"Timed out waiting for analysis to finish processing. Continuing."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 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.
|
||||||
|
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
|
||||||
|
try {
|
||||||
|
const response = await client.request(
|
||||||
|
"GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id",
|
||||||
|
{
|
||||||
|
owner: repositoryNwo.owner,
|
||||||
|
repo: repositoryNwo.repo,
|
||||||
|
sarif_id: sarifID,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const status = response.data.processing_status;
|
||||||
|
logger.info(`Analysis upload status is ${status}.`);
|
||||||
|
if (status === "complete") {
|
||||||
break;
|
break;
|
||||||
}
|
} else if (status === "failed") {
|
||||||
// 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.
|
throw new Error(
|
||||||
await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS);
|
`Code Scanning could not process the submitted SARIF file:\n${response.data.errors}`
|
||||||
try {
|
|
||||||
const response = await client.request(
|
|
||||||
"GET /repos/:owner/:repo/code-scanning/sarifs/:sarif_id",
|
|
||||||
{
|
|
||||||
owner: repositoryNwo.owner,
|
|
||||||
repo: repositoryNwo.repo,
|
|
||||||
sarif_id: sarifID,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
const status = response.data.processing_status;
|
}
|
||||||
logger.info(`Analysis upload status is ${status}.`);
|
} catch (e) {
|
||||||
if (status === "complete") {
|
if (util.isHTTPError(e)) {
|
||||||
break;
|
switch (e.status) {
|
||||||
} else if (status === "failed") {
|
case 404:
|
||||||
throw new Error(
|
logger.debug("Analysis is not found yet...");
|
||||||
`Code Scanning could not process the submitted SARIF file:\n${response.data.errors}`
|
break;
|
||||||
);
|
default:
|
||||||
}
|
throw e;
|
||||||
} catch (e) {
|
|
||||||
if (util.isHTTPError(e)) {
|
|
||||||
switch (e.status) {
|
|
||||||
case 404:
|
|
||||||
logger.debug("Analysis is not found yet...");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.endGroup();
|
|
||||||
}
|
}
|
||||||
|
logger.endGroup();
|
||||||
return {
|
|
||||||
raw_upload_size_bytes: rawUploadSizeBytes,
|
|
||||||
zipped_upload_size_bytes: zippedUploadSizeBytes,
|
|
||||||
num_results_in_sarif: numResultInSarif,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateUniqueCategory(category: string | undefined) {
|
export function validateUniqueCategory(category: string | undefined) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import * as core from "@actions/core";
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import { getActionsLogger } from "./logging";
|
import { getActionsLogger } from "./logging";
|
||||||
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import * as upload_lib from "./upload-lib";
|
import * as upload_lib from "./upload-lib";
|
||||||
import {
|
import {
|
||||||
getGitHubVersion,
|
getGitHubVersion,
|
||||||
|
|
@ -56,13 +57,21 @@ async function run() {
|
||||||
|
|
||||||
const gitHubVersion = await getGitHubVersion(apiDetails);
|
const gitHubVersion = await getGitHubVersion(apiDetails);
|
||||||
|
|
||||||
const uploadStats = await upload_lib.uploadFromActions(
|
const uploadResult = await upload_lib.uploadFromActions(
|
||||||
actionsUtil.getRequiredInput("sarif_file"),
|
actionsUtil.getRequiredInput("sarif_file"),
|
||||||
gitHubVersion,
|
gitHubVersion,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
getActionsLogger()
|
getActionsLogger()
|
||||||
);
|
);
|
||||||
await sendSuccessStatusReport(startedAt, uploadStats);
|
if (actionsUtil.getRequiredInput("wait-for-processing") === "true") {
|
||||||
|
await upload_lib.waitForProcessing(
|
||||||
|
parseRepositoryNwo(getRequiredEnvParam("GITHUB_REPOSITORY")),
|
||||||
|
uploadResult.sarifID,
|
||||||
|
apiDetails,
|
||||||
|
getActionsLogger()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await sendSuccessStatusReport(startedAt, uploadResult.statusReport);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
const stack = error instanceof Error ? error.stack : String(error);
|
const stack = error instanceof Error ? error.stack : String(error);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue