Simplify computation of job status

- Move it out of the failed SARIF reporting so we compute the job status
whether or not we have a CodeQL config.
- Add comments to clarify what happens in the case that the CodeQL
config is absent.
This commit is contained in:
Henry Mercer
2026-01-23 16:52:38 +00:00
parent 1601acf88b
commit dcd1b12beb
3 changed files with 601 additions and 585 deletions
+21 -55
View File
@@ -1,6 +1,5 @@
import * as fs from "fs";
import * as core from "@actions/core";
import * as github from "@actions/github";
import * as actionsUtil from "./actions-util";
@@ -129,48 +128,32 @@ export async function tryUploadSarifIfRunFailed(
features: FeatureEnablement,
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.ConfigErrorStatus,
);
// If the only enabled analysis kind is `code-quality`, then we shouldn't
// upload the failed SARIF to Code Scanning.
if (!isCodeScanningEnabled(config)) {
return {
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
};
}
try {
return await maybeUploadFailedSarif(
config,
repositoryNwo,
features,
logger,
);
} catch (e) {
logger.debug(
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
);
return createFailedUploadFailedSarifResult(e);
}
} else {
core.exportVariable(
EnvVar.JOB_STATUS,
process.env[EnvVar.JOB_STATUS] ?? JobStatus.SuccessStatus,
);
// If the only enabled analysis kind is `code-quality`, then we shouldn't
// upload the failed SARIF to Code Scanning.
if (!isCodeScanningEnabled(config)) {
return {
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
};
}
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
return {
upload_failed_run_skipped_because:
"Analyze Action completed successfully",
};
}
try {
return await maybeUploadFailedSarif(
config,
repositoryNwo,
features,
logger,
);
} catch (e) {
logger.debug(
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
);
return createFailedUploadFailedSarifResult(e);
}
}
export async function run(
@@ -335,20 +318,3 @@ 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.UnknownStatus;
}
return jobStatusFromEnvironment as JobStatus;
}
+51 -4
View File
@@ -14,12 +14,13 @@ import {
import { getGitHubVersion } from "./api-client";
import { CachingKind } from "./caching-utils";
import { getCodeQL } from "./codeql";
import { Config, getConfig } from "./config-utils";
import { type Config, getConfig } from "./config-utils";
import * as debugArtifacts from "./debug-artifacts";
import {
DependencyCachingUsageReport,
getDependencyCacheUsage,
} from "./dependency-caching";
import { EnvVar } from "./environment";
import { Features } from "./feature-flags";
import * as gitUtils from "./git-utils";
import * as initActionPostHelper from "./init-action-post-helper";
@@ -33,6 +34,7 @@ import {
getActionsStatus,
ActionName,
getJobStatusDisplayName,
JobStatus,
} from "./status-report";
import { checkDiskUsage, checkGitHubVersionInRange, wrapError } from "./util";
@@ -85,7 +87,7 @@ async function run(startedAt: Date) {
logger,
);
// If we are analysing the default branch and some kind of caching is enabled,
// If we are analyzing the default branch and some kind of caching is enabled,
// then try to determine our overall cache usage for dependency caches. We only
// do this under these circumstances to avoid slowing down analyses for PRs
// and where caching may not be enabled.
@@ -115,7 +117,7 @@ async function run(startedAt: Date) {
}
return;
}
const jobStatus = initActionPostHelper.getFinalJobStatus();
const jobStatus = getFinalJobStatus(config);
logger.info(`CodeQL job status was ${getJobStatusDisplayName(jobStatus)}.`);
const statusReportBase = await createStatusReportBase(
@@ -130,7 +132,7 @@ async function run(startedAt: Date) {
const statusReport: InitPostStatusReport = {
...statusReportBase,
...uploadFailedSarifResult,
job_status: initActionPostHelper.getFinalJobStatus(),
job_status: jobStatus,
dependency_caching_usage: dependencyCachingUsage,
};
logger.info("Sending status report for init-post step.");
@@ -139,6 +141,51 @@ async function run(startedAt: Date) {
}
}
function getFinalJobStatus(config: Config | undefined): JobStatus {
const jobStatusFromEnvironment = process.env[EnvVar.JOB_STATUS];
if (jobStatusFromEnvironment !== undefined) {
// Validate the job status from the environment. If it is invalid, return unknown.
if (
Object.values(JobStatus).includes(jobStatusFromEnvironment as JobStatus)
) {
return jobStatusFromEnvironment as JobStatus;
}
return JobStatus.UnknownStatus;
}
let jobStatus: JobStatus;
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
core.exportVariable(EnvVar.JOB_STATUS, JobStatus.SuccessStatus);
jobStatus = JobStatus.SuccessStatus;
} else if (config !== undefined) {
// - We have computed a CodeQL config
// - Analyze didn't complete successfully
// - The job status hasn't already been set to Failure/ConfigurationError
//
// 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.
jobStatus = JobStatus.ConfigErrorStatus;
} else {
// If we didn't manage to compute a CodeQL config, it is unclear at this
// point why the analyze Action didn't complete.
// - One possibility is that the workflow run was cancelled. We could
// consider determining workflow cancellation using the GitHub API, but
// for now we treat all these cases as unknown.
// - Another possibility is that we're running a workflow that only runs
// `init`, for instance a workflow that was created before `setup-codeql`
// was available and uses `init` just to set up the CodeQL tools.
jobStatus = JobStatus.UnknownStatus;
}
// This shouldn't be necessary, but in the odd case that we run more than one
// `init` post step, ensure the job status is consistent between them.
core.exportVariable(EnvVar.JOB_STATUS, jobStatus);
return jobStatus;
}
async function runWrapper() {
const startedAt = new Date();
const logger = getActionsLogger();