mirror of
https://github.com/github/codeql-action.git
synced 2026-01-06 14:40:10 +08:00
Send overall job status in init-post status report (#2097)
Co-authored-by: Henry Mercer <henry@henrymercer.name>
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* Environment variables used by the CodeQL Action.
|
||||
*
|
||||
* We recommend prefixing environment variables with `CODEQL_ACTION_`
|
||||
* to reduce the risk that they are overwritten by other steps.
|
||||
*/
|
||||
export enum EnvVar {
|
||||
/** Whether the `analyze` Action completes successfully. */
|
||||
ANALYZE_DID_COMPLETE_SUCCESSFULLY = "CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY",
|
||||
@@ -35,6 +41,9 @@ export enum EnvVar {
|
||||
/** UUID representing the current job run. */
|
||||
JOB_RUN_UUID = "JOB_RUN_UUID",
|
||||
|
||||
/** Status for the entire job, submitted to the status report in `init-post` */
|
||||
JOB_STATUS = "CODEQL_ACTION_JOB_STATUS",
|
||||
|
||||
ODASA_TRACER_CONFIGURATION = "ODASA_TRACER_CONFIGURATION",
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as core from "@actions/core";
|
||||
import * as github from "@actions/github";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
@@ -8,6 +9,7 @@ import { EnvVar } from "./environment";
|
||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||
import { Logger } from "./logging";
|
||||
import { RepositoryNwo, parseRepositoryNwo } from "./repository";
|
||||
import { JobStatus } from "./status-report";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
import {
|
||||
delay,
|
||||
@@ -36,6 +38,10 @@ export interface UploadFailedSarifResult extends uploadLib.UploadStatusReport {
|
||||
sarifID?: string;
|
||||
}
|
||||
|
||||
export interface JobStatusReport {
|
||||
job_status: JobStatus;
|
||||
}
|
||||
|
||||
function createFailedUploadFailedSarifResult(
|
||||
error: unknown,
|
||||
): UploadFailedSarifResult {
|
||||
@@ -121,6 +127,15 @@ export async function tryUploadSarifIfRunFailed(
|
||||
logger: Logger,
|
||||
): Promise<UploadFailedSarifResult> {
|
||||
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] !== "true") {
|
||||
// If analyze didn't complete successfully and the job status hasn't
|
||||
// already been set to Failure/ConfigurationError previously, this
|
||||
// means that something along the way failed in a step that is not
|
||||
// owned by the Action, for example a manual build step. We
|
||||
// consider this a configuration error.
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.ConfigurationError,
|
||||
);
|
||||
try {
|
||||
return await maybeUploadFailedSarif(
|
||||
config,
|
||||
@@ -135,6 +150,10 @@ export async function tryUploadSarifIfRunFailed(
|
||||
return createFailedUploadFailedSarifResult(e);
|
||||
}
|
||||
} else {
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.Success,
|
||||
);
|
||||
return {
|
||||
upload_failed_run_skipped_because:
|
||||
"Analyze Action completed successfully",
|
||||
@@ -282,3 +301,20 @@ async function removeUploadedSarif(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the final job status sent in the `init-post` Action, based on the
|
||||
* current value of the JOB_STATUS environment variable. If the variable is
|
||||
* unset, or if its value is not one of the JobStatus enum values, returns
|
||||
* Unknown. Otherwise it returns the status set in the environment variable.
|
||||
*/
|
||||
export function getFinalJobStatus(): JobStatus {
|
||||
const jobStatusFromEnvironment = process.env[EnvVar.JOB_STATUS];
|
||||
if (
|
||||
!jobStatusFromEnvironment ||
|
||||
!Object.values(JobStatus).includes(jobStatusFromEnvironment as JobStatus)
|
||||
) {
|
||||
return JobStatus.Unknown;
|
||||
}
|
||||
return jobStatusFromEnvironment as JobStatus;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ import {
|
||||
|
||||
interface InitPostStatusReport
|
||||
extends StatusReportBase,
|
||||
initActionPostHelper.UploadFailedSarifResult {}
|
||||
initActionPostHelper.UploadFailedSarifResult,
|
||||
initActionPostHelper.JobStatusReport {}
|
||||
|
||||
async function runWrapper() {
|
||||
const startedAt = new Date();
|
||||
@@ -83,6 +84,7 @@ async function runWrapper() {
|
||||
const statusReport: InitPostStatusReport = {
|
||||
...statusReportBase,
|
||||
...uploadFailedSarifResult,
|
||||
job_status: initActionPostHelper.getFinalJobStatus(),
|
||||
};
|
||||
await sendStatusReport(statusReport);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,20 @@ export type ActionName =
|
||||
| "upload-sarif";
|
||||
|
||||
export type ActionStatus =
|
||||
| "aborted"
|
||||
| "aborted" // Only used in the init Action, if init failed before initializing the tracer due to something other than a configuration error.
|
||||
| "failure"
|
||||
| "starting"
|
||||
| "success"
|
||||
| "user-error";
|
||||
|
||||
/** Overall status of the entire job. String values match the Hydro schema. */
|
||||
export enum JobStatus {
|
||||
Unknown = "JOB_STATUS_UNKNOWN",
|
||||
Success = "JOB_STATUS_SUCCESS",
|
||||
Failure = "JOB_STATUS_FAILURE",
|
||||
ConfigurationError = "JOB_STATUS_CONFIGURATION_ERROR",
|
||||
}
|
||||
|
||||
export interface StatusReportBase {
|
||||
/** Name of the action being executed. */
|
||||
action_name: ActionName;
|
||||
@@ -133,6 +141,25 @@ export function getActionsStatus(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: ActionStatus) {
|
||||
if (actionStatus === "user-error") {
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.ConfigurationError,
|
||||
);
|
||||
} else if (actionStatus === "failure" || actionStatus === "aborted") {
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.Failure,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Any status report may include an array of EventReports associated with it.
|
||||
export interface EventReport {
|
||||
/** Time this event ended. */
|
||||
@@ -273,6 +300,8 @@ const INCOMPATIBLE_MSG =
|
||||
export async function sendStatusReport<S extends StatusReportBase>(
|
||||
statusReport: S,
|
||||
): Promise<boolean> {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user