Include runner disk info in status report

This commit is contained in:
Henry Mercer 2023-08-07 16:00:32 +01:00
parent 09ce3dbf90
commit 7dcb3e5276
30 changed files with 232 additions and 150 deletions

View file

@ -52,7 +52,7 @@ interface FinishWithTrapUploadStatusReport extends FinishStatusReport {
trap_cache_upload_duration_ms: number;
}
export async function sendStatusReport(
async function sendStatusReport(
startedAt: Date,
config: Config | undefined,
stats: AnalysisStatusReport | undefined,
@ -67,6 +67,7 @@ export async function sendStatusReport(
"finish",
status,
startedAt,
await util.checkDiskUsage(),
error?.message,
error?.stack,
);
@ -184,7 +185,12 @@ async function run() {
try {
if (
!(await statusReport.sendStatusReport(
await createStatusReportBase("finish", "starting", startedAt),
await createStatusReportBase(
"finish",
"starting",
startedAt,
await util.checkDiskUsage(logger),
),
))
) {
return;

View file

@ -10,7 +10,7 @@ import { determineAutobuildLanguages, runAutobuild } from "./autobuild";
import * as configUtils from "./config-utils";
import { EnvVar } from "./environment";
import { Language } from "./languages";
import { getActionsLogger } from "./logging";
import { Logger, getActionsLogger } from "./logging";
import {
StatusReportBase,
getActionsStatus,
@ -18,6 +18,7 @@ import {
sendStatusReport,
} from "./status-report";
import {
checkDiskUsage,
checkGitHubVersionInRange,
initializeEnvironment,
wrapError,
@ -31,6 +32,7 @@ interface AutobuildStatusReport extends StatusReportBase {
}
async function sendCompletedStatusReport(
logger: Logger,
startedAt: Date,
allLanguages: string[],
failingLanguage?: string,
@ -43,6 +45,7 @@ async function sendCompletedStatusReport(
"autobuild",
status,
startedAt,
await checkDiskUsage(logger),
cause?.message,
cause?.stack,
);
@ -62,7 +65,12 @@ async function run() {
try {
if (
!(await sendStatusReport(
await createStatusReportBase("autobuild", "starting", startedAt),
await createStatusReportBase(
"autobuild",
"starting",
startedAt,
await checkDiskUsage(logger),
),
))
) {
return;
@ -101,6 +109,7 @@ async function run() {
`We were unable to automatically build your code. Please replace the call to the autobuild action with your custom build steps. ${error.message}`,
);
await sendCompletedStatusReport(
logger,
startedAt,
languages ?? [],
currentLanguage,
@ -109,7 +118,7 @@ async function run() {
return;
}
await sendCompletedStatusReport(startedAt, languages ?? []);
await sendCompletedStatusReport(logger, startedAt, languages ?? []);
}
async function runWrapper() {

View file

@ -1,41 +1,37 @@
export enum EnvVar {
/** Set to true when the `analyze` Action completes successfully. */
/** Whether the `analyze` Action completes successfully. */
ANALYZE_DID_COMPLETE_SUCCESSFULLY = "CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY",
/** Set to "true" when the CodeQL Action has invoked the Go autobuilder. */
/** Whether the CodeQL Action has invoked the Go autobuilder. */
DID_AUTOBUILD_GOLANG = "CODEQL_ACTION_DID_AUTOBUILD_GOLANG",
/**
* Used to disable the SARIF post-processing in the Action that removes duplicate locations from
* Whether to disable the SARIF post-processing in the Action that removes duplicate locations from
* notifications in the `run[].invocations[].toolExecutionNotifications` SARIF property.
*/
DISABLE_DUPLICATE_LOCATION_FIX = "CODEQL_ACTION_DISABLE_DUPLICATE_LOCATION_FIX",
/**
* If set to the "true" string, then the CodeQL Action is using its
* own deprecated and non-standard way of scanning for multiple
* languages.
* Whether the CodeQL Action is using its own deprecated and non-standard way of scanning for
* multiple languages.
*/
FEATURE_MULTI_LANGUAGE = "CODEQL_ACTION_FEATURE_MULTI_LANGUAGE",
/**
* If set to the "true" string, then the CodeQL Action is using its
* own sandwiched workflow mechanism.
*/
/** Whether the CodeQL Action is using its own sandwiched workflow mechanism. */
FEATURE_SANDWICH = "CODEQL_ACTION_FEATURE_SANDWICH",
/**
* If set to a truthy value, then the CodeQL Action might combine SARIF
* output from several `interpret-results` runs for the same language.
* Whether the CodeQL Action might combine SARIF output from several `interpret-results` runs for
* the same language.
*/
FEATURE_SARIF_COMBINE = "CODEQL_ACTION_FEATURE_SARIF_COMBINE",
/**
* If set to the "true" string, then the CodeQL Action will upload SARIF,
* not the CLI.
*/
/** Whether the CodeQL Action will upload SARIF, not the CLI. */
FEATURE_WILL_UPLOAD = "CODEQL_ACTION_FEATURE_WILL_UPLOAD",
/** Whether the CodeQL Action has already warned the user about low disk space. */
HAS_WARNED_ABOUT_DISK_SPACE = "CODEQL_ACTION_HAS_WARNED_ABOUT_DISK_SPACE",
/** UUID representing the current job run. */
JOB_RUN_UUID = "JOB_RUN_UUID",
@ -44,7 +40,7 @@ export enum EnvVar {
/** Whether to suppress the warning if the current CLI will soon be unsupported. */
SUPPRESS_DEPRECATED_SOON_WARNING = "CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING",
/** Used to disable uploading SARIF results or status reports to the GitHub API */
/** Whether to disable uploading SARIF results or status reports to the GitHub API */
TEST_MODE = "CODEQL_ACTION_TEST_MODE",
TESTING_ENVIRONMENT = "CODEQL_ACTION_TESTING_ENVIRONMENT",

View file

@ -20,6 +20,7 @@ import {
getActionsStatus,
} from "./status-report";
import {
checkDiskUsage,
checkGitHubVersionInRange,
getRequiredEnvParam,
wrapError,
@ -66,6 +67,7 @@ async function runWrapper() {
"init-post",
getActionsStatus(error),
startedAt,
await checkDiskUsage(),
error.message,
error.stack,
),
@ -76,6 +78,7 @@ async function runWrapper() {
"init-post",
"success",
startedAt,
await checkDiskUsage(),
);
const statusReport: InitPostStatusReport = {
...statusReportBase,

View file

@ -28,6 +28,7 @@ import {
} from "./status-report";
import { getTotalCacheSize } from "./trap-caching";
import {
checkDiskUsage,
checkForTimeout,
checkGitHubVersionInRange,
DEFAULT_DEBUG_ARTIFACT_NAME,
@ -102,6 +103,7 @@ async function sendCompletedStatusReport(
"init",
getActionsStatus(error),
startedAt,
await checkDiskUsage(logger),
error?.message,
error?.stack,
);
@ -222,6 +224,7 @@ async function run() {
"init",
"starting",
startedAt,
await checkDiskUsage(logger),
workflowErrors,
),
))
@ -302,6 +305,7 @@ async function run() {
"init",
error instanceof UserError ? "user-error" : "aborted",
startedAt,
await checkDiskUsage(),
error.message,
error.stack,
),

View file

@ -16,7 +16,12 @@ import {
createStatusReportBase,
getActionsStatus,
} from "./status-report";
import { checkForTimeout, checkGitHubVersionInRange, wrapError } from "./util";
import {
checkDiskUsage,
checkForTimeout,
checkGitHubVersionInRange,
wrapError,
} from "./util";
const ACTION_NAME = "resolve-environment";
const ENVIRONMENT_OUTPUT_NAME = "environment";
@ -29,7 +34,12 @@ async function run() {
try {
if (
!(await sendStatusReport(
await createStatusReportBase(ACTION_NAME, "starting", startedAt),
await createStatusReportBase(
ACTION_NAME,
"starting",
startedAt,
await checkDiskUsage(logger),
),
))
) {
return;
@ -74,6 +84,7 @@ async function run() {
ACTION_NAME,
getActionsStatus(error),
startedAt,
await checkDiskUsage(),
error.message,
error.stack,
),
@ -84,7 +95,12 @@ async function run() {
}
await sendStatusReport(
await createStatusReportBase(ACTION_NAME, "success", startedAt),
await createStatusReportBase(
ACTION_NAME,
"success",
startedAt,
await checkDiskUsage(),
),
);
}

View file

@ -28,33 +28,31 @@ test("createStatusReportBase", async (t) => {
"init",
"failure",
new Date("May 19, 2023 05:19:00"),
{ numAvailableBytes: 100, numTotalBytes: 500 },
"failure cause",
"exception stack trace",
);
t.assert(typeof statusReport.job_run_uuid === "string");
t.assert(statusReport.workflow_run_id === 100);
t.assert(statusReport.workflow_run_attempt === 2);
t.assert(
statusReport.workflow_name === (process.env["GITHUB_WORKFLOW"] || ""),
t.is(statusReport.action_name, "init");
t.is(statusReport.action_oid, "unknown");
t.is(typeof statusReport.action_version, "string");
t.is(
statusReport.action_started_at,
new Date("May 19, 2023 05:19:00").toISOString(),
);
t.assert(statusReport.job_name === (process.env["GITHUB_JOB"] || ""));
t.assert(statusReport.analysis_key === "analysis-key");
t.assert(statusReport.commit_oid === process.env["GITHUB_SHA"]);
t.assert(statusReport.ref === process.env["GITHUB_REF"]);
t.assert(statusReport.action_name === "init");
t.assert(statusReport.action_oid === "unknown");
t.assert(
statusReport.started_at === process.env[EnvVar.WORKFLOW_STARTED_AT],
);
t.assert(
statusReport.action_started_at ===
new Date("May 19, 2023 05:19:00").toISOString(),
);
t.assert(statusReport.status === "failure");
t.assert(statusReport.cause === "failure cause");
t.assert(statusReport.exception === "exception stack trace");
t.assert(statusReport.runner_os === process.env["RUNNER_OS"]);
t.assert(typeof statusReport.action_version === "string");
t.is(statusReport.analysis_key, "analysis-key");
t.is(statusReport.cause, "failure cause");
t.is(statusReport.commit_oid, process.env["GITHUB_SHA"]);
t.is(statusReport.exception, "exception stack trace");
t.is(statusReport.job_name, process.env["GITHUB_JOB"] || "");
t.is(typeof statusReport.job_run_uuid, "string");
t.is(statusReport.ref, process.env["GITHUB_REF"]);
t.is(statusReport.runner_available_disk_space_bytes, 100);
t.is(statusReport.runner_os, process.env["RUNNER_OS"]);
t.is(statusReport.started_at, process.env[EnvVar.WORKFLOW_STARTED_AT]!);
t.is(statusReport.status, "failure");
t.is(statusReport.workflow_name, process.env["GITHUB_WORKFLOW"] || "");
t.is(statusReport.workflow_run_attempt, 2);
t.is(statusReport.workflow_run_id, 100);
});
});

View file

@ -20,6 +20,7 @@ import {
getCachedCodeQlVersion,
isInTestMode,
GITHUB_DOTCOM_URL,
DiskUsage,
} from "./util";
export type ActionName =
@ -88,10 +89,6 @@ export interface StatusReportBase {
runner_arch?: string;
/** Available disk space on the runner, in bytes. */
runner_available_disk_space_bytes: number;
/**
* Version of the runner image, for workflows running on GitHub-hosted runners. Absent otherwise.
*/
runner_image_version?: string;
/** Action runner operating system (context runner.os). */
runner_os: string;
/** Action runner operating system release (x.y.z from os.release()). */
@ -164,6 +161,7 @@ export async function createStatusReportBase(
actionName: ActionName,
status: ActionStatus,
actionStartedAt: Date,
diskInfo: DiskUsage,
cause?: string,
exception?: string,
): Promise<StatusReportBase> {
@ -191,23 +189,25 @@ export async function createStatusReportBase(
}
const statusReport: StatusReportBase = {
job_run_uuid: jobRunUUID,
workflow_run_id: workflowRunID,
workflow_run_attempt: workflowRunAttempt,
workflow_name: workflowName,
job_name: jobName,
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: getActionVersion(),
analysis_key,
commit_oid: commitOid,
job_name: jobName,
job_run_uuid: jobRunUUID,
ref,
action_name: actionName,
action_ref: actionRef,
action_oid: "unknown", // TODO decide if it's possible to fill this in
runner_available_disk_space_bytes: diskInfo.numAvailableBytes,
runner_os: runnerOs,
runner_total_disk_space_bytes: diskInfo.numTotalBytes,
started_at: workflowStartedAt,
action_started_at: actionStartedAt.toISOString(),
status,
testing_environment: testingEnvironment,
runner_os: runnerOs,
action_version: getActionVersion(),
workflow_name: workflowName,
workflow_run_attempt: workflowRunAttempt,
workflow_run_id: workflowRunID,
};
// Add optional parameters

View file

@ -12,6 +12,7 @@ import {
} from "./status-report";
import * as upload_lib from "./upload-lib";
import {
checkDiskUsage,
getRequiredEnvParam,
initializeEnvironment,
isInTestMode,
@ -30,6 +31,7 @@ async function sendSuccessStatusReport(
"upload-sarif",
"success",
startedAt,
await checkDiskUsage(),
);
const statusReport: UploadSarifStatusReport = {
...statusReportBase,
@ -40,10 +42,16 @@ async function sendSuccessStatusReport(
async function run() {
const startedAt = new Date();
const logger = getActionsLogger();
initializeEnvironment(getActionVersion());
if (
!(await sendStatusReport(
await createStatusReportBase("upload-sarif", "starting", startedAt),
await createStatusReportBase(
"upload-sarif",
"starting",
startedAt,
await checkDiskUsage(),
),
))
) {
return;
@ -54,7 +62,7 @@ async function run() {
actionsUtil.getRequiredInput("sarif_file"),
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.getOptionalInput("category"),
getActionsLogger(),
logger,
);
core.setOutput("sarif-id", uploadResult.sarifID);
@ -65,7 +73,7 @@ async function run() {
await upload_lib.waitForProcessing(
parseRepositoryNwo(getRequiredEnvParam("GITHUB_REPOSITORY")),
uploadResult.sarifID,
getActionsLogger(),
logger,
);
}
await sendSuccessStatusReport(startedAt, uploadResult.statusReport);
@ -79,6 +87,7 @@ async function run() {
"upload-sarif",
getActionsStatus(error),
startedAt,
await checkDiskUsage(),
message,
error.stack,
),

View file

@ -4,6 +4,7 @@ import * as path from "path";
import { promisify } from "util";
import * as core from "@actions/core";
import checkDiskSpace from "check-disk-space";
import del from "del";
import getFolderSize from "get-folder-size";
import * as semver from "semver";
@ -14,7 +15,6 @@ import type { Config, Pack } from "./config-utils";
import { EnvVar } from "./environment";
import { Language } from "./languages";
import { Logger } from "./logging";
import { getDiskInfo } from "node-disk-info";
/**
* Specifies bundle versions that are known to be broken
@ -846,6 +846,29 @@ export function prettyPrintPack(pack: Pack) {
}`;
}
export async function checkDiskUsage() {
const diskUsage = awgetDiskInfo
export interface DiskUsage {
numAvailableBytes: number;
numTotalBytes: number;
}
export async function checkDiskUsage(logger?: Logger): Promise<DiskUsage> {
const diskUsage = await checkDiskSpace(
getRequiredEnvParam("GITHUB_WORKSPACE"),
);
const gbInBytes = 1024 * 1024 * 1024;
if (logger && diskUsage.free < 2 * gbInBytes) {
const message =
"The Actions runner is running low on disk space " +
`(${(diskUsage.free / gbInBytes).toPrecision(4)} GB available).`;
if (process.env[EnvVar.HAS_WARNED_ABOUT_DISK_SPACE] !== "true") {
logger.warning(message);
} else {
logger.debug(message);
}
core.exportVariable(EnvVar.HAS_WARNED_ABOUT_DISK_SPACE, "true");
}
return {
numAvailableBytes: diskUsage.free,
numTotalBytes: diskUsage.size,
};
}