mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 17:50:07 +08:00
Previously, we weren't catching any possible exceptions in `createStatusReportBase` and runs would fail if any of the telemetry sub-items threw exceptions. As telemetry should not block the analysis, we continue here even if the status report throws.
282 lines
13 KiB
JavaScript
Generated
282 lines
13 KiB
JavaScript
Generated
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.sendStatusReport = exports.createStatusReportBase = exports.getJobStatusDisplayName = exports.getActionsStatus = exports.JobStatus = exports.isFirstPartyAnalysis = exports.ActionName = void 0;
|
|
const os = __importStar(require("os"));
|
|
const core = __importStar(require("@actions/core"));
|
|
const actions_util_1 = require("./actions-util");
|
|
const api_client_1 = require("./api-client");
|
|
const environment_1 = require("./environment");
|
|
const util_1 = require("./util");
|
|
var ActionName;
|
|
(function (ActionName) {
|
|
ActionName["Autobuild"] = "autobuild";
|
|
ActionName["Analyze"] = "finish";
|
|
ActionName["Init"] = "init";
|
|
ActionName["InitPost"] = "init-post";
|
|
ActionName["ResolveEnvironment"] = "resolve-environment";
|
|
ActionName["UploadSarif"] = "upload-sarif";
|
|
})(ActionName || (exports.ActionName = ActionName = {}));
|
|
/**
|
|
* @returns a boolean indicating whether the analysis is considered to be first party.
|
|
*
|
|
* This is based on whether the init action has been used, which is only used for first party analysis.
|
|
* When a SARIF file has been generated by other means and submitted using the upload action, this is
|
|
* considered to be a third party analysis and is treated differently when calculating SLOs. To ensure
|
|
* misconfigured workflows are not treated as third party, only the upload-sarif action can return false.
|
|
*/
|
|
function isFirstPartyAnalysis(actionName) {
|
|
if (actionName !== ActionName.UploadSarif) {
|
|
return true;
|
|
}
|
|
return process.env[environment_1.EnvVar.INIT_ACTION_HAS_RUN] === "true";
|
|
}
|
|
exports.isFirstPartyAnalysis = isFirstPartyAnalysis;
|
|
/** Overall status of the entire job. String values match the Hydro schema. */
|
|
var JobStatus;
|
|
(function (JobStatus) {
|
|
JobStatus["UnknownStatus"] = "JOB_STATUS_UNKNOWN";
|
|
JobStatus["SuccessStatus"] = "JOB_STATUS_SUCCESS";
|
|
JobStatus["FailureStatus"] = "JOB_STATUS_FAILURE";
|
|
JobStatus["ConfigErrorStatus"] = "JOB_STATUS_CONFIGURATION_ERROR";
|
|
})(JobStatus || (exports.JobStatus = JobStatus = {}));
|
|
function getActionsStatus(error, otherFailureCause) {
|
|
if (error || otherFailureCause) {
|
|
return error instanceof util_1.ConfigurationError ? "user-error" : "failure";
|
|
}
|
|
else {
|
|
return "success";
|
|
}
|
|
}
|
|
exports.getActionsStatus = getActionsStatus;
|
|
function getJobStatusDisplayName(status) {
|
|
switch (status) {
|
|
case JobStatus.SuccessStatus:
|
|
return "success";
|
|
case JobStatus.FailureStatus:
|
|
return "failure";
|
|
case JobStatus.ConfigErrorStatus:
|
|
return "configuration error";
|
|
case JobStatus.UnknownStatus:
|
|
return "unknown";
|
|
default:
|
|
(0, util_1.assertNever)(status);
|
|
}
|
|
}
|
|
exports.getJobStatusDisplayName = getJobStatusDisplayName;
|
|
/**
|
|
* Sets the overall job status environment variable to configuration error
|
|
* or failure, unless it's already been set to one of these values in a
|
|
* previous step.
|
|
*/
|
|
function setJobStatusIfUnsuccessful(actionStatus) {
|
|
if (actionStatus === "user-error") {
|
|
core.exportVariable(environment_1.EnvVar.JOB_STATUS, process.env[environment_1.EnvVar.JOB_STATUS] ?? JobStatus.ConfigErrorStatus);
|
|
}
|
|
else if (actionStatus === "failure" || actionStatus === "aborted") {
|
|
core.exportVariable(environment_1.EnvVar.JOB_STATUS, process.env[environment_1.EnvVar.JOB_STATUS] ?? JobStatus.FailureStatus);
|
|
}
|
|
}
|
|
/**
|
|
* Compose a StatusReport.
|
|
*
|
|
* @param actionName The name of the action, e.g. 'init', 'finish', 'upload-sarif'
|
|
* @param status The status. Must be 'success', 'failure', or 'starting'
|
|
* @param startedAt The time this action started executing.
|
|
* @param cause Cause of failure (only supply if status is 'failure')
|
|
* @param exception Exception (only supply if status is 'failure')
|
|
* @returns undefined if an exception was thrown.
|
|
*/
|
|
async function createStatusReportBase(actionName, status, actionStartedAt, config, diskInfo, logger, cause, exception) {
|
|
try {
|
|
const commitOid = (0, actions_util_1.getOptionalInput)("sha") || process.env["GITHUB_SHA"] || "";
|
|
const ref = await (0, actions_util_1.getRef)();
|
|
const jobRunUUID = process.env[environment_1.EnvVar.JOB_RUN_UUID] || "";
|
|
const workflowRunID = (0, actions_util_1.getWorkflowRunID)();
|
|
const workflowRunAttempt = (0, actions_util_1.getWorkflowRunAttempt)();
|
|
const workflowName = process.env["GITHUB_WORKFLOW"] || "";
|
|
const jobName = process.env["GITHUB_JOB"] || "";
|
|
const analysis_key = await (0, api_client_1.getAnalysisKey)();
|
|
let workflowStartedAt = process.env[environment_1.EnvVar.WORKFLOW_STARTED_AT];
|
|
if (workflowStartedAt === undefined) {
|
|
workflowStartedAt = actionStartedAt.toISOString();
|
|
core.exportVariable(environment_1.EnvVar.WORKFLOW_STARTED_AT, workflowStartedAt);
|
|
}
|
|
const runnerOs = (0, util_1.getRequiredEnvParam)("RUNNER_OS");
|
|
const codeQlCliVersion = (0, util_1.getCachedCodeQlVersion)();
|
|
const actionRef = process.env["GITHUB_ACTION_REF"] || "";
|
|
const testingEnvironment = process.env[environment_1.EnvVar.TESTING_ENVIRONMENT] || "";
|
|
// re-export the testing environment variable so that it is available to subsequent steps,
|
|
// even if it was only set for this step
|
|
if (testingEnvironment !== "") {
|
|
core.exportVariable(environment_1.EnvVar.TESTING_ENVIRONMENT, testingEnvironment);
|
|
}
|
|
const statusReport = {
|
|
action_name: actionName,
|
|
action_oid: "unknown", // TODO decide if it's possible to fill this in
|
|
action_ref: actionRef,
|
|
action_started_at: actionStartedAt.toISOString(),
|
|
action_version: (0, actions_util_1.getActionVersion)(),
|
|
analysis_key,
|
|
build_mode: config?.buildMode,
|
|
commit_oid: commitOid,
|
|
first_party_analysis: isFirstPartyAnalysis(actionName),
|
|
job_name: jobName,
|
|
job_run_uuid: jobRunUUID,
|
|
ref,
|
|
runner_os: runnerOs,
|
|
started_at: workflowStartedAt,
|
|
status,
|
|
testing_environment: testingEnvironment,
|
|
workflow_name: workflowName,
|
|
workflow_run_attempt: workflowRunAttempt,
|
|
workflow_run_id: workflowRunID,
|
|
};
|
|
try {
|
|
statusReport.actions_event_name = (0, actions_util_1.getWorkflowEventName)();
|
|
}
|
|
catch (e) {
|
|
logger.warning(`Could not determine the workflow event name: ${e}.`);
|
|
}
|
|
if (config) {
|
|
statusReport.languages = config.languages.join(",");
|
|
}
|
|
if (diskInfo) {
|
|
statusReport.runner_available_disk_space_bytes =
|
|
diskInfo.numAvailableBytes;
|
|
statusReport.runner_total_disk_space_bytes = diskInfo.numTotalBytes;
|
|
}
|
|
// Add optional parameters
|
|
if (cause) {
|
|
statusReport.cause = cause;
|
|
}
|
|
if (exception) {
|
|
statusReport.exception = exception;
|
|
}
|
|
if (status === "success" ||
|
|
status === "failure" ||
|
|
status === "aborted" ||
|
|
status === "user-error") {
|
|
statusReport.completed_at = new Date().toISOString();
|
|
}
|
|
const matrix = (0, actions_util_1.getRequiredInput)("matrix");
|
|
if (matrix) {
|
|
statusReport.matrix_vars = matrix;
|
|
}
|
|
if ("RUNNER_ARCH" in process.env) {
|
|
// RUNNER_ARCH is available only in GHES 3.4 and later
|
|
// Values other than X86, X64, ARM, or ARM64 are discarded server side
|
|
statusReport.runner_arch = process.env["RUNNER_ARCH"];
|
|
}
|
|
if (runnerOs === "Windows" || runnerOs === "macOS") {
|
|
statusReport.runner_os_release = os.release();
|
|
}
|
|
if (codeQlCliVersion !== undefined) {
|
|
statusReport.codeql_version = codeQlCliVersion.version;
|
|
}
|
|
const imageVersion = process.env["ImageVersion"];
|
|
if (imageVersion) {
|
|
statusReport.runner_image_version = imageVersion;
|
|
}
|
|
return statusReport;
|
|
}
|
|
catch (e) {
|
|
logger.warning(`Caught an exception while gathering information for telemetry: ${e}. Will skip sending status report.`);
|
|
return undefined;
|
|
}
|
|
}
|
|
exports.createStatusReportBase = createStatusReportBase;
|
|
const OUT_OF_DATE_MSG = "CodeQL Action is out-of-date. Please upgrade to the latest version of codeql-action.";
|
|
const INCOMPATIBLE_MSG = "CodeQL Action version is incompatible with the code scanning endpoint. Please update to a compatible version of codeql-action.";
|
|
/**
|
|
* Send a status report to the code_scanning/analysis/status endpoint.
|
|
*
|
|
* Optionally checks the response from the API endpoint and sets the action
|
|
* as failed if the status report failed. This is only expected to be used
|
|
* when sending a 'starting' report.
|
|
*
|
|
* The `/code-scanning/analysis/status` endpoint is internal and it is not critical that it succeeds:
|
|
* https://github.com/github/codeql/issues/15462#issuecomment-1919186317
|
|
*
|
|
* Failures while calling this endpoint are logged as warings.
|
|
*/
|
|
async function sendStatusReport(statusReport) {
|
|
setJobStatusIfUnsuccessful(statusReport.status);
|
|
const statusReportJSON = JSON.stringify(statusReport);
|
|
core.debug(`Sending status report: ${statusReportJSON}`);
|
|
// If in test mode we don't want to upload the results
|
|
if ((0, util_1.isInTestMode)()) {
|
|
core.debug("In test mode. Status reports are not uploaded.");
|
|
return;
|
|
}
|
|
const nwo = (0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY");
|
|
const [owner, repo] = nwo.split("/");
|
|
const client = (0, api_client_1.getApiClient)();
|
|
try {
|
|
await client.request("PUT /repos/:owner/:repo/code-scanning/analysis/status", {
|
|
owner,
|
|
repo,
|
|
data: statusReportJSON,
|
|
});
|
|
}
|
|
catch (e) {
|
|
console.log(e);
|
|
if ((0, util_1.isHTTPError)(e)) {
|
|
switch (e.status) {
|
|
case 403:
|
|
if ((0, actions_util_1.getWorkflowEventName)() === "push" &&
|
|
process.env["GITHUB_ACTOR"] === "dependabot[bot]") {
|
|
core.warning('Workflows triggered by Dependabot on the "push" event run with read-only access. ' +
|
|
"Uploading Code Scanning results requires write access. " +
|
|
'To use Code Scanning with Dependabot, please ensure you are using the "pull_request" event for this workflow and avoid triggering on the "push" event for Dependabot branches. ' +
|
|
"See https://docs.github.com/en/code-security/secure-coding/configuring-code-scanning#scanning-on-push for more information on how to configure these events.");
|
|
}
|
|
else {
|
|
core.warning(e.message);
|
|
}
|
|
return;
|
|
case 404:
|
|
core.warning(e.message);
|
|
return;
|
|
case 422:
|
|
// schema incompatibility when reporting status
|
|
// this means that this action version is no longer compatible with the API
|
|
// we still want to continue as it is likely the analysis endpoint will work
|
|
if ((0, util_1.getRequiredEnvParam)("GITHUB_SERVER_URL") !== util_1.GITHUB_DOTCOM_URL) {
|
|
core.debug(INCOMPATIBLE_MSG);
|
|
}
|
|
else {
|
|
core.debug(OUT_OF_DATE_MSG);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
// something else has gone wrong and the request/response will be logged by octokit
|
|
// it's possible this is a transient error and we should continue scanning
|
|
core.warning("An unexpected error occurred when sending code scanning status report.");
|
|
}
|
|
}
|
|
exports.sendStatusReport = sendStatusReport;
|
|
//# sourceMappingURL=status-report.js.map
|