From 2399df74271c38d9326cf5aa5f0da1b358b1417e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 16 Jun 2026 13:00:13 +0200 Subject: [PATCH 01/14] Add `ActionsEnvVars` enum --- lib/entry-points.js | 26 ++++++++++++++------------ src/actions-util.ts | 44 ++++++++++++++++++++++++++++++++++---------- src/api-client.ts | 10 +++++++--- src/testing-utils.ts | 4 ++-- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index cdbd6ab82b..a9110febce 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -144948,7 +144948,7 @@ var getOptionalInput = function(name) { }; function getTemporaryDirectory() { const value = process.env["CODEQL_ACTION_TEMP"]; - return value !== void 0 && value !== "" ? value : getRequiredEnvParam("RUNNER_TEMP"); + return value !== void 0 && value !== "" ? value : getRequiredEnvParam("RUNNER_TEMP" /* RUNNER_TEMP */); } var PR_DIFF_RANGE_JSON_FILENAME = "pr-diff-range.json"; function getDiffRangesJsonFilePath() { @@ -144958,19 +144958,19 @@ function getActionVersion() { return "4.36.3"; } function getWorkflowEventName() { - return getRequiredEnvParam("GITHUB_EVENT_NAME"); + return getRequiredEnvParam("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); } function isRunningLocalAction() { const relativeScriptPath = getRelativeScriptPath(); return relativeScriptPath.startsWith("..") || path2.isAbsolute(relativeScriptPath); } function getRelativeScriptPath() { - const runnerTemp = getRequiredEnvParam("RUNNER_TEMP"); + const runnerTemp = getRequiredEnvParam("RUNNER_TEMP" /* RUNNER_TEMP */); const actionsDirectory = path2.join(path2.dirname(runnerTemp), "_actions"); return path2.relative(actionsDirectory, __filename); } function getWorkflowEvent() { - const eventJsonFile = getRequiredEnvParam("GITHUB_EVENT_PATH"); + const eventJsonFile = getRequiredEnvParam("GITHUB_EVENT_PATH" /* GITHUB_EVENT_PATH */); try { return JSON.parse(fs2.readFileSync(eventJsonFile, "utf-8")); } catch (e) { @@ -145027,31 +145027,33 @@ function getUploadValue(input) { } } function getWorkflowRunID() { - const workflowRunIdString = getRequiredEnvParam("GITHUB_RUN_ID"); + const workflowRunIdString = getRequiredEnvParam("GITHUB_RUN_ID" /* GITHUB_RUN_ID */); const workflowRunID = parseInt(workflowRunIdString, 10); if (Number.isNaN(workflowRunID)) { throw new Error( - `GITHUB_RUN_ID must define a non NaN workflow run ID. Current value is ${workflowRunIdString}` + `${"GITHUB_RUN_ID" /* GITHUB_RUN_ID */} must define a non NaN workflow run ID. Current value is ${workflowRunIdString}` ); } if (workflowRunID < 0) { throw new Error( - `GITHUB_RUN_ID must be a non-negative integer. Current value is ${workflowRunIdString}` + `${"GITHUB_RUN_ID" /* GITHUB_RUN_ID */} must be a non-negative integer. Current value is ${workflowRunIdString}` ); } return workflowRunID; } function getWorkflowRunAttempt() { - const workflowRunAttemptString = getRequiredEnvParam("GITHUB_RUN_ATTEMPT"); + const workflowRunAttemptString = getRequiredEnvParam( + "GITHUB_RUN_ATTEMPT" /* GITHUB_RUN_ATTEMPT */ + ); const workflowRunAttempt = parseInt(workflowRunAttemptString, 10); if (Number.isNaN(workflowRunAttempt)) { throw new Error( - `GITHUB_RUN_ATTEMPT must define a non NaN workflow run attempt. Current value is ${workflowRunAttemptString}` + `${"GITHUB_RUN_ATTEMPT" /* GITHUB_RUN_ATTEMPT */} must define a non NaN workflow run attempt. Current value is ${workflowRunAttemptString}` ); } if (workflowRunAttempt <= 0) { throw new Error( - `GITHUB_RUN_ATTEMPT must be a positive integer. Current value is ${workflowRunAttemptString}` + `${"GITHUB_RUN_ATTEMPT" /* GITHUB_RUN_ATTEMPT */} must be a positive integer. Current value is ${workflowRunAttemptString}` ); } return workflowRunAttempt; @@ -145362,8 +145364,8 @@ function createApiClientWithDetails(apiDetails, { allowExternal = false } = {}) function getApiDetails() { return { auth: getRequiredInput("token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL") + url: getRequiredEnvParam("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */), + apiURL: getRequiredEnvParam("GITHUB_API_URL" /* GITHUB_API_URL */) }; } function getApiClient() { diff --git a/src/actions-util.ts b/src/actions-util.ts index dea22d5c57..d7fbacbf3e 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -21,6 +21,28 @@ import { */ declare const __CODEQL_ACTION_VERSION__: string; +/** + * Enumerates known GitHub Actions environment variables that we expect + * to be set in a GitHub Actions environment. + */ +export enum ActionsEnvVars { + GITHUB_ACTION_REPOSITORY = "GITHUB_ACTION_REPOSITORY", + GITHUB_API_URL = "GITHUB_API_URL", + GITHUB_EVENT_NAME = "GITHUB_EVENT_NAME", + GITHUB_EVENT_PATH = "GITHUB_EVENT_PATH", + GITHUB_JOB = "GITHUB_JOB", + GITHUB_REF = "GITHUB_REF", + GITHUB_REPOSITORY = "GITHUB_REPOSITORY", + GITHUB_RUN_ATTEMPT = "GITHUB_RUN_ATTEMPT", + GITHUB_RUN_ID = "GITHUB_RUN_ID", + GITHUB_SERVER_URL = "GITHUB_SERVER_URL", + GITHUB_SHA = "GITHUB_SHA", + GITHUB_WORKFLOW = "GITHUB_WORKFLOW", + RUNNER_NAME = "RUNNER_NAME", + RUNNER_OS = "RUNNER_OS", + RUNNER_TEMP = "RUNNER_TEMP", +} + /** * Abstracts over GitHub Actions functions so that we do not have to stub * global functions in tests. @@ -65,7 +87,7 @@ export function getTemporaryDirectory(): string { const value = process.env["CODEQL_ACTION_TEMP"]; return value !== undefined && value !== "" ? value - : getRequiredEnvParam("RUNNER_TEMP"); + : getRequiredEnvParam(ActionsEnvVars.RUNNER_TEMP); } const PR_DIFF_RANGE_JSON_FILENAME = "pr-diff-range.json"; @@ -84,7 +106,7 @@ export function getActionVersion(): string { * This will be "dynamic" for default setup workflow runs. */ export function getWorkflowEventName() { - return getRequiredEnvParam("GITHUB_EVENT_NAME"); + return getRequiredEnvParam(ActionsEnvVars.GITHUB_EVENT_NAME); } /** @@ -104,14 +126,14 @@ export function isRunningLocalAction(): boolean { * This can be used to get the Action's name or tell if we're running a local Action. */ function getRelativeScriptPath(): string { - const runnerTemp = getRequiredEnvParam("RUNNER_TEMP"); + const runnerTemp = getRequiredEnvParam(ActionsEnvVars.RUNNER_TEMP); const actionsDirectory = path.join(path.dirname(runnerTemp), "_actions"); return path.relative(actionsDirectory, __filename); } /** Returns the contents of `GITHUB_EVENT_PATH` as a JSON object. */ export function getWorkflowEvent(): any { - const eventJsonFile = getRequiredEnvParam("GITHUB_EVENT_PATH"); + const eventJsonFile = getRequiredEnvParam(ActionsEnvVars.GITHUB_EVENT_PATH); try { return JSON.parse(fs.readFileSync(eventJsonFile, "utf-8")); } catch (e) { @@ -181,16 +203,16 @@ export function getUploadValue(input: string | undefined): UploadKind { * Get the workflow run ID. */ export function getWorkflowRunID(): number { - const workflowRunIdString = getRequiredEnvParam("GITHUB_RUN_ID"); + const workflowRunIdString = getRequiredEnvParam(ActionsEnvVars.GITHUB_RUN_ID); const workflowRunID = parseInt(workflowRunIdString, 10); if (Number.isNaN(workflowRunID)) { throw new Error( - `GITHUB_RUN_ID must define a non NaN workflow run ID. Current value is ${workflowRunIdString}`, + `${ActionsEnvVars.GITHUB_RUN_ID} must define a non NaN workflow run ID. Current value is ${workflowRunIdString}`, ); } if (workflowRunID < 0) { throw new Error( - `GITHUB_RUN_ID must be a non-negative integer. Current value is ${workflowRunIdString}`, + `${ActionsEnvVars.GITHUB_RUN_ID} must be a non-negative integer. Current value is ${workflowRunIdString}`, ); } return workflowRunID; @@ -200,16 +222,18 @@ export function getWorkflowRunID(): number { * Get the workflow run attempt number. */ export function getWorkflowRunAttempt(): number { - const workflowRunAttemptString = getRequiredEnvParam("GITHUB_RUN_ATTEMPT"); + const workflowRunAttemptString = getRequiredEnvParam( + ActionsEnvVars.GITHUB_RUN_ATTEMPT, + ); const workflowRunAttempt = parseInt(workflowRunAttemptString, 10); if (Number.isNaN(workflowRunAttempt)) { throw new Error( - `GITHUB_RUN_ATTEMPT must define a non NaN workflow run attempt. Current value is ${workflowRunAttemptString}`, + `${ActionsEnvVars.GITHUB_RUN_ATTEMPT} must define a non NaN workflow run attempt. Current value is ${workflowRunAttemptString}`, ); } if (workflowRunAttempt <= 0) { throw new Error( - `GITHUB_RUN_ATTEMPT must be a positive integer. Current value is ${workflowRunAttemptString}`, + `${ActionsEnvVars.GITHUB_RUN_ATTEMPT} must be a positive integer. Current value is ${workflowRunAttemptString}`, ); } return workflowRunAttempt; diff --git a/src/api-client.ts b/src/api-client.ts index 333280f8e7..16e4082e90 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -2,7 +2,11 @@ import * as core from "@actions/core"; import * as githubUtils from "@actions/github/lib/utils"; import * as retry from "@octokit/plugin-retry"; -import { getActionVersion, getRequiredInput } from "./actions-util"; +import { + ActionsEnvVars, + getActionVersion, + getRequiredInput, +} from "./actions-util"; import { EnvVar } from "./environment"; import { Logger } from "./logging"; import { getRepositoryNwo, RepositoryNwo } from "./repository"; @@ -70,8 +74,8 @@ function createApiClientWithDetails( export function getApiDetails(): GitHubApiDetails { return { auth: getRequiredInput("token"), - url: getRequiredEnvParam("GITHUB_SERVER_URL"), - apiURL: getRequiredEnvParam("GITHUB_API_URL"), + url: getRequiredEnvParam(ActionsEnvVars.GITHUB_SERVER_URL), + apiURL: getRequiredEnvParam(ActionsEnvVars.GITHUB_API_URL), }; } diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 2660c21a69..411cb87319 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -10,7 +10,7 @@ import test, { import nock from "nock"; import * as sinon from "sinon"; -import { ActionsEnv, getActionVersion } from "./actions-util"; +import { ActionsEnv, ActionsEnvVars, getActionVersion } from "./actions-util"; import { AnalysisKind } from "./analyses"; import * as apiClient from "./api-client"; import { GitHubApiDetails } from "./api-client"; @@ -200,7 +200,7 @@ export const DEFAULT_ACTIONS_VARS = { GITHUB_WORKFLOW: "test-workflow", RUNNER_NAME: "my-runner", RUNNER_OS: "Linux", -} as const satisfies Record; +} as const satisfies Partial>; /** Partial mappings from GitHub Actions environment variables to values. */ export type ActionVarOverrides = Partial< From e1905475d1141d294256ac4055201a21865bba1c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 16 Jun 2026 13:22:35 +0200 Subject: [PATCH 02/14] Allow abstracting over `process.env` --- lib/entry-points.js | 14 ++++++++++---- src/environment.ts | 8 ++++++++ src/testing-utils.ts | 7 +++++++ src/util.ts | 42 +++++++++++++++++++++++++++++++++++------- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index a9110febce..ca2bd7e421 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -144583,20 +144583,26 @@ function initializeEnvironment(version) { core2.exportVariable("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); core2.exportVariable("CODEQL_ACTION_VERSION" /* VERSION */, version); } -function getRequiredEnvParam(paramName) { - const value = process.env[paramName]; +function getRequiredEnvVar(env, paramName) { + const value = env[paramName]; if (value === void 0 || value.length === 0) { throw new Error(`${paramName} environment variable must be set`); } return value; } -function getOptionalEnvVar(paramName) { - const value = process.env[paramName]; +function getRequiredEnvParam(paramName) { + return getRequiredEnvVar(process.env, paramName); +} +function getOptionalEnvVarFrom(env, paramName) { + const value = env[paramName]; if (value?.trim().length === 0) { return void 0; } return value; } +function getOptionalEnvVar(paramName) { + return getOptionalEnvVarFrom(process.env, paramName); +} var HTTPError = class extends Error { status; constructor(message, status) { diff --git a/src/environment.ts b/src/environment.ts index c3f54ebd27..c0ca050b03 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -160,3 +160,11 @@ export enum EnvVar { /** Used by Code Scanning Risk Assessment to communicate the assessment ID to the CodeQL Action. */ RISK_ASSESSMENT_ID = "CODEQL_ACTION_RISK_ASSESSMENT_ID", } + +/** A wrapper around an environment, to allow abstracting away from `process.env` in tests. */ +export interface Env { + /** Tries to get the value for `name` and throws if there isn't one. */ + getRequired(name: string): string; + /** Gets the value for `name`, or `undefined` if it isn't set or empty. */ + getOptional(name: string): string | undefined; +} diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 411cb87319..22ed1e21a5 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -18,6 +18,7 @@ import { CachingKind } from "./caching-utils"; import * as codeql from "./codeql"; import { Config } from "./config-utils"; import * as defaults from "./defaults.json"; +import { Env } from "./environment"; import { CodeQLDefaultVersionInfo, Feature, @@ -29,6 +30,7 @@ import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, + getEnv, GitHubVariant, GitHubVersion, HTTPError, @@ -172,6 +174,11 @@ export function makeMacro( return wrapper; } +export function getTestEnv(): Env { + const testEnv: NodeJS.ProcessEnv = {}; + return getEnv(testEnv); +} + /** * Gets an `ActionsEnv` instance for use in tests. */ diff --git a/src/util.ts b/src/util.ts index fc0553b1b7..7f52456608 100644 --- a/src/util.ts +++ b/src/util.ts @@ -13,7 +13,7 @@ import * as apiCompatibility from "./api-compatibility.json"; import type { CodeQL, VersionInfo } from "./codeql"; import type { Pack } from "./config/db-config"; import type { Config } from "./config-utils"; -import { EnvVar } from "./environment"; +import { Env, EnvVar } from "./environment"; import * as json from "./json"; import { Language } from "./languages"; import { Logger } from "./logging"; @@ -566,11 +566,22 @@ export function initializeEnvironment(version: string) { core.exportVariable(EnvVar.VERSION, version); } +/** Gets an `Env` instance for `env`, which is `process.env` by default. */ +export function getEnv(env: NodeJS.ProcessEnv = process.env): Env { + return { + getRequired: (name) => getRequiredEnvVar(env, name), + getOptional: (name) => getOptionalEnvVarFrom(env, name), + }; +} + /** - * Get an environment parameter, but throw an error if it is not set. + * Gets an environment variable, but throws an error if it is not set. */ -export function getRequiredEnvParam(paramName: string): string { - const value = process.env[paramName]; +export function getRequiredEnvVar( + env: NodeJS.ProcessEnv, + paramName: string, +): string { + const value = env[paramName]; if (value === undefined || value.length === 0) { throw new Error(`${paramName} environment variable must be set`); } @@ -578,16 +589,33 @@ export function getRequiredEnvParam(paramName: string): string { } /** - * Get an environment variable, but return `undefined` if it is not set or empty. + * Get an environment parameter, but throw an error if it is not set. */ -export function getOptionalEnvVar(paramName: string): string | undefined { - const value = process.env[paramName]; +export function getRequiredEnvParam(paramName: string): string { + return getRequiredEnvVar(process.env, paramName); +} + +/** + * Gets an environment variable, but returns `undefined` if it is not set or empty. + */ +export function getOptionalEnvVarFrom( + env: NodeJS.ProcessEnv, + paramName: string, +): string | undefined { + const value = env[paramName]; if (value?.trim().length === 0) { return undefined; } return value; } +/** + * Get an environment variable, but return `undefined` if it is not set or empty. + */ +export function getOptionalEnvVar(paramName: string): string | undefined { + return getOptionalEnvVarFrom(process.env, paramName); +} + export class HTTPError extends Error { public status: number; From 9b35ab94e1dfa5cfef82b6e8c7c3ea3a6e5a0a79 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 30 Jun 2026 12:59:35 +0100 Subject: [PATCH 03/14] Add initial `ActionState` type --- src/action-common.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/action-common.ts diff --git a/src/action-common.ts b/src/action-common.ts new file mode 100644 index 0000000000..5af58f08b7 --- /dev/null +++ b/src/action-common.ts @@ -0,0 +1,37 @@ +import { Env } from "./environment"; +import { FeatureEnablement } from "./feature-flags"; +import { Logger } from "./logging"; + +/** Describes different state features that an Action may have. */ +export interface FeatureState { + Logger: { + /** The logger that is in use. */ + logger: Logger; + }; + Env: { + /** Information about environment variables. */ + env: Env; + }; + FeatureFlags: { + /** Information about enabled feature flags. */ + features: FeatureEnablement; + }; +} + +/** Identifies a type of state an Action may have. */ +export type StateFeature = keyof FeatureState; + +/** Constructs the union of all state types identifies by `Fs`. */ +export type FieldsOf = Fs extends [ + infer Head extends StateFeature, +] + ? FeatureState[Head] + : Fs extends [ + infer Head extends StateFeature, + ...infer Tail extends StateFeature[], + ] + ? FeatureState[Head] & FieldsOf + : never; + +/** Describes the state of an Action that has access to the state corresponding to `Fs`. */ +export type ActionState = FieldsOf; From 26e9e9e9326d60dccb8487b1f67e965c7878df43 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 30 Jun 2026 13:19:10 +0100 Subject: [PATCH 04/14] Add `TestEnv` class to simplify testing of `ActionState`-dependent functions --- src/testing-utils.ts | 94 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 22ed1e21a5..64a62175a4 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -10,6 +10,7 @@ import test, { import nock from "nock"; import * as sinon from "sinon"; +import { ActionState, StateFeature } from "./action-common"; import { ActionsEnv, ActionsEnvVars, getActionVersion } from "./actions-util"; import { AnalysisKind } from "./analyses"; import * as apiClient from "./api-client"; @@ -188,6 +189,99 @@ export function getTestActionsEnv(): ActionsEnv { }; } +/** For testing purposes, we make all available state features accessible in `TestEnv`. */ +type AllState = ["Logger", "Env", "FeatureFlags"]; + +/** + * Wraps a function that accepts an `ActionState` for testing in different environments. + */ +export class TestEnv< + Args extends readonly any[], + R, + Fs extends ReadonlyArray, +> { + private readonly fn: (state: ActionState, ...args: Args) => R; + private args?: Args; + private logger: RecordingLogger; + private state: ActionState; + + constructor( + fn: (state: ActionState, ...args: Args) => R, + cloneFrom?: TestEnv, + ) { + this.fn = fn; + this.args = cloneFrom?.args; + this.logger = new RecordingLogger(); + this.state = + cloneFrom !== undefined + ? { ...cloneFrom.state } + : { + logger: new RecordingLogger(), + env: getTestEnv(), + features: createFeatures([]), + }; + } + + private clone(): TestEnv { + return new TestEnv(this.fn, this); + } + + public getLogger(): RecordingLogger { + return this.logger; + } + + public getState(): ActionState { + return this.state; + } + + public getArgs(): Args | undefined { + return this.args; + } + + public withArgs(...args: Args) { + const result = this.clone(); + result.args = args; + return result; + } + + public withFeatures(enabled: Feature[]): TestEnv { + const result = this.clone(); + result.state.features = createFeatures(enabled); + return result; + } + + public withEnv(env: Env): TestEnv { + const result = this.clone(); + result.state.env = env; + return result; + } + + call(): R { + if (!this.args) { + throw new Error("Trying to call function in TestEnv without arguments."); + } + return this.fn(this.state as ActionState, ...this.args); + } + + public passes( + assertion: (makeCall: () => R) => T | Promise, + ): T | Promise { + return assertion(() => { + const result = this.call(); + return result; + }); + } +} + +/** Utility function to construct a `TestEnv`. */ +export function callee< + Args extends readonly any[], + R, + Fs extends readonly StateFeature[], +>(fn: (state: ActionState, ...args: Args) => R): TestEnv { + return new TestEnv(fn); +} + /** * Default values for environment variables typically set in an Actions * environment. Tests can override individual variables by passing them in the From b009eac5591fa3e6ef8e99152184da56c77aa58c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 17:35:46 +0100 Subject: [PATCH 05/14] Add `ActionsEnv` support to `ActionState` --- src/action-common.ts | 5 +++++ src/testing-utils.ts | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/action-common.ts b/src/action-common.ts index 5af58f08b7..424a9181d2 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -1,3 +1,4 @@ +import { ActionsEnv } from "./actions-util"; import { Env } from "./environment"; import { FeatureEnablement } from "./feature-flags"; import { Logger } from "./logging"; @@ -12,6 +13,10 @@ export interface FeatureState { /** Information about environment variables. */ env: Env; }; + Actions: { + /** Access to Actions-related functionality. */ + actions: ActionsEnv; + }; FeatureFlags: { /** Information about enabled feature flags. */ features: FeatureEnablement; diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 64a62175a4..2f8506ca3f 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -11,7 +11,12 @@ import nock from "nock"; import * as sinon from "sinon"; import { ActionState, StateFeature } from "./action-common"; -import { ActionsEnv, ActionsEnvVars, getActionVersion } from "./actions-util"; +import { + ActionsEnv, + ActionsEnvVars, + getActionsEnv, + getActionVersion, +} from "./actions-util"; import { AnalysisKind } from "./analyses"; import * as apiClient from "./api-client"; import { GitHubApiDetails } from "./api-client"; @@ -190,7 +195,7 @@ export function getTestActionsEnv(): ActionsEnv { } /** For testing purposes, we make all available state features accessible in `TestEnv`. */ -type AllState = ["Logger", "Env", "FeatureFlags"]; +type AllState = ["Logger", "Env", "Actions", "FeatureFlags"]; /** * Wraps a function that accepts an `ActionState` for testing in different environments. @@ -218,6 +223,7 @@ export class TestEnv< : { logger: new RecordingLogger(), env: getTestEnv(), + actions: getActionsEnv(), features: createFeatures([]), }; } @@ -256,6 +262,12 @@ export class TestEnv< return result; } + public withActions(actions: ActionsEnv): TestEnv { + const result = this.clone(); + result.state.actions = actions; + return result; + } + call(): R { if (!this.args) { throw new Error("Trying to call function in TestEnv without arguments."); From 9c16c3b47b3bfc50316599f1b3d0bacb56291ff1 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 17:45:56 +0100 Subject: [PATCH 06/14] Add common entry point --- src/action-common.ts | 56 +++++++++++++++++++++++++++++++++++++++----- src/testing-utils.ts | 5 +++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/action-common.ts b/src/action-common.ts index 424a9181d2..cc9f7d3d7a 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -1,7 +1,19 @@ -import { ActionsEnv } from "./actions-util"; +import * as core from "@actions/core"; + +import { ActionsEnv, getActionsEnv } from "./actions-util"; import { Env } from "./environment"; import { FeatureEnablement } from "./feature-flags"; -import { Logger } from "./logging"; +import { getActionsLogger, Logger } from "./logging"; +import { ActionName, sendUnhandledErrorStatusReport } from "./status-report"; +import { getEnv, getErrorMessage } from "./util"; + +/** Common state that is always available in `ActionState`. */ +export interface BaseState { + /** The name of the Action. */ + name: ActionName; + /** When the Action was started. */ + startedAt: Date; +} /** Describes different state features that an Action may have. */ export interface FeatureState { @@ -27,10 +39,8 @@ export interface FeatureState { export type StateFeature = keyof FeatureState; /** Constructs the union of all state types identifies by `Fs`. */ -export type FieldsOf = Fs extends [ - infer Head extends StateFeature, -] - ? FeatureState[Head] +export type FieldsOf = Fs extends [] + ? BaseState : Fs extends [ infer Head extends StateFeature, ...infer Tail extends StateFeature[], @@ -40,3 +50,37 @@ export type FieldsOf = Fs extends [ /** Describes the state of an Action that has access to the state corresponding to `Fs`. */ export type ActionState = FieldsOf; + +/** The type of an Action's main entry point. */ +export type ActionMain = ( + state: ActionState<["Logger", "Env", "Actions"]>, +) => Promise; + +/** A specification for a CodeQL Action step. */ +export interface Action { + /** The name of the Action. */ + name: ActionName; + /** The entry point for the Action. */ + run: ActionMain; +} + +/** A generic entry point that sets up the environment for the `action` and runs it. */ +export async function runInActions(action: Action) { + const startedAt = new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv, + }); + } catch (error) { + core.setFailed(`${action.name} action failed: ${getErrorMessage(error)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error, logger); + } +} diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 2f8506ca3f..d3faf7ea63 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -33,6 +33,7 @@ import { } from "./feature-flags"; import { Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; +import { ActionName } from "./status-report"; import { DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, @@ -221,6 +222,8 @@ export class TestEnv< cloneFrom !== undefined ? { ...cloneFrom.state } : { + name: ActionName.Init, + startedAt: new Date(), logger: new RecordingLogger(), env: getTestEnv(), actions: getActionsEnv(), @@ -272,7 +275,7 @@ export class TestEnv< if (!this.args) { throw new Error("Trying to call function in TestEnv without arguments."); } - return this.fn(this.state as ActionState, ...this.args); + return this.fn(this.state as unknown as ActionState, ...this.args); } public passes( From a3a1cdd43a5c8fd5be4644b12973cfff975c4a70 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 17:56:54 +0100 Subject: [PATCH 07/14] Use the common entry point for `upload-sarif` --- lib/entry-points.js | 582 +++++++++++++++++++------------------ src/upload-sarif-action.ts | 32 +- 2 files changed, 310 insertions(+), 304 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ca2bd7e421..7a80e3741b 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -21409,7 +21409,7 @@ var require_core = __commonJS({ exports2.getBooleanInput = getBooleanInput; exports2.setOutput = setOutput7; exports2.setCommandEcho = setCommandEcho; - exports2.setFailed = setFailed12; + exports2.setFailed = setFailed13; exports2.isDebug = isDebug5; exports2.debug = debug6; exports2.error = error3; @@ -21493,7 +21493,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); function setCommandEcho(enabled) { (0, command_1.issue)("echo", enabled ? "on" : "off"); } - function setFailed12(message) { + function setFailed13(message) { process.exitCode = ExitCode.Failure; error3(message); } @@ -30692,7 +30692,7 @@ var require_internal_glob_options_helper = __commonJS({ })(); Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getOptions = getOptions; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); function getOptions(copy) { const result = { followSymbolicLinks: true, @@ -30704,23 +30704,23 @@ var require_internal_glob_options_helper = __commonJS({ if (copy) { if (typeof copy.followSymbolicLinks === "boolean") { result.followSymbolicLinks = copy.followSymbolicLinks; - core30.debug(`followSymbolicLinks '${result.followSymbolicLinks}'`); + core31.debug(`followSymbolicLinks '${result.followSymbolicLinks}'`); } if (typeof copy.implicitDescendants === "boolean") { result.implicitDescendants = copy.implicitDescendants; - core30.debug(`implicitDescendants '${result.implicitDescendants}'`); + core31.debug(`implicitDescendants '${result.implicitDescendants}'`); } if (typeof copy.matchDirectories === "boolean") { result.matchDirectories = copy.matchDirectories; - core30.debug(`matchDirectories '${result.matchDirectories}'`); + core31.debug(`matchDirectories '${result.matchDirectories}'`); } if (typeof copy.omitBrokenSymbolicLinks === "boolean") { result.omitBrokenSymbolicLinks = copy.omitBrokenSymbolicLinks; - core30.debug(`omitBrokenSymbolicLinks '${result.omitBrokenSymbolicLinks}'`); + core31.debug(`omitBrokenSymbolicLinks '${result.omitBrokenSymbolicLinks}'`); } if (typeof copy.excludeHiddenFiles === "boolean") { result.excludeHiddenFiles = copy.excludeHiddenFiles; - core30.debug(`excludeHiddenFiles '${result.excludeHiddenFiles}'`); + core31.debug(`excludeHiddenFiles '${result.excludeHiddenFiles}'`); } } return result; @@ -32350,7 +32350,7 @@ var require_internal_globber = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DefaultGlobber = void 0; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var fs31 = __importStar2(require("fs")); var globOptionsHelper = __importStar2(require_internal_glob_options_helper()); var path29 = __importStar2(require("path")); @@ -32403,7 +32403,7 @@ var require_internal_globber = __commonJS({ } const stack = []; for (const searchPath of patternHelper.getSearchPaths(patterns)) { - core30.debug(`Search path '${searchPath}'`); + core31.debug(`Search path '${searchPath}'`); try { yield __await2(fs31.promises.lstat(searchPath)); } catch (err) { @@ -32478,7 +32478,7 @@ var require_internal_globber = __commonJS({ } catch (err) { if (err.code === "ENOENT") { if (options.omitBrokenSymbolicLinks) { - core30.debug(`Broken symlink '${item.path}'`); + core31.debug(`Broken symlink '${item.path}'`); return void 0; } throw new Error(`No information found for the path '${item.path}'. This may indicate a broken symbolic link.`); @@ -32494,7 +32494,7 @@ var require_internal_globber = __commonJS({ traversalChain.pop(); } if (traversalChain.some((x) => x === realPath)) { - core30.debug(`Symlink cycle detected for path '${item.path}' and realpath '${realPath}'`); + core31.debug(`Symlink cycle detected for path '${item.path}' and realpath '${realPath}'`); return void 0; } traversalChain.push(realPath); @@ -32597,7 +32597,7 @@ var require_internal_hash_files = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.hashFiles = hashFiles2; var crypto3 = __importStar2(require("crypto")); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var fs31 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util3 = __importStar2(require("util")); @@ -32606,7 +32606,7 @@ var require_internal_hash_files = __commonJS({ return __awaiter2(this, arguments, void 0, function* (globber, currentWorkspace, verbose = false) { var _a2, e_1, _b, _c; var _d; - const writeDelegate = verbose ? core30.info : core30.debug; + const writeDelegate = verbose ? core31.info : core31.debug; let hasMatch = false; const githubWorkspace = currentWorkspace ? currentWorkspace : (_d = process.env["GITHUB_WORKSPACE"]) !== null && _d !== void 0 ? _d : process.cwd(); const result = crypto3.createHash("sha256"); @@ -33997,7 +33997,7 @@ var require_cacheUtils = __commonJS({ exports2.assertDefined = assertDefined; exports2.getCacheVersion = getCacheVersion; exports2.getRuntimeToken = getRuntimeToken; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var exec3 = __importStar2(require_exec()); var glob2 = __importStar2(require_glob()); var io9 = __importStar2(require_io()); @@ -34048,7 +34048,7 @@ var require_cacheUtils = __commonJS({ _e = false; const file = _c; const relativeFile = path29.relative(workspace, file).replace(new RegExp(`\\${path29.sep}`, "g"), "/"); - core30.debug(`Matched: ${relativeFile}`); + core31.debug(`Matched: ${relativeFile}`); if (relativeFile === "") { paths.push("."); } else { @@ -34076,7 +34076,7 @@ var require_cacheUtils = __commonJS({ return __awaiter2(this, arguments, void 0, function* (app, additionalArgs = []) { let versionOutput = ""; additionalArgs.push("--version"); - core30.debug(`Checking ${app} ${additionalArgs.join(" ")}`); + core31.debug(`Checking ${app} ${additionalArgs.join(" ")}`); try { yield exec3.exec(`${app}`, additionalArgs, { ignoreReturnCode: true, @@ -34087,10 +34087,10 @@ var require_cacheUtils = __commonJS({ } }); } catch (err) { - core30.debug(err.message); + core31.debug(err.message); } versionOutput = versionOutput.trim(); - core30.debug(versionOutput); + core31.debug(versionOutput); return versionOutput; }); } @@ -34098,7 +34098,7 @@ var require_cacheUtils = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { const versionOutput = yield getVersion("zstd", ["--quiet"]); const version = semver11.clean(versionOutput); - core30.debug(`zstd version: ${version}`); + core31.debug(`zstd version: ${version}`); if (versionOutput === "") { return constants_1.CompressionMethod.Gzip; } else { @@ -74396,7 +74396,7 @@ var require_uploadUtils = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.UploadProgress = void 0; exports2.uploadCacheArchiveSDK = uploadCacheArchiveSDK; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var storage_blob_1 = require_commonjs15(); var errors_1 = require_errors2(); var UploadProgress = class { @@ -74438,7 +74438,7 @@ var require_uploadUtils = __commonJS({ const percentage = (100 * (transferredBytes / this.contentLength)).toFixed(1); const elapsedTime = Date.now() - this.startTime; const uploadSpeed = (transferredBytes / (1024 * 1024) / (elapsedTime / 1e3)).toFixed(1); - core30.info(`Sent ${transferredBytes} of ${this.contentLength} (${percentage}%), ${uploadSpeed} MBs/sec`); + core31.info(`Sent ${transferredBytes} of ${this.contentLength} (${percentage}%), ${uploadSpeed} MBs/sec`); if (this.isDone()) { this.displayedComplete = true; } @@ -74495,14 +74495,14 @@ var require_uploadUtils = __commonJS({ }; try { uploadProgress.startDisplayTimer(); - core30.debug(`BlobClient: ${blobClient.name}:${blobClient.accountName}:${blobClient.containerName}`); + core31.debug(`BlobClient: ${blobClient.name}:${blobClient.accountName}:${blobClient.containerName}`); const response = yield blockBlobClient.uploadFile(archivePath, uploadOptions); if (response._response.status >= 400) { throw new errors_1.InvalidResponseError(`uploadCacheArchiveSDK: upload failed with status code ${response._response.status}`); } return response; } catch (error3) { - core30.warning(`uploadCacheArchiveSDK: internal error uploading cache archive: ${error3.message}`); + core31.warning(`uploadCacheArchiveSDK: internal error uploading cache archive: ${error3.message}`); throw error3; } finally { uploadProgress.stopDisplayTimer(); @@ -74587,7 +74587,7 @@ var require_requestUtils = __commonJS({ exports2.retry = retry2; exports2.retryTypedResponse = retryTypedResponse; exports2.retryHttpClientResponse = retryHttpClientResponse; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var http_client_1 = require_lib(); var constants_1 = require_constants7(); function isSuccessStatusCode(statusCode) { @@ -74645,9 +74645,9 @@ var require_requestUtils = __commonJS({ isRetryable = isRetryableStatusCode(statusCode); errorMessage = `Cache service responded with ${statusCode}`; } - core30.debug(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); + core31.debug(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); if (!isRetryable) { - core30.debug(`${name} - Error is not retryable`); + core31.debug(`${name} - Error is not retryable`); break; } yield sleep(delay2); @@ -74906,7 +74906,7 @@ var require_downloadUtils = __commonJS({ exports2.downloadCacheHttpClient = downloadCacheHttpClient; exports2.downloadCacheHttpClientConcurrent = downloadCacheHttpClientConcurrent; exports2.downloadCacheStorageSDK = downloadCacheStorageSDK; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var http_client_1 = require_lib(); var storage_blob_1 = require_commonjs15(); var buffer = __importStar2(require("buffer")); @@ -74944,7 +74944,7 @@ var require_downloadUtils = __commonJS({ this.segmentIndex = this.segmentIndex + 1; this.segmentSize = segmentSize; this.receivedBytes = 0; - core30.debug(`Downloading segment at offset ${this.segmentOffset} with length ${this.segmentSize}...`); + core31.debug(`Downloading segment at offset ${this.segmentOffset} with length ${this.segmentSize}...`); } /** * Sets the number of bytes received for the current segment. @@ -74978,7 +74978,7 @@ var require_downloadUtils = __commonJS({ const percentage = (100 * (transferredBytes / this.contentLength)).toFixed(1); const elapsedTime = Date.now() - this.startTime; const downloadSpeed = (transferredBytes / (1024 * 1024) / (elapsedTime / 1e3)).toFixed(1); - core30.info(`Received ${transferredBytes} of ${this.contentLength} (${percentage}%), ${downloadSpeed} MBs/sec`); + core31.info(`Received ${transferredBytes} of ${this.contentLength} (${percentage}%), ${downloadSpeed} MBs/sec`); if (this.isDone()) { this.displayedComplete = true; } @@ -75028,7 +75028,7 @@ var require_downloadUtils = __commonJS({ })); downloadResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => { downloadResponse.message.destroy(); - core30.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); + core31.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); }); yield pipeResponseToStream(downloadResponse, writeStream); const contentLengthHeader = downloadResponse.message.headers["content-length"]; @@ -75039,7 +75039,7 @@ var require_downloadUtils = __commonJS({ throw new Error(`Incomplete download. Expected file size: ${expectedLength}, actual file size: ${actualLength}`); } } else { - core30.debug("Unable to validate download, no Content-Length header"); + core31.debug("Unable to validate download, no Content-Length header"); } }); } @@ -75157,7 +75157,7 @@ var require_downloadUtils = __commonJS({ const properties = yield client.getProperties(); const contentLength = (_a2 = properties.contentLength) !== null && _a2 !== void 0 ? _a2 : -1; if (contentLength < 0) { - core30.debug("Unable to determine content length, downloading file with http-client..."); + core31.debug("Unable to determine content length, downloading file with http-client..."); yield downloadCacheHttpClient(archiveLocation, archivePath); } else { const maxSegmentSize = Math.min(134217728, buffer.constants.MAX_LENGTH); @@ -75247,7 +75247,7 @@ var require_options = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getUploadOptions = getUploadOptions; exports2.getDownloadOptions = getDownloadOptions; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); function getUploadOptions(copy) { const result = { useAzureSdk: false, @@ -75267,9 +75267,9 @@ var require_options = __commonJS({ } result.uploadConcurrency = !isNaN(Number(process.env["CACHE_UPLOAD_CONCURRENCY"])) ? Math.min(32, Number(process.env["CACHE_UPLOAD_CONCURRENCY"])) : result.uploadConcurrency; result.uploadChunkSize = !isNaN(Number(process.env["CACHE_UPLOAD_CHUNK_SIZE"])) ? Math.min(128 * 1024 * 1024, Number(process.env["CACHE_UPLOAD_CHUNK_SIZE"]) * 1024 * 1024) : result.uploadChunkSize; - core30.debug(`Use Azure SDK: ${result.useAzureSdk}`); - core30.debug(`Upload concurrency: ${result.uploadConcurrency}`); - core30.debug(`Upload chunk size: ${result.uploadChunkSize}`); + core31.debug(`Use Azure SDK: ${result.useAzureSdk}`); + core31.debug(`Upload concurrency: ${result.uploadConcurrency}`); + core31.debug(`Upload chunk size: ${result.uploadChunkSize}`); return result; } function getDownloadOptions(copy) { @@ -75305,12 +75305,12 @@ var require_options = __commonJS({ if (segmentDownloadTimeoutMins && !isNaN(Number(segmentDownloadTimeoutMins)) && isFinite(Number(segmentDownloadTimeoutMins))) { result.segmentTimeoutInMs = Number(segmentDownloadTimeoutMins) * 60 * 1e3; } - core30.debug(`Use Azure SDK: ${result.useAzureSdk}`); - core30.debug(`Download concurrency: ${result.downloadConcurrency}`); - core30.debug(`Request timeout (ms): ${result.timeoutInMs}`); - core30.debug(`Cache segment download timeout mins env var: ${process.env["SEGMENT_DOWNLOAD_TIMEOUT_MINS"]}`); - core30.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`); - core30.debug(`Lookup only: ${result.lookupOnly}`); + core31.debug(`Use Azure SDK: ${result.useAzureSdk}`); + core31.debug(`Download concurrency: ${result.downloadConcurrency}`); + core31.debug(`Request timeout (ms): ${result.timeoutInMs}`); + core31.debug(`Cache segment download timeout mins env var: ${process.env["SEGMENT_DOWNLOAD_TIMEOUT_MINS"]}`); + core31.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`); + core31.debug(`Lookup only: ${result.lookupOnly}`); return result; } } @@ -75504,7 +75504,7 @@ var require_cacheHttpClient = __commonJS({ exports2.downloadCache = downloadCache; exports2.reserveCache = reserveCache; exports2.saveCache = saveCache5; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var http_client_1 = require_lib(); var auth_1 = require_auth(); var fs31 = __importStar2(require("fs")); @@ -75522,7 +75522,7 @@ var require_cacheHttpClient = __commonJS({ throw new Error("Cache Service Url not found, unable to restore cache."); } const url2 = `${baseUrl}_apis/artifactcache/${resource}`; - core30.debug(`Resource Url: ${url2}`); + core31.debug(`Resource Url: ${url2}`); return url2; } function createAcceptHeader(type, apiVersion) { @@ -75550,7 +75550,7 @@ var require_cacheHttpClient = __commonJS({ return httpClient.getJson(getCacheApiUrl(resource)); })); if (response.statusCode === 204) { - if (core30.isDebug()) { + if (core31.isDebug()) { yield printCachesListForDiagnostics(keys[0], httpClient, version); } return null; @@ -75563,9 +75563,9 @@ var require_cacheHttpClient = __commonJS({ if (!cacheDownloadUrl) { throw new Error("Cache not found."); } - core30.setSecret(cacheDownloadUrl); - core30.debug(`Cache Result:`); - core30.debug(JSON.stringify(cacheResult)); + core31.setSecret(cacheDownloadUrl); + core31.debug(`Cache Result:`); + core31.debug(JSON.stringify(cacheResult)); return cacheResult; }); } @@ -75579,10 +75579,10 @@ var require_cacheHttpClient = __commonJS({ const cacheListResult = response.result; const totalCount = cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.totalCount; if (totalCount && totalCount > 0) { - core30.debug(`No matching cache found for cache key '${key}', version '${version} and scope ${process.env["GITHUB_REF"]}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key + core31.debug(`No matching cache found for cache key '${key}', version '${version} and scope ${process.env["GITHUB_REF"]}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key Other caches with similar key:`); for (const cacheEntry of (cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.artifactCaches) || []) { - core30.debug(`Cache Key: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheKey}, Cache Version: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheVersion}, Cache Scope: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.scope}, Cache Created: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.creationTime}`); + core31.debug(`Cache Key: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheKey}, Cache Version: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheVersion}, Cache Scope: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.scope}, Cache Created: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.creationTime}`); } } } @@ -75625,7 +75625,7 @@ Other caches with similar key:`); } function uploadChunk(httpClient, resourceUrl, openStream, start, end) { return __awaiter2(this, void 0, void 0, function* () { - core30.debug(`Uploading chunk of size ${end - start + 1} bytes at offset ${start} with content range: ${getContentRange(start, end)}`); + core31.debug(`Uploading chunk of size ${end - start + 1} bytes at offset ${start} with content range: ${getContentRange(start, end)}`); const additionalHeaders = { "Content-Type": "application/octet-stream", "Content-Range": getContentRange(start, end) @@ -75647,7 +75647,7 @@ Other caches with similar key:`); const concurrency = utils.assertDefined("uploadConcurrency", uploadOptions.uploadConcurrency); const maxChunkSize = utils.assertDefined("uploadChunkSize", uploadOptions.uploadChunkSize); const parallelUploads = [...new Array(concurrency).keys()]; - core30.debug("Awaiting all uploads"); + core31.debug("Awaiting all uploads"); let offset = 0; try { yield Promise.all(parallelUploads.map(() => __awaiter2(this, void 0, void 0, function* () { @@ -75690,16 +75690,16 @@ Other caches with similar key:`); yield (0, uploadUtils_1.uploadCacheArchiveSDK)(signedUploadURL, archivePath, options); } else { const httpClient = createHttpClient(); - core30.debug("Upload cache"); + core31.debug("Upload cache"); yield uploadFile(httpClient, cacheId, archivePath, options); - core30.debug("Commiting cache"); + core31.debug("Commiting cache"); const cacheSize = utils.getArchiveFileSizeInBytes(archivePath); - core30.info(`Cache Size: ~${Math.round(cacheSize / (1024 * 1024))} MB (${cacheSize} B)`); + core31.info(`Cache Size: ~${Math.round(cacheSize / (1024 * 1024))} MB (${cacheSize} B)`); const commitCacheResponse = yield commitCache(httpClient, cacheId, cacheSize); if (!(0, requestUtils_1.isSuccessStatusCode)(commitCacheResponse.statusCode)) { throw new Error(`Cache service responded with ${commitCacheResponse.statusCode} during commit cache.`); } - core30.info("Cache saved successfully"); + core31.info("Cache saved successfully"); } }); } @@ -81182,7 +81182,7 @@ var require_cache4 = __commonJS({ exports2.isFeatureAvailable = isFeatureAvailable; exports2.restoreCache = restoreCache5; exports2.saveCache = saveCache5; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var path29 = __importStar2(require("path")); var utils = __importStar2(require_cacheUtils()); var cacheHttpClient = __importStar2(require_cacheHttpClient()); @@ -81250,7 +81250,7 @@ var require_cache4 = __commonJS({ function restoreCache5(paths_1, primaryKey_1, restoreKeys_1, options_1) { return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) { const cacheServiceVersion = (0, config_1.getCacheServiceVersion)(); - core30.debug(`Cache service version: ${cacheServiceVersion}`); + core31.debug(`Cache service version: ${cacheServiceVersion}`); checkPaths(paths); switch (cacheServiceVersion) { case "v2": @@ -81265,8 +81265,8 @@ var require_cache4 = __commonJS({ return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) { restoreKeys = restoreKeys || []; const keys = [primaryKey, ...restoreKeys]; - core30.debug("Resolved Keys:"); - core30.debug(JSON.stringify(keys)); + core31.debug("Resolved Keys:"); + core31.debug(JSON.stringify(keys)); if (keys.length > 10) { throw new ValidationError(`Key Validation Error: Keys are limited to a maximum of 10.`); } @@ -81284,19 +81284,19 @@ var require_cache4 = __commonJS({ return void 0; } if (options === null || options === void 0 ? void 0 : options.lookupOnly) { - core30.info("Lookup only - skipping download"); + core31.info("Lookup only - skipping download"); return cacheEntry.cacheKey; } archivePath = path29.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); - core30.debug(`Archive Path: ${archivePath}`); + core31.debug(`Archive Path: ${archivePath}`); yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options); - if (core30.isDebug()) { + if (core31.isDebug()) { yield (0, tar_1.listTar)(archivePath, compressionMethod); } const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath); - core30.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); + core31.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); yield (0, tar_1.extractTar)(archivePath, compressionMethod); - core30.info("Cache restored successfully"); + core31.info("Cache restored successfully"); return cacheEntry.cacheKey; } catch (error3) { const typedError = error3; @@ -81304,16 +81304,16 @@ var require_cache4 = __commonJS({ throw error3; } else { if (typedError instanceof http_client_1.HttpClientError && typeof typedError.statusCode === "number" && typedError.statusCode >= 500) { - core30.error(`Failed to restore: ${error3.message}`); + core31.error(`Failed to restore: ${error3.message}`); } else { - core30.warning(`Failed to restore: ${error3.message}`); + core31.warning(`Failed to restore: ${error3.message}`); } } } finally { try { yield utils.unlinkFile(archivePath); } catch (error3) { - core30.debug(`Failed to delete archive: ${error3}`); + core31.debug(`Failed to delete archive: ${error3}`); } } return void 0; @@ -81324,8 +81324,8 @@ var require_cache4 = __commonJS({ options = Object.assign(Object.assign({}, options), { useAzureSdk: true }); restoreKeys = restoreKeys || []; const keys = [primaryKey, ...restoreKeys]; - core30.debug("Resolved Keys:"); - core30.debug(JSON.stringify(keys)); + core31.debug("Resolved Keys:"); + core31.debug(JSON.stringify(keys)); if (keys.length > 10) { throw new ValidationError(`Key Validation Error: Keys are limited to a maximum of 10.`); } @@ -81343,30 +81343,30 @@ var require_cache4 = __commonJS({ }; const response = yield twirpClient.GetCacheEntryDownloadURL(request3); if (!response.ok) { - core30.debug(`Cache not found for version ${request3.version} of keys: ${keys.join(", ")}`); + core31.debug(`Cache not found for version ${request3.version} of keys: ${keys.join(", ")}`); return void 0; } const isRestoreKeyMatch = request3.key !== response.matchedKey; if (isRestoreKeyMatch) { - core30.info(`Cache hit for restore-key: ${response.matchedKey}`); + core31.info(`Cache hit for restore-key: ${response.matchedKey}`); } else { - core30.info(`Cache hit for: ${response.matchedKey}`); + core31.info(`Cache hit for: ${response.matchedKey}`); } if (options === null || options === void 0 ? void 0 : options.lookupOnly) { - core30.info("Lookup only - skipping download"); + core31.info("Lookup only - skipping download"); return response.matchedKey; } archivePath = path29.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); - core30.debug(`Archive path: ${archivePath}`); - core30.debug(`Starting download of archive to: ${archivePath}`); + core31.debug(`Archive path: ${archivePath}`); + core31.debug(`Starting download of archive to: ${archivePath}`); yield cacheHttpClient.downloadCache(response.signedDownloadUrl, archivePath, options); const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath); - core30.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); - if (core30.isDebug()) { + core31.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); + if (core31.isDebug()) { yield (0, tar_1.listTar)(archivePath, compressionMethod); } yield (0, tar_1.extractTar)(archivePath, compressionMethod); - core30.info("Cache restored successfully"); + core31.info("Cache restored successfully"); return response.matchedKey; } catch (error3) { const typedError = error3; @@ -81374,9 +81374,9 @@ var require_cache4 = __commonJS({ throw error3; } else { if (typedError instanceof http_client_1.HttpClientError && typeof typedError.statusCode === "number" && typedError.statusCode >= 500) { - core30.error(`Failed to restore: ${error3.message}`); + core31.error(`Failed to restore: ${error3.message}`); } else { - core30.warning(`Failed to restore: ${error3.message}`); + core31.warning(`Failed to restore: ${error3.message}`); } } } finally { @@ -81385,7 +81385,7 @@ var require_cache4 = __commonJS({ yield utils.unlinkFile(archivePath); } } catch (error3) { - core30.debug(`Failed to delete archive: ${error3}`); + core31.debug(`Failed to delete archive: ${error3}`); } } return void 0; @@ -81394,7 +81394,7 @@ var require_cache4 = __commonJS({ function saveCache5(paths_1, key_1, options_1) { return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) { const cacheServiceVersion = (0, config_1.getCacheServiceVersion)(); - core30.debug(`Cache service version: ${cacheServiceVersion}`); + core31.debug(`Cache service version: ${cacheServiceVersion}`); checkPaths(paths); checkKey(key); switch (cacheServiceVersion) { @@ -81412,26 +81412,26 @@ var require_cache4 = __commonJS({ const compressionMethod = yield utils.getCompressionMethod(); let cacheId = -1; const cachePaths = yield utils.resolvePaths(paths); - core30.debug("Cache Paths:"); - core30.debug(`${JSON.stringify(cachePaths)}`); + core31.debug("Cache Paths:"); + core31.debug(`${JSON.stringify(cachePaths)}`); if (cachePaths.length === 0) { throw new Error(`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`); } const archiveFolder = yield utils.createTempDirectory(); const archivePath = path29.join(archiveFolder, utils.getCacheFileName(compressionMethod)); - core30.debug(`Archive Path: ${archivePath}`); + core31.debug(`Archive Path: ${archivePath}`); try { yield (0, tar_1.createTar)(archiveFolder, cachePaths, compressionMethod); - if (core30.isDebug()) { + if (core31.isDebug()) { yield (0, tar_1.listTar)(archivePath, compressionMethod); } const fileSizeLimit = 10 * 1024 * 1024 * 1024; const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath); - core30.debug(`File Size: ${archiveFileSize}`); + core31.debug(`File Size: ${archiveFileSize}`); if (archiveFileSize > fileSizeLimit && !(0, config_1.isGhes)()) { throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`); } - core30.debug("Reserving Cache"); + core31.debug("Reserving Cache"); const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, { compressionMethod, enableCrossOsArchive, @@ -81448,28 +81448,28 @@ var require_cache4 = __commonJS({ } throw new ReserveCacheError2(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${detailMessage}`); } - core30.debug(`Saving Cache (ID: ${cacheId})`); + core31.debug(`Saving Cache (ID: ${cacheId})`); yield cacheHttpClient.saveCache(cacheId, archivePath, "", options); } catch (error3) { const typedError = error3; if (typedError.name === ValidationError.name) { throw error3; } else if (typedError.name === CacheWriteDeniedError.name) { - core30.warning(`Failed to save: ${typedError.message}`); + core31.warning(`Failed to save: ${typedError.message}`); } else if (typedError.name === ReserveCacheError2.name) { - core30.info(`Failed to save: ${typedError.message}`); + core31.info(`Failed to save: ${typedError.message}`); } else { if (typedError instanceof http_client_1.HttpClientError && typeof typedError.statusCode === "number" && typedError.statusCode >= 500) { - core30.error(`Failed to save: ${typedError.message}`); + core31.error(`Failed to save: ${typedError.message}`); } else { - core30.warning(`Failed to save: ${typedError.message}`); + core31.warning(`Failed to save: ${typedError.message}`); } } } finally { try { yield utils.unlinkFile(archivePath); } catch (error3) { - core30.debug(`Failed to delete archive: ${error3}`); + core31.debug(`Failed to delete archive: ${error3}`); } } return cacheId; @@ -81483,23 +81483,23 @@ var require_cache4 = __commonJS({ const twirpClient = cacheTwirpClient.internalCacheTwirpClient(); let cacheId = -1; const cachePaths = yield utils.resolvePaths(paths); - core30.debug("Cache Paths:"); - core30.debug(`${JSON.stringify(cachePaths)}`); + core31.debug("Cache Paths:"); + core31.debug(`${JSON.stringify(cachePaths)}`); if (cachePaths.length === 0) { throw new Error(`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`); } const archiveFolder = yield utils.createTempDirectory(); const archivePath = path29.join(archiveFolder, utils.getCacheFileName(compressionMethod)); - core30.debug(`Archive Path: ${archivePath}`); + core31.debug(`Archive Path: ${archivePath}`); try { yield (0, tar_1.createTar)(archiveFolder, cachePaths, compressionMethod); - if (core30.isDebug()) { + if (core31.isDebug()) { yield (0, tar_1.listTar)(archivePath, compressionMethod); } const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath); - core30.debug(`File Size: ${archiveFileSize}`); + core31.debug(`File Size: ${archiveFileSize}`); options.archiveSizeBytes = archiveFileSize; - core30.debug("Reserving Cache"); + core31.debug("Reserving Cache"); const version = utils.getCacheVersion(paths, compressionMethod, enableCrossOsArchive); const request3 = { key, @@ -81510,20 +81510,20 @@ var require_cache4 = __commonJS({ const response = yield twirpClient.CreateCacheEntry(request3); if (!response.ok) { if (response.message && !response.message.startsWith(exports2.CACHE_WRITE_DENIED_PREFIX)) { - core30.warning(`Cache reservation failed: ${response.message}`); + core31.warning(`Cache reservation failed: ${response.message}`); } throw new Error(response.message || "Response was not ok"); } signedUploadUrl = response.signedUploadUrl; } catch (error3) { - core30.debug(`Failed to reserve cache: ${error3}`); + core31.debug(`Failed to reserve cache: ${error3}`); const errorMessage = (_a2 = error3 === null || error3 === void 0 ? void 0 : error3.message) !== null && _a2 !== void 0 ? _a2 : ""; if (errorMessage.startsWith(exports2.CACHE_WRITE_DENIED_PREFIX)) { throw new CacheWriteDeniedError(`Unable to reserve cache with key ${key}. More details: ${errorMessage}`); } throw new ReserveCacheError2(`Unable to reserve cache with key ${key}, another job may be creating this cache.`); } - core30.debug(`Attempting to upload cache located at: ${archivePath}`); + core31.debug(`Attempting to upload cache located at: ${archivePath}`); yield cacheHttpClient.saveCache(cacheId, archivePath, signedUploadUrl, options); const finalizeRequest = { key, @@ -81531,7 +81531,7 @@ var require_cache4 = __commonJS({ sizeBytes: `${archiveFileSize}` }; const finalizeResponse = yield twirpClient.FinalizeCacheEntryUpload(finalizeRequest); - core30.debug(`FinalizeCacheEntryUploadResponse: ${finalizeResponse.ok}`); + core31.debug(`FinalizeCacheEntryUploadResponse: ${finalizeResponse.ok}`); if (!finalizeResponse.ok) { if (finalizeResponse.message) { throw new FinalizeCacheError(finalizeResponse.message); @@ -81544,23 +81544,23 @@ var require_cache4 = __commonJS({ if (typedError.name === ValidationError.name) { throw error3; } else if (typedError.name === CacheWriteDeniedError.name) { - core30.warning(`Failed to save: ${typedError.message}`); + core31.warning(`Failed to save: ${typedError.message}`); } else if (typedError.name === ReserveCacheError2.name) { - core30.info(`Failed to save: ${typedError.message}`); + core31.info(`Failed to save: ${typedError.message}`); } else if (typedError.name === FinalizeCacheError.name) { - core30.warning(typedError.message); + core31.warning(typedError.message); } else { if (typedError instanceof http_client_1.HttpClientError && typeof typedError.statusCode === "number" && typedError.statusCode >= 500) { - core30.error(`Failed to save: ${typedError.message}`); + core31.error(`Failed to save: ${typedError.message}`); } else { - core30.warning(`Failed to save: ${typedError.message}`); + core31.warning(`Failed to save: ${typedError.message}`); } } } finally { try { yield utils.unlinkFile(archivePath); } catch (error3) { - core30.debug(`Failed to delete archive: ${error3}`); + core31.debug(`Failed to delete archive: ${error3}`); } } return cacheId; @@ -81787,7 +81787,7 @@ var require_retry_helper = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.RetryHelper = void 0; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var RetryHelper = class { constructor(maxAttempts, minSeconds, maxSeconds) { if (maxAttempts < 1) { @@ -81810,10 +81810,10 @@ var require_retry_helper = __commonJS({ if (isRetryable && !isRetryable(err)) { throw err; } - core30.info(err.message); + core31.info(err.message); } const seconds = this.getSleepAmount(); - core30.info(`Waiting ${seconds} seconds before trying again`); + core31.info(`Waiting ${seconds} seconds before trying again`); yield this.sleep(seconds); attempt++; } @@ -81916,7 +81916,7 @@ var require_tool_cache = __commonJS({ exports2.findFromManifest = findFromManifest; exports2.isExplicitVersion = isExplicitVersion; exports2.evaluateVersions = evaluateVersions; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var io9 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); var fs31 = __importStar2(require("fs")); @@ -81945,8 +81945,8 @@ var require_tool_cache = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { dest = dest || path29.join(_getTempDirectory(), crypto3.randomUUID()); yield io9.mkdirP(path29.dirname(dest)); - core30.debug(`Downloading ${url2}`); - core30.debug(`Destination ${dest}`); + core31.debug(`Downloading ${url2}`); + core31.debug(`Destination ${dest}`); const maxAttempts = 3; const minSeconds = _getGlobal("TEST_DOWNLOAD_TOOL_RETRY_MIN_SECONDS", 10); const maxSeconds = _getGlobal("TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS", 20); @@ -81972,7 +81972,7 @@ var require_tool_cache = __commonJS({ allowRetries: false }); if (auth2) { - core30.debug("set auth"); + core31.debug("set auth"); if (headers === void 0) { headers = {}; } @@ -81981,7 +81981,7 @@ var require_tool_cache = __commonJS({ const response = yield http.get(url2, headers); if (response.message.statusCode !== 200) { const err = new HTTPError2(response.message.statusCode); - core30.debug(`Failed to download from "${url2}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); + core31.debug(`Failed to download from "${url2}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); throw err; } const pipeline = util3.promisify(stream2.pipeline); @@ -81990,16 +81990,16 @@ var require_tool_cache = __commonJS({ let succeeded = false; try { yield pipeline(readStream, fs31.createWriteStream(dest)); - core30.debug("download complete"); + core31.debug("download complete"); succeeded = true; return dest; } finally { if (!succeeded) { - core30.debug("download failed"); + core31.debug("download failed"); try { yield io9.rmRF(dest); } catch (err) { - core30.debug(`Failed to delete '${dest}'. ${err.message}`); + core31.debug(`Failed to delete '${dest}'. ${err.message}`); } } } @@ -82014,7 +82014,7 @@ var require_tool_cache = __commonJS({ process.chdir(dest); if (_7zPath) { try { - const logLevel = core30.isDebug() ? "-bb1" : "-bb0"; + const logLevel = core31.isDebug() ? "-bb1" : "-bb0"; const args = [ "x", // eXtract files with full paths @@ -82067,7 +82067,7 @@ var require_tool_cache = __commonJS({ throw new Error("parameter 'file' is required"); } dest = yield _createExtractFolder(dest); - core30.debug("Checking tar --version"); + core31.debug("Checking tar --version"); let versionOutput = ""; yield (0, exec_1.exec)("tar --version", [], { ignoreReturnCode: true, @@ -82077,7 +82077,7 @@ var require_tool_cache = __commonJS({ stderr: (data) => versionOutput += data.toString() } }); - core30.debug(versionOutput.trim()); + core31.debug(versionOutput.trim()); const isGnuTar = versionOutput.toUpperCase().includes("GNU TAR"); let args; if (flags instanceof Array) { @@ -82085,7 +82085,7 @@ var require_tool_cache = __commonJS({ } else { args = [flags]; } - if (core30.isDebug() && !flags.includes("v")) { + if (core31.isDebug() && !flags.includes("v")) { args.push("-v"); } let destArg = dest; @@ -82116,7 +82116,7 @@ var require_tool_cache = __commonJS({ args = [flags]; } args.push("-x", "-C", dest, "-f", file); - if (core30.isDebug()) { + if (core31.isDebug()) { args.push("-v"); } const xarPath = yield io9.which("xar", true); @@ -82159,7 +82159,7 @@ var require_tool_cache = __commonJS({ "-Command", pwshCommand ]; - core30.debug(`Using pwsh at path: ${pwshPath}`); + core31.debug(`Using pwsh at path: ${pwshPath}`); yield (0, exec_1.exec)(`"${pwshPath}"`, args); } else { const powershellCommand = [ @@ -82179,7 +82179,7 @@ var require_tool_cache = __commonJS({ powershellCommand ]; const powershellPath = yield io9.which("powershell", true); - core30.debug(`Using powershell at path: ${powershellPath}`); + core31.debug(`Using powershell at path: ${powershellPath}`); yield (0, exec_1.exec)(`"${powershellPath}"`, args); } }); @@ -82188,7 +82188,7 @@ var require_tool_cache = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { const unzipPath = yield io9.which("unzip", true); const args = [file]; - if (!core30.isDebug()) { + if (!core31.isDebug()) { args.unshift("-q"); } args.unshift("-o"); @@ -82199,8 +82199,8 @@ var require_tool_cache = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { version = semver11.clean(version) || version; arch2 = arch2 || os7.arch(); - core30.debug(`Caching tool ${tool} ${version} ${arch2}`); - core30.debug(`source dir: ${sourceDir}`); + core31.debug(`Caching tool ${tool} ${version} ${arch2}`); + core31.debug(`source dir: ${sourceDir}`); if (!fs31.statSync(sourceDir).isDirectory()) { throw new Error("sourceDir is not a directory"); } @@ -82217,14 +82217,14 @@ var require_tool_cache = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { version = semver11.clean(version) || version; arch2 = arch2 || os7.arch(); - core30.debug(`Caching tool ${tool} ${version} ${arch2}`); - core30.debug(`source file: ${sourceFile}`); + core31.debug(`Caching tool ${tool} ${version} ${arch2}`); + core31.debug(`source file: ${sourceFile}`); if (!fs31.statSync(sourceFile).isFile()) { throw new Error("sourceFile is not a file"); } const destFolder = yield _createToolPath(tool, version, arch2); const destPath = path29.join(destFolder, targetFile); - core30.debug(`destination file ${destPath}`); + core31.debug(`destination file ${destPath}`); yield io9.cp(sourceFile, destPath); _completeToolPath(tool, version, arch2); return destFolder; @@ -82247,12 +82247,12 @@ var require_tool_cache = __commonJS({ if (versionSpec) { versionSpec = semver11.clean(versionSpec) || ""; const cachePath = path29.join(_getCacheDirectory(), toolName, versionSpec, arch2); - core30.debug(`checking cache: ${cachePath}`); + core31.debug(`checking cache: ${cachePath}`); if (fs31.existsSync(cachePath) && fs31.existsSync(`${cachePath}.complete`)) { - core30.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch2}`); + core31.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch2}`); toolPath = cachePath; } else { - core30.debug("not found"); + core31.debug("not found"); } } return toolPath; @@ -82281,7 +82281,7 @@ var require_tool_cache = __commonJS({ const http = new httpm.HttpClient("tool-cache"); const headers = {}; if (auth2) { - core30.debug("set auth"); + core31.debug("set auth"); headers.authorization = auth2; } const response = yield http.getJson(treeUrl, headers); @@ -82302,7 +82302,7 @@ var require_tool_cache = __commonJS({ try { releases = JSON.parse(versionsRaw); } catch (_a2) { - core30.debug("Invalid json"); + core31.debug("Invalid json"); } } return releases; @@ -82326,7 +82326,7 @@ var require_tool_cache = __commonJS({ function _createToolPath(tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { const folderPath = path29.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); - core30.debug(`destination ${folderPath}`); + core31.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; yield io9.rmRF(folderPath); yield io9.rmRF(markerPath); @@ -82338,18 +82338,18 @@ var require_tool_cache = __commonJS({ const folderPath = path29.join(_getCacheDirectory(), tool, semver11.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; fs31.writeFileSync(markerPath, ""); - core30.debug("finished caching tool"); + core31.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { const c = semver11.clean(versionSpec) || ""; - core30.debug(`isExplicit: ${c}`); + core31.debug(`isExplicit: ${c}`); const valid4 = semver11.valid(c) != null; - core30.debug(`explicit? ${valid4}`); + core31.debug(`explicit? ${valid4}`); return valid4; } function evaluateVersions(versions, versionSpec) { let version = ""; - core30.debug(`evaluating ${versions.length} versions`); + core31.debug(`evaluating ${versions.length} versions`); versions = versions.sort((a, b) => { if (semver11.gt(a, b)) { return 1; @@ -82365,9 +82365,9 @@ var require_tool_cache = __commonJS({ } } if (version) { - core30.debug(`matched: ${version}`); + core31.debug(`matched: ${version}`); } else { - core30.debug("match not found"); + core31.debug("match not found"); } return version; } @@ -87960,14 +87960,14 @@ var require_retention = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getExpiration = void 0; var generated_1 = require_generated(); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); function getExpiration(retentionDays) { if (!retentionDays) { return void 0; } const maxRetentionDays = getRetentionDays(); if (maxRetentionDays && maxRetentionDays < retentionDays) { - core30.warning(`Retention days cannot be greater than the maximum allowed retention set within the repository. Using ${maxRetentionDays} instead.`); + core31.warning(`Retention days cannot be greater than the maximum allowed retention set within the repository. Using ${maxRetentionDays} instead.`); retentionDays = maxRetentionDays; } const expirationDate = /* @__PURE__ */ new Date(); @@ -88305,7 +88305,7 @@ var require_util11 = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.maskSecretUrls = exports2.maskSigUrl = exports2.getBackendIdsFromToken = void 0; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var config_1 = require_config2(); var jwt_decode_1 = __importDefault2(require_jwt_decode_cjs()); var core_1 = require_core(); @@ -88332,8 +88332,8 @@ var require_util11 = __commonJS({ workflowRunBackendId: scopeParts[1], workflowJobRunBackendId: scopeParts[2] }; - core30.debug(`Workflow Run Backend ID: ${ids.workflowRunBackendId}`); - core30.debug(`Workflow Job Run Backend ID: ${ids.workflowJobRunBackendId}`); + core31.debug(`Workflow Run Backend ID: ${ids.workflowRunBackendId}`); + core31.debug(`Workflow Job Run Backend ID: ${ids.workflowJobRunBackendId}`); return ids; } throw InvalidJwtError; @@ -88693,7 +88693,7 @@ var require_blob_upload = __commonJS({ exports2.uploadZipToBlobStorage = void 0; var storage_blob_1 = require_commonjs15(); var config_1 = require_config2(); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var crypto3 = __importStar2(require("crypto")); var stream2 = __importStar2(require("stream")); var errors_1 = require_errors3(); @@ -88719,9 +88719,9 @@ var require_blob_upload = __commonJS({ const bufferSize = (0, config_1.getUploadChunkSize)(); const blobClient = new storage_blob_1.BlobClient(authenticatedUploadURL); const blockBlobClient = blobClient.getBlockBlobClient(); - core30.debug(`Uploading artifact zip to blob storage with maxConcurrency: ${maxConcurrency}, bufferSize: ${bufferSize}`); + core31.debug(`Uploading artifact zip to blob storage with maxConcurrency: ${maxConcurrency}, bufferSize: ${bufferSize}`); const uploadCallback = (progress) => { - core30.info(`Uploaded bytes ${progress.loadedBytes}`); + core31.info(`Uploaded bytes ${progress.loadedBytes}`); uploadByteCount = progress.loadedBytes; lastProgressTime = Date.now(); }; @@ -88735,7 +88735,7 @@ var require_blob_upload = __commonJS({ const hashStream = crypto3.createHash("sha256"); zipUploadStream.pipe(uploadStream); zipUploadStream.pipe(hashStream).setEncoding("hex"); - core30.info("Beginning upload of artifact content to blob storage"); + core31.info("Beginning upload of artifact content to blob storage"); try { yield Promise.race([ blockBlobClient.uploadStream(uploadStream, bufferSize, maxConcurrency, options), @@ -88749,12 +88749,12 @@ var require_blob_upload = __commonJS({ } finally { abortController.abort(); } - core30.info("Finished uploading artifact content to blob storage!"); + core31.info("Finished uploading artifact content to blob storage!"); hashStream.end(); sha256Hash = hashStream.read(); - core30.info(`SHA256 digest of uploaded artifact zip is ${sha256Hash}`); + core31.info(`SHA256 digest of uploaded artifact zip is ${sha256Hash}`); if (uploadByteCount === 0) { - core30.warning(`No data was uploaded to blob storage. Reported upload byte count is 0.`); + core31.warning(`No data was uploaded to blob storage. Reported upload byte count is 0.`); } return { uploadSize: uploadByteCount, @@ -110318,7 +110318,7 @@ var require_zip2 = __commonJS({ var stream2 = __importStar2(require("stream")); var promises_1 = require("fs/promises"); var archiver = __importStar2(require_archiver()); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var config_1 = require_config2(); exports2.DEFAULT_COMPRESSION_LEVEL = 6; var ZipUploadStream = class extends stream2.Transform { @@ -110335,7 +110335,7 @@ var require_zip2 = __commonJS({ exports2.ZipUploadStream = ZipUploadStream; function createZipUploadStream(uploadSpecification_1) { return __awaiter2(this, arguments, void 0, function* (uploadSpecification, compressionLevel = exports2.DEFAULT_COMPRESSION_LEVEL) { - core30.debug(`Creating Artifact archive with compressionLevel: ${compressionLevel}`); + core31.debug(`Creating Artifact archive with compressionLevel: ${compressionLevel}`); const zip = archiver.create("zip", { highWaterMark: (0, config_1.getUploadChunkSize)(), zlib: { level: compressionLevel } @@ -110359,8 +110359,8 @@ var require_zip2 = __commonJS({ } const bufferSize = (0, config_1.getUploadChunkSize)(); const zipUploadStream = new ZipUploadStream(bufferSize); - core30.debug(`Zip write high watermark value ${zipUploadStream.writableHighWaterMark}`); - core30.debug(`Zip read high watermark value ${zipUploadStream.readableHighWaterMark}`); + core31.debug(`Zip write high watermark value ${zipUploadStream.writableHighWaterMark}`); + core31.debug(`Zip read high watermark value ${zipUploadStream.readableHighWaterMark}`); zip.pipe(zipUploadStream); zip.finalize(); return zipUploadStream; @@ -110368,24 +110368,24 @@ var require_zip2 = __commonJS({ } exports2.createZipUploadStream = createZipUploadStream; var zipErrorCallback = (error3) => { - core30.error("An error has occurred while creating the zip file for upload"); - core30.info(error3); + core31.error("An error has occurred while creating the zip file for upload"); + core31.info(error3); throw new Error("An error has occurred during zip creation for the artifact"); }; var zipWarningCallback = (error3) => { if (error3.code === "ENOENT") { - core30.warning("ENOENT warning during artifact zip creation. No such file or directory"); - core30.info(error3); + core31.warning("ENOENT warning during artifact zip creation. No such file or directory"); + core31.info(error3); } else { - core30.warning(`A non-blocking warning has occurred during artifact zip creation: ${error3.code}`); - core30.info(error3); + core31.warning(`A non-blocking warning has occurred during artifact zip creation: ${error3.code}`); + core31.info(error3); } }; var zipFinishCallback = () => { - core30.debug("Zip stream for upload has finished."); + core31.debug("Zip stream for upload has finished."); }; var zipEndCallback = () => { - core30.debug("Zip stream for upload has ended."); + core31.debug("Zip stream for upload has ended."); }; } }); @@ -110450,7 +110450,7 @@ var require_upload_artifact = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.uploadArtifact = void 0; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var retention_1 = require_retention(); var path_and_artifact_name_validation_1 = require_path_and_artifact_name_validation(); var artifact_twirp_client_1 = require_artifact_twirp_client2(); @@ -110497,13 +110497,13 @@ var require_upload_artifact = __commonJS({ value: `sha256:${uploadResult.sha256Hash}` }); } - core30.info(`Finalizing artifact upload`); + core31.info(`Finalizing artifact upload`); const finalizeArtifactResp = yield artifactClient.FinalizeArtifact(finalizeArtifactReq); if (!finalizeArtifactResp.ok) { throw new errors_1.InvalidResponseError("FinalizeArtifact: response from backend was not ok"); } const artifactId = BigInt(finalizeArtifactResp.artifactId); - core30.info(`Artifact ${name}.zip successfully finalized. Artifact ID ${artifactId}`); + core31.info(`Artifact ${name}.zip successfully finalized. Artifact ID ${artifactId}`); return { size: uploadResult.uploadSize, digest: uploadResult.sha256Hash, @@ -117227,7 +117227,7 @@ var require_download_artifact = __commonJS({ var crypto3 = __importStar2(require("crypto")); var stream2 = __importStar2(require("stream")); var github5 = __importStar2(require_github2()); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var httpClient = __importStar2(require_lib()); var unzip_stream_1 = __importDefault2(require_unzip()); var user_agent_1 = require_user_agent2(); @@ -117263,7 +117263,7 @@ var require_download_artifact = __commonJS({ return yield streamExtractExternal(url2, directory); } catch (error3) { retryCount++; - core30.debug(`Failed to download artifact after ${retryCount} retries due to ${error3.message}. Retrying in 5 seconds...`); + core31.debug(`Failed to download artifact after ${retryCount} retries due to ${error3.message}. Retrying in 5 seconds...`); yield new Promise((resolve14) => setTimeout(resolve14, 5e3)); } } @@ -117293,7 +117293,7 @@ var require_download_artifact = __commonJS({ extractStream.on("data", () => { timer.refresh(); }).on("error", (error3) => { - core30.debug(`response.message: Artifact download failed: ${error3.message}`); + core31.debug(`response.message: Artifact download failed: ${error3.message}`); clearTimeout(timer); reject(error3); }).pipe(unzip_stream_1.default.Extract({ path: directory })).on("close", () => { @@ -117301,7 +117301,7 @@ var require_download_artifact = __commonJS({ if (hashStream) { hashStream.end(); sha256Digest = hashStream.read(); - core30.info(`SHA256 digest of downloaded artifact is ${sha256Digest}`); + core31.info(`SHA256 digest of downloaded artifact is ${sha256Digest}`); } resolve14({ sha256Digest: `sha256:${sha256Digest}` }); }).on("error", (error3) => { @@ -117316,7 +117316,7 @@ var require_download_artifact = __commonJS({ const downloadPath = yield resolveOrCreateDirectory(options === null || options === void 0 ? void 0 : options.path); const api = github5.getOctokit(token); let digestMismatch = false; - core30.info(`Downloading artifact '${artifactId}' from '${repositoryOwner}/${repositoryName}'`); + core31.info(`Downloading artifact '${artifactId}' from '${repositoryOwner}/${repositoryName}'`); const { headers, status } = yield api.rest.actions.downloadArtifact({ owner: repositoryOwner, repo: repositoryName, @@ -117333,16 +117333,16 @@ var require_download_artifact = __commonJS({ if (!location) { throw new Error(`Unable to redirect to artifact download url`); } - core30.info(`Redirecting to blob download url: ${scrubQueryParameters(location)}`); + core31.info(`Redirecting to blob download url: ${scrubQueryParameters(location)}`); try { - core30.info(`Starting download of artifact to: ${downloadPath}`); + core31.info(`Starting download of artifact to: ${downloadPath}`); const extractResponse = yield streamExtract(location, downloadPath); - core30.info(`Artifact download completed successfully.`); + core31.info(`Artifact download completed successfully.`); if (options === null || options === void 0 ? void 0 : options.expectedHash) { if ((options === null || options === void 0 ? void 0 : options.expectedHash) !== extractResponse.sha256Digest) { digestMismatch = true; - core30.debug(`Computed digest: ${extractResponse.sha256Digest}`); - core30.debug(`Expected digest: ${options.expectedHash}`); + core31.debug(`Computed digest: ${extractResponse.sha256Digest}`); + core31.debug(`Expected digest: ${options.expectedHash}`); } } } catch (error3) { @@ -117369,7 +117369,7 @@ var require_download_artifact = __commonJS({ Are you trying to download from a different run? Try specifying a github-token with \`actions:read\` scope.`); } if (artifacts.length > 1) { - core30.warning("Multiple artifacts found, defaulting to first."); + core31.warning("Multiple artifacts found, defaulting to first."); } const signedReq = { workflowRunBackendId: artifacts[0].workflowRunBackendId, @@ -117377,16 +117377,16 @@ Are you trying to download from a different run? Try specifying a github-token w name: artifacts[0].name }; const { signedUrl } = yield artifactClient.GetSignedArtifactURL(signedReq); - core30.info(`Redirecting to blob download url: ${scrubQueryParameters(signedUrl)}`); + core31.info(`Redirecting to blob download url: ${scrubQueryParameters(signedUrl)}`); try { - core30.info(`Starting download of artifact to: ${downloadPath}`); + core31.info(`Starting download of artifact to: ${downloadPath}`); const extractResponse = yield streamExtract(signedUrl, downloadPath); - core30.info(`Artifact download completed successfully.`); + core31.info(`Artifact download completed successfully.`); if (options === null || options === void 0 ? void 0 : options.expectedHash) { if ((options === null || options === void 0 ? void 0 : options.expectedHash) !== extractResponse.sha256Digest) { digestMismatch = true; - core30.debug(`Computed digest: ${extractResponse.sha256Digest}`); - core30.debug(`Expected digest: ${options.expectedHash}`); + core31.debug(`Computed digest: ${extractResponse.sha256Digest}`); + core31.debug(`Expected digest: ${options.expectedHash}`); } } } catch (error3) { @@ -117399,10 +117399,10 @@ Are you trying to download from a different run? Try specifying a github-token w function resolveOrCreateDirectory() { return __awaiter2(this, arguments, void 0, function* (downloadPath = (0, config_1.getGitHubWorkspaceDir)()) { if (!(yield exists(downloadPath))) { - core30.debug(`Artifact destination folder does not exist, creating: ${downloadPath}`); + core31.debug(`Artifact destination folder does not exist, creating: ${downloadPath}`); yield promises_1.default.mkdir(downloadPath, { recursive: true }); } else { - core30.debug(`Artifact destination folder already exists: ${downloadPath}`); + core31.debug(`Artifact destination folder already exists: ${downloadPath}`); } return downloadPath; }); @@ -117443,7 +117443,7 @@ var require_retry_options = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getRetryOptions = void 0; - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var defaultMaxRetryNumber = 5; var defaultExemptStatusCodes = [400, 401, 403, 404, 422]; function getRetryOptions(defaultOptions, retries = defaultMaxRetryNumber, exemptStatusCodes = defaultExemptStatusCodes) { @@ -117458,7 +117458,7 @@ var require_retry_options = __commonJS({ retryOptions.doNotRetry = exemptStatusCodes; } const requestOptions = Object.assign(Object.assign({}, defaultOptions.request), { retries }); - core30.debug(`GitHub client configured with: (retries: ${requestOptions.retries}, retry-exempt-status-code: ${(_a2 = retryOptions.doNotRetry) !== null && _a2 !== void 0 ? _a2 : "octokit default: [400, 401, 403, 404, 422]"})`); + core31.debug(`GitHub client configured with: (retries: ${requestOptions.retries}, retry-exempt-status-code: ${(_a2 = retryOptions.doNotRetry) !== null && _a2 !== void 0 ? _a2 : "octokit default: [400, 401, 403, 404, 422]"})`); return [retryOptions, requestOptions]; } exports2.getRetryOptions = getRetryOptions; @@ -117615,7 +117615,7 @@ var require_get_artifact = __commonJS({ exports2.getArtifactInternal = exports2.getArtifactPublic = void 0; var github_1 = require_github2(); var plugin_retry_1 = require_dist_node12(); - var core30 = __importStar2(require_core()); + var core31 = __importStar2(require_core()); var utils_1 = require_utils9(); var retry_options_1 = require_retry_options(); var plugin_request_log_1 = require_dist_node11(); @@ -117653,7 +117653,7 @@ var require_get_artifact = __commonJS({ let artifact2 = getArtifactResp.data.artifacts[0]; if (getArtifactResp.data.artifacts.length > 1) { artifact2 = getArtifactResp.data.artifacts.sort((a, b) => b.id - a.id)[0]; - core30.debug(`More than one artifact found for a single name, returning newest (id: ${artifact2.id})`); + core31.debug(`More than one artifact found for a single name, returning newest (id: ${artifact2.id})`); } return { artifact: { @@ -117686,7 +117686,7 @@ var require_get_artifact = __commonJS({ let artifact2 = res.artifacts[0]; if (res.artifacts.length > 1) { artifact2 = res.artifacts.sort((a, b) => Number(b.databaseId) - Number(a.databaseId))[0]; - core30.debug(`More than one artifact found for a single name, returning newest (id: ${artifact2.databaseId})`); + core31.debug(`More than one artifact found for a single name, returning newest (id: ${artifact2.databaseId})`); } return { artifact: { @@ -120862,11 +120862,11 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); (0, command_1.issue)("echo", enabled ? "on" : "off"); } exports2.setCommandEcho = setCommandEcho; - function setFailed12(message) { + function setFailed13(message) { process.exitCode = ExitCode.Failure; error3(message); } - exports2.setFailed = setFailed12; + exports2.setFailed = setFailed13; function isDebug5() { return process.env["RUNNER_DEBUG"] === "1"; } @@ -122440,7 +122440,7 @@ var require_requestUtils2 = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.retryHttpClientRequest = exports2.retry = void 0; var utils_1 = require_utils11(); - var core30 = __importStar2(require_core3()); + var core31 = __importStar2(require_core3()); var config_variables_1 = require_config_variables(); function retry2(name, operation, customErrorMessages, maxAttempts) { return __awaiter2(this, void 0, void 0, function* () { @@ -122467,13 +122467,13 @@ var require_requestUtils2 = __commonJS({ errorMessage = error3.message; } if (!isRetryable) { - core30.info(`${name} - Error is not retryable`); + core31.info(`${name} - Error is not retryable`); if (response) { (0, utils_1.displayHttpDiagnostics)(response); } break; } - core30.info(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); + core31.info(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); yield (0, utils_1.sleep)((0, utils_1.getExponentialRetryTimeInMilliseconds)(attempt)); attempt++; } @@ -122557,7 +122557,7 @@ var require_upload_http_client = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.UploadHttpClient = void 0; var fs31 = __importStar2(require("fs")); - var core30 = __importStar2(require_core3()); + var core31 = __importStar2(require_core3()); var tmp = __importStar2(require_tmp_promise()); var stream2 = __importStar2(require("stream")); var utils_1 = require_utils11(); @@ -122622,7 +122622,7 @@ var require_upload_http_client = __commonJS({ return __awaiter2(this, void 0, void 0, function* () { const FILE_CONCURRENCY = (0, config_variables_1.getUploadFileConcurrency)(); const MAX_CHUNK_SIZE = (0, config_variables_1.getUploadChunkSize)(); - core30.debug(`File Concurrency: ${FILE_CONCURRENCY}, and Chunk Size: ${MAX_CHUNK_SIZE}`); + core31.debug(`File Concurrency: ${FILE_CONCURRENCY}, and Chunk Size: ${MAX_CHUNK_SIZE}`); const parameters = []; let continueOnError = true; if (options) { @@ -122659,15 +122659,15 @@ var require_upload_http_client = __commonJS({ } const startTime = perf_hooks_1.performance.now(); const uploadFileResult = yield this.uploadFileAsync(index2, currentFileParameters); - if (core30.isDebug()) { - core30.debug(`File: ${++completedFiles}/${filesToUpload.length}. ${currentFileParameters.file} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish upload`); + if (core31.isDebug()) { + core31.debug(`File: ${++completedFiles}/${filesToUpload.length}. ${currentFileParameters.file} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish upload`); } uploadFileSize += uploadFileResult.successfulUploadSize; totalFileSize += uploadFileResult.totalSize; if (uploadFileResult.isSuccess === false) { failedItemsToReport.push(currentFileParameters.file); if (!continueOnError) { - core30.error(`aborting artifact upload`); + core31.error(`aborting artifact upload`); abortPendingFileUploads = true; } } @@ -122676,7 +122676,7 @@ var require_upload_http_client = __commonJS({ }))); this.statusReporter.stop(); this.uploadHttpManager.disposeAndReplaceAllClients(); - core30.info(`Total size of all the files uploaded is ${uploadFileSize} bytes`); + core31.info(`Total size of all the files uploaded is ${uploadFileSize} bytes`); return { uploadSize: uploadFileSize, totalSize: totalFileSize, @@ -122702,16 +122702,16 @@ var require_upload_http_client = __commonJS({ let uploadFileSize = 0; let isGzip = true; if (!isFIFO && totalFileSize < 65536) { - core30.debug(`${parameters.file} is less than 64k in size. Creating a gzip file in-memory to potentially reduce the upload size`); + core31.debug(`${parameters.file} is less than 64k in size. Creating a gzip file in-memory to potentially reduce the upload size`); const buffer = yield (0, upload_gzip_1.createGZipFileInBuffer)(parameters.file); let openUploadStream; if (totalFileSize < buffer.byteLength) { - core30.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); + core31.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); openUploadStream = () => fs31.createReadStream(parameters.file); isGzip = false; uploadFileSize = totalFileSize; } else { - core30.debug(`A gzip file created for ${parameters.file} helped with reducing the size of the original file. The file will be uploaded using gzip.`); + core31.debug(`A gzip file created for ${parameters.file} helped with reducing the size of the original file. The file will be uploaded using gzip.`); openUploadStream = () => { const passThrough = new stream2.PassThrough(); passThrough.end(buffer); @@ -122723,7 +122723,7 @@ var require_upload_http_client = __commonJS({ if (!result) { isUploadSuccessful = false; failedChunkSizes += uploadFileSize; - core30.warning(`Aborting upload for ${parameters.file} due to failure`); + core31.warning(`Aborting upload for ${parameters.file} due to failure`); } return { isSuccess: isUploadSuccessful, @@ -122732,16 +122732,16 @@ var require_upload_http_client = __commonJS({ }; } else { const tempFile = yield tmp.file(); - core30.debug(`${parameters.file} is greater than 64k in size. Creating a gzip file on-disk ${tempFile.path} to potentially reduce the upload size`); + core31.debug(`${parameters.file} is greater than 64k in size. Creating a gzip file on-disk ${tempFile.path} to potentially reduce the upload size`); uploadFileSize = yield (0, upload_gzip_1.createGZipFileOnDisk)(parameters.file, tempFile.path); let uploadFilePath = tempFile.path; if (!isFIFO && totalFileSize < uploadFileSize) { - core30.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); + core31.debug(`The gzip file created for ${parameters.file} did not help with reducing the size of the file. The original file will be uploaded as-is`); uploadFileSize = totalFileSize; uploadFilePath = parameters.file; isGzip = false; } else { - core30.debug(`The gzip file created for ${parameters.file} is smaller than the original file. The file will be uploaded using gzip.`); + core31.debug(`The gzip file created for ${parameters.file} is smaller than the original file. The file will be uploaded using gzip.`); } let abortFileUpload = false; while (offset < uploadFileSize) { @@ -122761,7 +122761,7 @@ var require_upload_http_client = __commonJS({ if (!result) { isUploadSuccessful = false; failedChunkSizes += chunkSize; - core30.warning(`Aborting upload for ${parameters.file} due to failure`); + core31.warning(`Aborting upload for ${parameters.file} due to failure`); abortFileUpload = true; } else { if (uploadFileSize > 8388608) { @@ -122769,7 +122769,7 @@ var require_upload_http_client = __commonJS({ } } } - core30.debug(`deleting temporary gzip file ${tempFile.path}`); + core31.debug(`deleting temporary gzip file ${tempFile.path}`); yield tempFile.cleanup(); return { isSuccess: isUploadSuccessful, @@ -122808,7 +122808,7 @@ var require_upload_http_client = __commonJS({ if (response) { (0, utils_1.displayHttpDiagnostics)(response); } - core30.info(`Retry limit has been reached for chunk at offset ${start} to ${resourceUrl}`); + core31.info(`Retry limit has been reached for chunk at offset ${start} to ${resourceUrl}`); return true; } return false; @@ -122816,14 +122816,14 @@ var require_upload_http_client = __commonJS({ const backOff = (retryAfterValue) => __awaiter2(this, void 0, void 0, function* () { this.uploadHttpManager.disposeAndReplaceClient(httpClientIndex); if (retryAfterValue) { - core30.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the upload`); + core31.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the upload`); yield (0, utils_1.sleep)(retryAfterValue); } else { const backoffTime = (0, utils_1.getExponentialRetryTimeInMilliseconds)(retryCount); - core30.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the upload at offset ${start}`); + core31.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the upload at offset ${start}`); yield (0, utils_1.sleep)(backoffTime); } - core30.info(`Finished backoff for retry #${retryCount}, continuing with upload`); + core31.info(`Finished backoff for retry #${retryCount}, continuing with upload`); return; }); while (retryCount <= retryLimit) { @@ -122831,7 +122831,7 @@ var require_upload_http_client = __commonJS({ try { response = yield uploadChunkRequest(); } catch (error3) { - core30.info(`An error has been caught http-client index ${httpClientIndex}, retrying the upload`); + core31.info(`An error has been caught http-client index ${httpClientIndex}, retrying the upload`); console.log(error3); if (incrementAndCheckRetryLimit()) { return false; @@ -122843,13 +122843,13 @@ var require_upload_http_client = __commonJS({ if ((0, utils_1.isSuccessStatusCode)(response.message.statusCode)) { return true; } else if ((0, utils_1.isRetryableStatusCode)(response.message.statusCode)) { - core30.info(`A ${response.message.statusCode} status code has been received, will attempt to retry the upload`); + core31.info(`A ${response.message.statusCode} status code has been received, will attempt to retry the upload`); if (incrementAndCheckRetryLimit(response)) { return false; } (0, utils_1.isThrottledStatusCode)(response.message.statusCode) ? yield backOff((0, utils_1.tryGetRetryAfterValueTimeInMilliseconds)(response.message.headers)) : yield backOff(); } else { - core30.error(`Unexpected response. Unable to upload chunk to ${resourceUrl}`); + core31.error(`Unexpected response. Unable to upload chunk to ${resourceUrl}`); (0, utils_1.displayHttpDiagnostics)(response); return false; } @@ -122867,7 +122867,7 @@ var require_upload_http_client = __commonJS({ resourceUrl.searchParams.append("artifactName", artifactName); const parameters = { Size: size }; const data = JSON.stringify(parameters, null, 2); - core30.debug(`URL is ${resourceUrl.toString()}`); + core31.debug(`URL is ${resourceUrl.toString()}`); const client = this.uploadHttpManager.getClient(0); const headers = (0, utils_1.getUploadHeaders)("application/json", false); const customErrorMessages = /* @__PURE__ */ new Map([ @@ -122880,7 +122880,7 @@ var require_upload_http_client = __commonJS({ return client.patch(resourceUrl.toString(), data, headers); }), customErrorMessages); yield response.readBody(); - core30.debug(`Artifact ${artifactName} has been successfully uploaded, total size in bytes: ${size}`); + core31.debug(`Artifact ${artifactName} has been successfully uploaded, total size in bytes: ${size}`); }); } }; @@ -122949,7 +122949,7 @@ var require_download_http_client = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DownloadHttpClient = void 0; var fs31 = __importStar2(require("fs")); - var core30 = __importStar2(require_core3()); + var core31 = __importStar2(require_core3()); var zlib3 = __importStar2(require("zlib")); var utils_1 = require_utils11(); var url_1 = require("url"); @@ -123003,11 +123003,11 @@ var require_download_http_client = __commonJS({ downloadSingleArtifact(downloadItems) { return __awaiter2(this, void 0, void 0, function* () { const DOWNLOAD_CONCURRENCY = (0, config_variables_1.getDownloadFileConcurrency)(); - core30.debug(`Download file concurrency is set to ${DOWNLOAD_CONCURRENCY}`); + core31.debug(`Download file concurrency is set to ${DOWNLOAD_CONCURRENCY}`); const parallelDownloads = [...new Array(DOWNLOAD_CONCURRENCY).keys()]; let currentFile = 0; let downloadedFiles = 0; - core30.info(`Total number of files that will be downloaded: ${downloadItems.length}`); + core31.info(`Total number of files that will be downloaded: ${downloadItems.length}`); this.statusReporter.setTotalNumberOfFilesToProcess(downloadItems.length); this.statusReporter.start(); yield Promise.all(parallelDownloads.map((index2) => __awaiter2(this, void 0, void 0, function* () { @@ -123016,8 +123016,8 @@ var require_download_http_client = __commonJS({ currentFile += 1; const startTime = perf_hooks_1.performance.now(); yield this.downloadIndividualFile(index2, currentFileToDownload.sourceLocation, currentFileToDownload.targetPath); - if (core30.isDebug()) { - core30.debug(`File: ${++downloadedFiles}/${downloadItems.length}. ${currentFileToDownload.targetPath} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish downloading`); + if (core31.isDebug()) { + core31.debug(`File: ${++downloadedFiles}/${downloadItems.length}. ${currentFileToDownload.targetPath} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish downloading`); } this.statusReporter.incrementProcessedCount(); } @@ -123055,19 +123055,19 @@ var require_download_http_client = __commonJS({ } else { this.downloadHttpManager.disposeAndReplaceClient(httpClientIndex); if (retryAfterValue) { - core30.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the download`); + core31.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the download`); yield (0, utils_1.sleep)(retryAfterValue); } else { const backoffTime = (0, utils_1.getExponentialRetryTimeInMilliseconds)(retryCount); - core30.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the download`); + core31.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the download`); yield (0, utils_1.sleep)(backoffTime); } - core30.info(`Finished backoff for retry #${retryCount}, continuing with download`); + core31.info(`Finished backoff for retry #${retryCount}, continuing with download`); } }); const isAllBytesReceived = (expected, received) => { if (!expected || !received || process.env["ACTIONS_ARTIFACT_SKIP_DOWNLOAD_VALIDATION"]) { - core30.info("Skipping download validation."); + core31.info("Skipping download validation."); return true; } return parseInt(expected) === received; @@ -123088,7 +123088,7 @@ var require_download_http_client = __commonJS({ try { response = yield makeDownloadRequest(); } catch (error3) { - core30.info("An error occurred while attempting to download a file"); + core31.info("An error occurred while attempting to download a file"); console.log(error3); yield backOff(); continue; @@ -123108,7 +123108,7 @@ var require_download_http_client = __commonJS({ } } if (forceRetry || (0, utils_1.isRetryableStatusCode)(response.message.statusCode)) { - core30.info(`A ${response.message.statusCode} response code has been received while attempting to download an artifact`); + core31.info(`A ${response.message.statusCode} response code has been received while attempting to download an artifact`); resetDestinationStream(downloadPath); (0, utils_1.isThrottledStatusCode)(response.message.statusCode) ? yield backOff((0, utils_1.tryGetRetryAfterValueTimeInMilliseconds)(response.message.headers)) : yield backOff(); } else { @@ -123130,29 +123130,29 @@ var require_download_http_client = __commonJS({ if (isGzip) { const gunzip = zlib3.createGunzip(); response.message.on("error", (error3) => { - core30.info(`An error occurred while attempting to read the response stream`); + core31.info(`An error occurred while attempting to read the response stream`); gunzip.close(); destinationStream.close(); reject(error3); }).pipe(gunzip).on("error", (error3) => { - core30.info(`An error occurred while attempting to decompress the response stream`); + core31.info(`An error occurred while attempting to decompress the response stream`); destinationStream.close(); reject(error3); }).pipe(destinationStream).on("close", () => { resolve14(); }).on("error", (error3) => { - core30.info(`An error occurred while writing a downloaded file to ${destinationStream.path}`); + core31.info(`An error occurred while writing a downloaded file to ${destinationStream.path}`); reject(error3); }); } else { response.message.on("error", (error3) => { - core30.info(`An error occurred while attempting to read the response stream`); + core31.info(`An error occurred while attempting to read the response stream`); destinationStream.close(); reject(error3); }).pipe(destinationStream).on("close", () => { resolve14(); }).on("error", (error3) => { - core30.info(`An error occurred while writing a downloaded file to ${destinationStream.path}`); + core31.info(`An error occurred while writing a downloaded file to ${destinationStream.path}`); reject(error3); }); } @@ -123291,7 +123291,7 @@ var require_artifact_client = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DefaultArtifactClient = void 0; - var core30 = __importStar2(require_core3()); + var core31 = __importStar2(require_core3()); var upload_specification_1 = require_upload_specification(); var upload_http_client_1 = require_upload_http_client(); var utils_1 = require_utils11(); @@ -123312,7 +123312,7 @@ var require_artifact_client = __commonJS({ */ uploadArtifact(name, files, rootDirectory, options) { return __awaiter2(this, void 0, void 0, function* () { - core30.info(`Starting artifact upload + core31.info(`Starting artifact upload For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging`); (0, path_and_artifact_name_validation_1.checkArtifactName)(name); const uploadSpecification = (0, upload_specification_1.getUploadSpecification)(name, rootDirectory, files); @@ -123324,24 +123324,24 @@ For more detailed logs during the artifact upload process, enable step-debugging }; const uploadHttpClient = new upload_http_client_1.UploadHttpClient(); if (uploadSpecification.length === 0) { - core30.warning(`No files found that can be uploaded`); + core31.warning(`No files found that can be uploaded`); } else { const response = yield uploadHttpClient.createArtifactInFileContainer(name, options); if (!response.fileContainerResourceUrl) { - core30.debug(response.toString()); + core31.debug(response.toString()); throw new Error("No URL provided by the Artifact Service to upload an artifact to"); } - core30.debug(`Upload Resource URL: ${response.fileContainerResourceUrl}`); - core30.info(`Container for artifact "${name}" successfully created. Starting upload of file(s)`); + core31.debug(`Upload Resource URL: ${response.fileContainerResourceUrl}`); + core31.info(`Container for artifact "${name}" successfully created. Starting upload of file(s)`); const uploadResult = yield uploadHttpClient.uploadArtifactToFileContainer(response.fileContainerResourceUrl, uploadSpecification, options); - core30.info(`File upload process has finished. Finalizing the artifact upload`); + core31.info(`File upload process has finished. Finalizing the artifact upload`); yield uploadHttpClient.patchArtifactSize(uploadResult.totalSize, name); if (uploadResult.failedItems.length > 0) { - core30.info(`Upload finished. There were ${uploadResult.failedItems.length} items that failed to upload`); + core31.info(`Upload finished. There were ${uploadResult.failedItems.length} items that failed to upload`); } else { - core30.info(`Artifact has been finalized. All files have been successfully uploaded!`); + core31.info(`Artifact has been finalized. All files have been successfully uploaded!`); } - core30.info(` + core31.info(` The raw size of all the files that were specified for upload is ${uploadResult.totalSize} bytes The size of all the files that were uploaded is ${uploadResult.uploadSize} bytes. This takes into account any gzip compression used to reduce the upload size, time and storage @@ -123375,10 +123375,10 @@ Note: The size of downloaded zips can differ significantly from the reported siz path29 = (0, path_1.resolve)(path29); const downloadSpecification = (0, download_specification_1.getDownloadSpecification)(name, items.value, path29, (options === null || options === void 0 ? void 0 : options.createArtifactFolder) || false); if (downloadSpecification.filesToDownload.length === 0) { - core30.info(`No downloadable files were found for the artifact: ${artifactToDownload.name}`); + core31.info(`No downloadable files were found for the artifact: ${artifactToDownload.name}`); } else { yield (0, utils_1.createDirectoriesForArtifact)(downloadSpecification.directoryStructure); - core30.info("Directory structure has been set up for the artifact"); + core31.info("Directory structure has been set up for the artifact"); yield (0, utils_1.createEmptyFilesForArtifact)(downloadSpecification.emptyFilesToCreate); yield downloadHttpClient.downloadSingleArtifact(downloadSpecification.filesToDownload); } @@ -123394,7 +123394,7 @@ Note: The size of downloaded zips can differ significantly from the reported siz const response = []; const artifacts = yield downloadHttpClient.listArtifacts(); if (artifacts.count === 0) { - core30.info("Unable to find any artifacts for the associated workflow"); + core31.info("Unable to find any artifacts for the associated workflow"); return response; } if (!path29) { @@ -123406,11 +123406,11 @@ Note: The size of downloaded zips can differ significantly from the reported siz while (downloadedArtifacts < artifacts.count) { const currentArtifactToDownload = artifacts.value[downloadedArtifacts]; downloadedArtifacts += 1; - core30.info(`starting download of artifact ${currentArtifactToDownload.name} : ${downloadedArtifacts}/${artifacts.count}`); + core31.info(`starting download of artifact ${currentArtifactToDownload.name} : ${downloadedArtifacts}/${artifacts.count}`); const items = yield downloadHttpClient.getContainerItems(currentArtifactToDownload.name, currentArtifactToDownload.fileContainerResourceUrl); const downloadSpecification = (0, download_specification_1.getDownloadSpecification)(currentArtifactToDownload.name, items.value, path29, true); if (downloadSpecification.filesToDownload.length === 0) { - core30.info(`No downloadable files were found for any artifact ${currentArtifactToDownload.name}`); + core31.info(`No downloadable files were found for any artifact ${currentArtifactToDownload.name}`); } else { yield (0, utils_1.createDirectoriesForArtifact)(downloadSpecification.directoryStructure); yield (0, utils_1.createEmptyFilesForArtifact)(downloadSpecification.emptyFilesToCreate); @@ -144583,6 +144583,12 @@ function initializeEnvironment(version) { core2.exportVariable("CODEQL_ACTION_FEATURE_WILL_UPLOAD" /* FEATURE_WILL_UPLOAD */, "true"); core2.exportVariable("CODEQL_ACTION_VERSION" /* VERSION */, version); } +function getEnv(env = process.env) { + return { + getRequired: (name) => getRequiredEnvVar(env, name), + getOptional: (name) => getOptionalEnvVarFrom(env, name) + }; +} function getRequiredEnvVar(env, paramName) { const value = env[paramName]; if (value === void 0 || value.length === 0) { @@ -162142,7 +162148,30 @@ async function runWrapper9() { } // src/upload-sarif-action.ts +var core29 = __toESM(require_core()); + +// src/action-common.ts var core28 = __toESM(require_core()); +async function runInActions(action) { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv + }); + } catch (error3) { + core28.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); + } +} + +// src/upload-sarif-action.ts async function sendSuccessStatusReport2(startedAt, uploadStats, logger) { const statusReportBase = await createStatusReportBase( "upload-sarif" /* UploadSarif */, @@ -162160,8 +162189,7 @@ async function sendSuccessStatusReport2(startedAt, uploadStats, logger) { await sendStatusReport(statusReport); } } -async function run8(startedAt) { - const logger = getActionsLogger(); +async function run8({ startedAt, logger }) { try { initializeEnvironment(getActionVersion()); const gitHubVersion = await getGitHubVersion(); @@ -162203,11 +162231,11 @@ async function run8(startedAt) { } const codeScanningResult = uploadResults["code-scanning" /* CodeScanning */]; if (codeScanningResult !== void 0) { - core28.setOutput("sarif-id", codeScanningResult.sarifID); + core29.setOutput("sarif-id", codeScanningResult.sarifID); } - core28.setOutput("sarif-ids", JSON.stringify(uploadResults)); + core29.setOutput("sarif-ids", JSON.stringify(uploadResults)); if (shouldSkipSarifUpload()) { - core28.debug( + core29.debug( "SARIF upload disabled by an environment variable. Waiting for processing is disabled." ); } else if (getRequiredInput("wait-for-processing") === "true") { @@ -162227,7 +162255,7 @@ async function run8(startedAt) { } catch (unwrappedError) { const error3 = isThirdPartyAnalysis("upload-sarif" /* UploadSarif */) && unwrappedError instanceof InvalidSarifUploadError ? new ConfigurationError(unwrappedError.message) : wrapError(unwrappedError); const message = error3.message; - core28.setFailed(message); + core29.setFailed(message); const errorStatusReportBase = await createStatusReportBase( "upload-sarif" /* UploadSarif */, getActionsStatus(error3), @@ -162244,26 +162272,16 @@ async function run8(startedAt) { return; } } +var uploadSarif = { + name: "upload-sarif" /* UploadSarif */, + run: run8 +}; async function runWrapper10() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run8(startedAt); - } catch (error3) { - core28.setFailed( - `codeql/upload-sarif action failed: ${getErrorMessage(error3)}` - ); - await sendUnhandledErrorStatusReport( - "upload-sarif" /* UploadSarif */, - startedAt, - error3, - logger - ); - } + await runInActions(uploadSarif); } // src/upload-sarif-action-post.ts -var core29 = __toESM(require_core()); +var core30 = __toESM(require_core()); async function runWrapper11() { try { restoreInputs(); @@ -162272,7 +162290,7 @@ async function runWrapper11() { checkGitHubVersionInRange(gitHubVersion, logger); if (process.env["CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */] !== "true") { if (gitHubVersion.type === void 0) { - core29.warning( + core30.warning( `Did not upload debug artifacts because cannot determine the GitHub variant running.` ); return; @@ -162289,7 +162307,7 @@ async function runWrapper11() { ); } } catch (error3) { - core29.setFailed( + core30.setFailed( `upload-sarif post-action step failed: ${getErrorMessage(error3)}` ); } diff --git a/src/upload-sarif-action.ts b/src/upload-sarif-action.ts index bd190f0318..214f3bf980 100644 --- a/src/upload-sarif-action.ts +++ b/src/upload-sarif-action.ts @@ -1,17 +1,17 @@ import * as core from "@actions/core"; +import { Action, ActionState, runInActions } from "./action-common"; import * as actionsUtil from "./actions-util"; import { getActionVersion, getTemporaryDirectory } from "./actions-util"; import * as analyses from "./analyses"; import { getGitHubVersion } from "./api-client"; import { initFeatures } from "./feature-flags"; -import { Logger, getActionsLogger } from "./logging"; +import { Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; import { InvalidSarifUploadError } from "./sarif"; import { createStatusReportBase, sendStatusReport, - sendUnhandledErrorStatusReport, StatusReportBase, getActionsStatus, ActionName, @@ -23,7 +23,6 @@ import { ConfigurationError, checkActionVersion, checkDiskUsage, - getErrorMessage, initializeEnvironment, shouldSkipSarifUpload, wrapError, @@ -55,12 +54,9 @@ async function sendSuccessStatusReport( } } -async function run(startedAt: Date) { +async function run({ startedAt, logger }: ActionState<["Logger"]>) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. - - const logger = getActionsLogger(); - try { initializeEnvironment(getActionVersion()); @@ -165,20 +161,12 @@ async function run(startedAt: Date) { } } +/** Defines the `upload-sarif` Action. */ +const uploadSarif: Action = { + name: ActionName.UploadSarif, + run, +}; + export async function runWrapper() { - const startedAt = new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error) { - core.setFailed( - `codeql/upload-sarif action failed: ${getErrorMessage(error)}`, - ); - await sendUnhandledErrorStatusReport( - ActionName.UploadSarif, - startedAt, - error, - logger, - ); - } + await runInActions(uploadSarif); } From 6ab762cada80c7344235d9c3ce058ad1b6eee3c2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:02:03 +0100 Subject: [PATCH 08/14] Use the common entry point for `setup-codeql` --- lib/entry-points.js | 116 ++++++++++++++++++------------------- src/setup-codeql-action.ts | 32 +++++----- 2 files changed, 68 insertions(+), 80 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7a80e3741b..cd151ff17f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -161047,7 +161047,30 @@ async function runWrapper6() { } // src/setup-codeql-action.ts +var core24 = __toESM(require_core()); + +// src/action-common.ts var core23 = __toESM(require_core()); +async function runInActions(action) { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv + }); + } catch (error3) { + core23.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); + } +} + +// src/setup-codeql-action.ts async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, @@ -161078,8 +161101,10 @@ async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, } await sendStatusReport({ ...initStatusReport, ...initToolsDownloadFields }); } -async function run6(startedAt) { - const logger = getActionsLogger(); +async function run6({ + startedAt, + logger +}) { let codeql; let toolsDownloadStatusReport; let toolsFeatureFlagsValid; @@ -161105,7 +161130,7 @@ async function run6(startedAt) { ); const jobRunUuid = v4_default(); logger.info(`Job run UUID is ${jobRunUuid}.`); - core23.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + core24.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", @@ -161138,12 +161163,12 @@ async function run6(startedAt) { toolsDownloadStatusReport = initCodeQLResult.toolsDownloadStatusReport; toolsVersion = initCodeQLResult.toolsVersion; toolsSource = initCodeQLResult.toolsSource; - core23.setOutput("codeql-path", codeql.getPath()); - core23.setOutput("codeql-version", (await codeql.getVersion()).version); - core23.exportVariable("CODEQL_ACTION_SETUP_CODEQL_HAS_RUN" /* SETUP_CODEQL_ACTION_HAS_RUN */, "true"); + core24.setOutput("codeql-path", codeql.getPath()); + core24.setOutput("codeql-version", (await codeql.getVersion()).version); + core24.exportVariable("CODEQL_ACTION_SETUP_CODEQL_HAS_RUN" /* SETUP_CODEQL_ACTION_HAS_RUN */, "true"); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); - core23.setFailed(error3.message); + core24.setFailed(error3.message); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, error3 instanceof ConfigurationError ? "user-error" : "failure", @@ -161168,31 +161193,23 @@ async function run6(startedAt) { logger ); } +var setupCodeQL2 = { + name: "setup-codeql" /* SetupCodeQL */, + run: run6 +}; async function runWrapper7() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run6(startedAt); - } catch (error3) { - core23.setFailed(`setup-codeql action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport( - "setup-codeql" /* SetupCodeQL */, - startedAt, - error3, - logger - ); - } + await runInActions(setupCodeQL2); await checkForTimeout(); } // src/start-proxy-action.ts var import_child_process2 = require("child_process"); var path28 = __toESM(require("path")); -var core26 = __toESM(require_core()); +var core27 = __toESM(require_core()); // src/start-proxy.ts var path26 = __toESM(require("path")); -var core25 = __toESM(require_core()); +var core26 = __toESM(require_core()); var toolcache4 = __toESM(require_tool_cache()); // src/start-proxy/types.ts @@ -161332,7 +161349,7 @@ function getAddressString(address) { } // src/start-proxy/validation.ts -var core24 = __toESM(require_core()); +var core25 = __toESM(require_core()); function cloneCredential(schema, obj) { const result = {}; for (const key of Object.keys(schema)) { @@ -161351,14 +161368,14 @@ function getAuthConfig(config) { } if (isToken(config)) { if (isDefined2(config.token)) { - core24.setSecret(config.token); + core25.setSecret(config.token); } return cloneCredential(tokenSchema, config); } else { let username = void 0; let password = void 0; if ("password" in config && isString(config.password)) { - core24.setSecret(config.password); + core25.setSecret(config.password); password = config.password; } if ("username" in config && isString(config.username)) { @@ -161414,7 +161431,7 @@ function getSafeErrorMessage(error3) { } async function sendFailedStatusReport(logger, startedAt, language, unwrappedError) { const error3 = wrapError(unwrappedError); - core25.setFailed(`start-proxy action failed: ${error3.message}`); + core26.setFailed(`start-proxy action failed: ${error3.message}`); const statusReportMessage = getSafeErrorMessage(error3); const errorStatusReportBase = await createStatusReportBase( "start-proxy" /* StartProxy */, @@ -161983,7 +162000,7 @@ async function run7(startedAt) { persistInputs(); const tempDir = getTemporaryDirectory(); const proxyLogFilePath = path28.resolve(tempDir, "proxy.log"); - core26.saveState("proxy-log-file", proxyLogFilePath); + core27.saveState("proxy-log-file", proxyLogFilePath); const repositoryNwo = getRepositoryNwo(); const gitHubVersion = await getGitHubVersion(); features = initFeatures( @@ -162008,7 +162025,7 @@ async function run7(startedAt) { `Credentials loaded for the following registries: ${credentials.map((c) => credentialToStr(c)).join("\n")}` ); - if (core26.isDebug() || isInTestMode()) { + if (core27.isDebug() || isInTestMode()) { try { await checkProxyEnvironment(logger, language); } catch (err) { @@ -162048,7 +162065,7 @@ async function runWrapper8() { try { await run7(startedAt); } catch (error3) { - core26.setFailed(`start-proxy action failed: ${getErrorMessage(error3)}`); + core27.setFailed(`start-proxy action failed: ${getErrorMessage(error3)}`); await sendUnhandledErrorStatusReport( "start-proxy" /* StartProxy */, startedAt, @@ -162074,7 +162091,7 @@ async function startProxy(binPath, config, logFilePath, logger) { ); subprocess.unref(); if (subprocess.pid) { - core26.saveState("proxy-process-pid", `${subprocess.pid}`); + core27.saveState("proxy-process-pid", `${subprocess.pid}`); } subprocess.on("error", (error3) => { subprocessError = error3; @@ -162093,25 +162110,25 @@ async function startProxy(binPath, config, logFilePath, logger) { throw subprocessError; } logger.info(`Proxy started on ${host}:${port}`); - core26.setOutput("proxy_host", host); - core26.setOutput("proxy_port", port.toString()); - core26.setOutput("proxy_ca_certificate", config.ca.cert); + core27.setOutput("proxy_host", host); + core27.setOutput("proxy_port", port.toString()); + core27.setOutput("proxy_ca_certificate", config.ca.cert); const registry_urls = config.all_credentials.filter((credential) => credential.url !== void 0).map((credential) => ({ type: credential.type, url: credential.url, "replaces-base": credential["replaces-base"] })); - core26.setOutput("proxy_urls", JSON.stringify(registry_urls)); + core27.setOutput("proxy_urls", JSON.stringify(registry_urls)); return { host, port, cert: config.ca.cert, registries: registry_urls }; } // src/start-proxy-action-post.ts -var core27 = __toESM(require_core()); +var core28 = __toESM(require_core()); async function runWrapper9() { const logger = getActionsLogger(); try { restoreInputs(); - const pid = core27.getState("proxy-process-pid"); + const pid = core28.getState("proxy-process-pid"); if (pid) { process.kill(Number(pid)); } @@ -162119,8 +162136,8 @@ async function runWrapper9() { getTemporaryDirectory(), logger ); - if (config?.debugMode || core27.isDebug()) { - const logFilePath = core27.getState("proxy-log-file"); + if (config?.debugMode || core28.isDebug()) { + const logFilePath = core28.getState("proxy-log-file"); logger.info( "Debug mode is on. Uploading proxy log as Actions debugging artifact..." ); @@ -162149,29 +162166,6 @@ async function runWrapper9() { // src/upload-sarif-action.ts var core29 = __toESM(require_core()); - -// src/action-common.ts -var core28 = __toESM(require_core()); -async function runInActions(action) { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - const env = getEnv(); - const actionsEnv = getActionsEnv(); - try { - await action.run({ - name: action.name, - startedAt, - logger, - env, - actions: actionsEnv - }); - } catch (error3) { - core28.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); - } -} - -// src/upload-sarif-action.ts async function sendSuccessStatusReport2(startedAt, uploadStats, logger) { const statusReportBase = await createStatusReportBase( "upload-sarif" /* UploadSarif */, diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index d3e0e7dbcc..a6b5f83f5e 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -1,6 +1,7 @@ import * as core from "@actions/core"; import { v4 as uuidV4 } from "uuid"; +import { Action, ActionState, runInActions } from "./action-common"; import { getActionVersion, getOptionalInput, @@ -14,7 +15,7 @@ import { getRawLanguagesNoAutodetect } from "./config-utils"; import { EnvVar } from "./environment"; import { initFeatures } from "./feature-flags"; import { initCodeQL } from "./init"; -import { getActionsLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; import { ToolsSource } from "./setup-codeql"; import { @@ -24,7 +25,6 @@ import { createStatusReportBase, getActionsStatus, sendStatusReport, - sendUnhandledErrorStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; import { @@ -36,7 +36,6 @@ import { ConfigurationError, wrapError, checkActionVersion, - getErrorMessage, } from "./util"; /** @@ -88,12 +87,13 @@ async function sendCompletedStatusReport( } /** The main behaviour of this action. */ -async function run(startedAt: Date): Promise { +async function run({ + startedAt, + logger, +}: ActionState<["Logger"]>): Promise { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. - const logger = getActionsLogger(); - let codeql: CodeQL; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; @@ -195,20 +195,14 @@ async function run(startedAt: Date): Promise { ); } +/** Defines the `setup-codeql` Action. */ +const setupCodeQL: Action = { + name: ActionName.SetupCodeQL, + run, +}; + /** Run the action and catch any unhandled errors. */ export async function runWrapper(): Promise { - const startedAt = new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error) { - core.setFailed(`setup-codeql action failed: ${getErrorMessage(error)}`); - await sendUnhandledErrorStatusReport( - ActionName.SetupCodeQL, - startedAt, - error, - logger, - ); - } + await runInActions(setupCodeQL); await checkForTimeout(); } From 6136b93088d3e80d3e692839c6365aaf19de13f8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:30:46 +0100 Subject: [PATCH 09/14] Use the common entry point for `init` --- src/init-action.ts | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/init-action.ts b/src/init-action.ts index ec711cdf0b..114344b667 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -7,9 +7,9 @@ import * as io from "@actions/io"; import * as semver from "semver"; import { v4 as uuidV4 } from "uuid"; +import { Action, ActionState, runInActions } from "./action-common"; import { FileCmdNotFoundError, - getActionsEnv, getActionVersion, getFileType, getOptionalInput, @@ -56,7 +56,7 @@ import { runDatabaseInitCluster, } from "./init"; import { JavaEnvVars, BuiltInLanguage } from "./languages"; -import { getActionsLogger, Logger, withGroupAsync } from "./logging"; +import { Logger, withGroupAsync } from "./logging"; import { downloadOverlayBaseDatabaseFromCache, OverlayBaseDatabaseDownloadStats, @@ -73,7 +73,6 @@ import { createStatusReportBase, getActionsStatus, sendStatusReport, - sendUnhandledErrorStatusReport, } from "./status-report"; import { ZstdAvailability } from "./tar"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -204,12 +203,12 @@ async function sendCompletedStatusReport( } } -async function run(startedAt: Date) { +async function run(actionState: ActionState<["Logger", "Actions"]>) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. - const logger = getActionsLogger(); - const actionsEnv = getActionsEnv(); + const startedAt = actionState.startedAt; + const logger = actionState.logger; let apiDetails: GitHubApiCombinedDetails; let config: configUtils.Config | undefined; @@ -854,19 +853,13 @@ async function recordZstdAvailability( ); } +/** Defines the `init` Action. */ +const init: Action = { + name: ActionName.Init, + run, +}; + export async function runWrapper() { - const startedAt = new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error) { - core.setFailed(`init action failed: ${getErrorMessage(error)}`); - await sendUnhandledErrorStatusReport( - ActionName.Init, - startedAt, - error, - logger, - ); - } + await runInActions(init); await checkForTimeout(); } From a9ceac150d702d1a9394aa083efa5736f11b6986 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:31:25 +0100 Subject: [PATCH 10/14] Accept `ActionState` in `getConfigFileInput` --- lib/entry-points.js | 418 ++++++++++++++++++++-------------------- src/config/file.test.ts | 105 +++++----- src/config/file.ts | 20 +- src/init-action.ts | 9 +- 4 files changed, 266 insertions(+), 286 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index cd151ff17f..696b557764 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -12012,13 +12012,13 @@ var require_headers = __commonJS({ var HeadersList = class _HeadersList { /** @type {[string, string][]|null} */ cookies = null; - constructor(init) { - if (init instanceof _HeadersList) { - this[kHeadersMap] = new Map(init[kHeadersMap]); - this[kHeadersSortedMap] = init[kHeadersSortedMap]; - this.cookies = init.cookies === null ? null : [...init.cookies]; + constructor(init2) { + if (init2 instanceof _HeadersList) { + this[kHeadersMap] = new Map(init2[kHeadersMap]); + this[kHeadersSortedMap] = init2[kHeadersSortedMap]; + this.cookies = init2.cookies === null ? null : [...init2.cookies]; } else { - this[kHeadersMap] = new Map(init); + this[kHeadersMap] = new Map(init2); this[kHeadersSortedMap] = null; } } @@ -12177,16 +12177,16 @@ var require_headers = __commonJS({ var Headers = class _Headers { #guard; #headersList; - constructor(init = void 0) { + constructor(init2 = void 0) { webidl.util.markAsUncloneable(this); - if (init === kConstruct) { + if (init2 === kConstruct) { return; } this.#headersList = new HeadersList(); this.#guard = "none"; - if (init !== void 0) { - init = webidl.converters.HeadersInit(init, "Headers contructor", "init"); - fill(this, init); + if (init2 !== void 0) { + init2 = webidl.converters.HeadersInit(init2, "Headers contructor", "init"); + fill(this, init2); } } // https://fetch.spec.whatwg.org/#dom-headers-append @@ -12417,17 +12417,17 @@ var require_response = __commonJS({ return responseObject; } // https://fetch.spec.whatwg.org/#dom-response-json - static json(data, init = {}) { + static json(data, init2 = {}) { webidl.argumentLengthCheck(arguments, 1, "Response.json"); - if (init !== null) { - init = webidl.converters.ResponseInit(init); + if (init2 !== null) { + init2 = webidl.converters.ResponseInit(init2); } const bytes = textEncoder.encode( serializeJavascriptValueToJSONString(data) ); const body = extractBody(bytes); const responseObject = fromInnerResponse(makeResponse({}), "response"); - initializeResponse(responseObject, init, { body: body[0], type: "application/json" }); + initializeResponse(responseObject, init2, { body: body[0], type: "application/json" }); return responseObject; } // Creates a redirect Response that redirects to url with status status. @@ -12451,7 +12451,7 @@ var require_response = __commonJS({ return responseObject; } // https://fetch.spec.whatwg.org/#dom-response - constructor(body = null, init = {}) { + constructor(body = null, init2 = {}) { webidl.util.markAsUncloneable(this); if (body === kConstruct) { return; @@ -12459,7 +12459,7 @@ var require_response = __commonJS({ if (body !== null) { body = webidl.converters.BodyInit(body); } - init = webidl.converters.ResponseInit(init); + init2 = webidl.converters.ResponseInit(init2); this[kState] = makeResponse({}); this[kHeaders] = new Headers(kConstruct); setHeadersGuard(this[kHeaders], "response"); @@ -12469,7 +12469,7 @@ var require_response = __commonJS({ const [extractedBody, type] = extractBody(body); bodyWithType = { body: extractedBody, type }; } - initializeResponse(this, init, bodyWithType); + initializeResponse(this, init2, bodyWithType); } // Returns response’s type, e.g., "cors". get type() { @@ -12588,7 +12588,7 @@ var require_response = __commonJS({ } return newResponse; } - function makeResponse(init) { + function makeResponse(init2) { return { aborted: false, rangeRequested: false, @@ -12599,9 +12599,9 @@ var require_response = __commonJS({ timingInfo: null, cacheState: "", statusText: "", - ...init, - headersList: init?.headersList ? new HeadersList(init?.headersList) : new HeadersList(), - urlList: init?.urlList ? [...init.urlList] : [] + ...init2, + headersList: init2?.headersList ? new HeadersList(init2?.headersList) : new HeadersList(), + urlList: init2?.urlList ? [...init2.urlList] : [] }; } function makeNetworkError(reason) { @@ -12671,23 +12671,23 @@ var require_response = __commonJS({ assert(isCancelled(fetchParams)); return isAborted(fetchParams) ? makeNetworkError(Object.assign(new DOMException("The operation was aborted.", "AbortError"), { cause: err })) : makeNetworkError(Object.assign(new DOMException("Request was cancelled."), { cause: err })); } - function initializeResponse(response, init, body) { - if (init.status !== null && (init.status < 200 || init.status > 599)) { + function initializeResponse(response, init2, body) { + if (init2.status !== null && (init2.status < 200 || init2.status > 599)) { throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.'); } - if ("statusText" in init && init.statusText != null) { - if (!isValidReasonPhrase(String(init.statusText))) { + if ("statusText" in init2 && init2.statusText != null) { + if (!isValidReasonPhrase(String(init2.statusText))) { throw new TypeError("Invalid statusText"); } } - if ("status" in init && init.status != null) { - response[kState].status = init.status; + if ("status" in init2 && init2.status != null) { + response[kState].status = init2.status; } - if ("statusText" in init && init.statusText != null) { - response[kState].statusText = init.statusText; + if ("statusText" in init2 && init2.statusText != null) { + response[kState].statusText = init2.statusText; } - if ("headers" in init && init.headers != null) { - fill(response[kHeaders], init.headers); + if ("headers" in init2 && init2.headers != null) { + fill(response[kHeaders], init2.headers); } if (body) { if (nullBodyStatus.includes(response.status)) { @@ -12883,7 +12883,7 @@ var require_request2 = __commonJS({ var patchMethodWarning = false; var Request = class _Request { // https://fetch.spec.whatwg.org/#dom-request - constructor(input, init = {}) { + constructor(input, init2 = {}) { webidl.util.markAsUncloneable(this); if (input === kConstruct) { return; @@ -12891,13 +12891,13 @@ var require_request2 = __commonJS({ const prefix = "Request constructor"; webidl.argumentLengthCheck(arguments, 1, prefix); input = webidl.converters.RequestInfo(input, prefix, "input"); - init = webidl.converters.RequestInit(init, prefix, "init"); + init2 = webidl.converters.RequestInit(init2, prefix, "init"); let request3 = null; let fallbackMode = null; const baseUrl = environmentSettingsObject.settingsObject.baseUrl; let signal = null; if (typeof input === "string") { - this[kDispatcher] = init.dispatcher; + this[kDispatcher] = init2.dispatcher; let parsedURL; try { parsedURL = new URL(input, baseUrl); @@ -12912,7 +12912,7 @@ var require_request2 = __commonJS({ request3 = makeRequest({ urlList: [parsedURL] }); fallbackMode = "cors"; } else { - this[kDispatcher] = init.dispatcher || input[kDispatcher]; + this[kDispatcher] = init2.dispatcher || input[kDispatcher]; assert(input instanceof _Request); request3 = input[kState]; signal = input[kSignal]; @@ -12922,10 +12922,10 @@ var require_request2 = __commonJS({ if (request3.window?.constructor?.name === "EnvironmentSettingsObject" && sameOrigin(request3.window, origin)) { window2 = request3.window; } - if (init.window != null) { + if (init2.window != null) { throw new TypeError(`'window' option '${window2}' must be null`); } - if ("window" in init) { + if ("window" in init2) { window2 = "no-window"; } request3 = makeRequest({ @@ -12971,7 +12971,7 @@ var require_request2 = __commonJS({ // URL list A clone of request’s URL list. urlList: [...request3.urlList] }); - const initHasKey = Object.keys(init).length !== 0; + const initHasKey = Object.keys(init2).length !== 0; if (initHasKey) { if (request3.mode === "navigate") { request3.mode = "same-origin"; @@ -12984,8 +12984,8 @@ var require_request2 = __commonJS({ request3.url = request3.urlList[request3.urlList.length - 1]; request3.urlList = [request3.url]; } - if (init.referrer !== void 0) { - const referrer = init.referrer; + if (init2.referrer !== void 0) { + const referrer = init2.referrer; if (referrer === "") { request3.referrer = "no-referrer"; } else { @@ -13002,12 +13002,12 @@ var require_request2 = __commonJS({ } } } - if (init.referrerPolicy !== void 0) { - request3.referrerPolicy = init.referrerPolicy; + if (init2.referrerPolicy !== void 0) { + request3.referrerPolicy = init2.referrerPolicy; } let mode; - if (init.mode !== void 0) { - mode = init.mode; + if (init2.mode !== void 0) { + mode = init2.mode; } else { mode = fallbackMode; } @@ -13020,28 +13020,28 @@ var require_request2 = __commonJS({ if (mode != null) { request3.mode = mode; } - if (init.credentials !== void 0) { - request3.credentials = init.credentials; + if (init2.credentials !== void 0) { + request3.credentials = init2.credentials; } - if (init.cache !== void 0) { - request3.cache = init.cache; + if (init2.cache !== void 0) { + request3.cache = init2.cache; } if (request3.cache === "only-if-cached" && request3.mode !== "same-origin") { throw new TypeError( "'only-if-cached' can be set only with 'same-origin' mode" ); } - if (init.redirect !== void 0) { - request3.redirect = init.redirect; + if (init2.redirect !== void 0) { + request3.redirect = init2.redirect; } - if (init.integrity != null) { - request3.integrity = String(init.integrity); + if (init2.integrity != null) { + request3.integrity = String(init2.integrity); } - if (init.keepalive !== void 0) { - request3.keepalive = Boolean(init.keepalive); + if (init2.keepalive !== void 0) { + request3.keepalive = Boolean(init2.keepalive); } - if (init.method !== void 0) { - let method = init.method; + if (init2.method !== void 0) { + let method = init2.method; const mayBeNormalized = normalizedMethodRecords[method]; if (mayBeNormalized !== void 0) { request3.method = mayBeNormalized; @@ -13063,8 +13063,8 @@ var require_request2 = __commonJS({ patchMethodWarning = true; } } - if (init.signal !== void 0) { - signal = init.signal; + if (init2.signal !== void 0) { + signal = init2.signal; } this[kState] = request3; const ac = new AbortController(); @@ -13106,7 +13106,7 @@ var require_request2 = __commonJS({ } if (initHasKey) { const headersList = getHeadersList(this[kHeaders]); - const headers = init.headers !== void 0 ? init.headers : new HeadersList(headersList); + const headers = init2.headers !== void 0 ? init2.headers : new HeadersList(headersList); headersList.clear(); if (headers instanceof HeadersList) { for (const { name, value } of headers.rawValues()) { @@ -13118,13 +13118,13 @@ var require_request2 = __commonJS({ } } const inputBody = input instanceof _Request ? input[kState].body : null; - if ((init.body != null || inputBody != null) && (request3.method === "GET" || request3.method === "HEAD")) { + if ((init2.body != null || inputBody != null) && (request3.method === "GET" || request3.method === "HEAD")) { throw new TypeError("Request with GET/HEAD method cannot have body."); } let initBody = null; - if (init.body != null) { + if (init2.body != null) { const [extractedBody, contentType] = extractBody( - init.body, + init2.body, request3.keepalive ); initBody = extractedBody; @@ -13134,7 +13134,7 @@ var require_request2 = __commonJS({ } const inputOrInitBody = initBody ?? inputBody; if (inputOrInitBody != null && inputOrInitBody.source == null) { - if (initBody != null && init.duplex == null) { + if (initBody != null && init2.duplex == null) { throw new TypeError("RequestInit: duplex option is required when sending a body."); } if (request3.mode !== "same-origin" && request3.mode !== "cors") { @@ -13329,46 +13329,46 @@ var require_request2 = __commonJS({ } }; mixinBody(Request); - function makeRequest(init) { + function makeRequest(init2) { return { - method: init.method ?? "GET", - localURLsOnly: init.localURLsOnly ?? false, - unsafeRequest: init.unsafeRequest ?? false, - body: init.body ?? null, - client: init.client ?? null, - reservedClient: init.reservedClient ?? null, - replacesClientId: init.replacesClientId ?? "", - window: init.window ?? "client", - keepalive: init.keepalive ?? false, - serviceWorkers: init.serviceWorkers ?? "all", - initiator: init.initiator ?? "", - destination: init.destination ?? "", - priority: init.priority ?? null, - origin: init.origin ?? "client", - policyContainer: init.policyContainer ?? "client", - referrer: init.referrer ?? "client", - referrerPolicy: init.referrerPolicy ?? "", - mode: init.mode ?? "no-cors", - useCORSPreflightFlag: init.useCORSPreflightFlag ?? false, - credentials: init.credentials ?? "same-origin", - useCredentials: init.useCredentials ?? false, - cache: init.cache ?? "default", - redirect: init.redirect ?? "follow", - integrity: init.integrity ?? "", - cryptoGraphicsNonceMetadata: init.cryptoGraphicsNonceMetadata ?? "", - parserMetadata: init.parserMetadata ?? "", - reloadNavigation: init.reloadNavigation ?? false, - historyNavigation: init.historyNavigation ?? false, - userActivation: init.userActivation ?? false, - taintedOrigin: init.taintedOrigin ?? false, - redirectCount: init.redirectCount ?? 0, - responseTainting: init.responseTainting ?? "basic", - preventNoCacheCacheControlHeaderModification: init.preventNoCacheCacheControlHeaderModification ?? false, - done: init.done ?? false, - timingAllowFailed: init.timingAllowFailed ?? false, - urlList: init.urlList, - url: init.urlList[0], - headersList: init.headersList ? new HeadersList(init.headersList) : new HeadersList() + method: init2.method ?? "GET", + localURLsOnly: init2.localURLsOnly ?? false, + unsafeRequest: init2.unsafeRequest ?? false, + body: init2.body ?? null, + client: init2.client ?? null, + reservedClient: init2.reservedClient ?? null, + replacesClientId: init2.replacesClientId ?? "", + window: init2.window ?? "client", + keepalive: init2.keepalive ?? false, + serviceWorkers: init2.serviceWorkers ?? "all", + initiator: init2.initiator ?? "", + destination: init2.destination ?? "", + priority: init2.priority ?? null, + origin: init2.origin ?? "client", + policyContainer: init2.policyContainer ?? "client", + referrer: init2.referrer ?? "client", + referrerPolicy: init2.referrerPolicy ?? "", + mode: init2.mode ?? "no-cors", + useCORSPreflightFlag: init2.useCORSPreflightFlag ?? false, + credentials: init2.credentials ?? "same-origin", + useCredentials: init2.useCredentials ?? false, + cache: init2.cache ?? "default", + redirect: init2.redirect ?? "follow", + integrity: init2.integrity ?? "", + cryptoGraphicsNonceMetadata: init2.cryptoGraphicsNonceMetadata ?? "", + parserMetadata: init2.parserMetadata ?? "", + reloadNavigation: init2.reloadNavigation ?? false, + historyNavigation: init2.historyNavigation ?? false, + userActivation: init2.userActivation ?? false, + taintedOrigin: init2.taintedOrigin ?? false, + redirectCount: init2.redirectCount ?? 0, + responseTainting: init2.responseTainting ?? "basic", + preventNoCacheCacheControlHeaderModification: init2.preventNoCacheCacheControlHeaderModification ?? false, + done: init2.done ?? false, + timingAllowFailed: init2.timingAllowFailed ?? false, + urlList: init2.urlList, + url: init2.urlList[0], + headersList: init2.headersList ? new HeadersList(init2.headersList) : new HeadersList() }; } function cloneRequest(request3) { @@ -13617,12 +13617,12 @@ var require_fetch = __commonJS({ function handleFetchDone(response) { finalizeAndReportTiming(response, "fetch"); } - function fetch(input, init = void 0) { + function fetch(input, init2 = void 0) { webidl.argumentLengthCheck(arguments, 1, "globalThis.fetch"); let p = createDeferredPromise(); let requestObject; try { - requestObject = new Request(input, init); + requestObject = new Request(input, init2); } catch (e) { p.reject(e); return p.promise; @@ -16602,9 +16602,9 @@ var require_events = __commonJS({ ports }); } - static createFastMessageEvent(type, init) { - const messageEvent = new _MessageEvent(kConstruct, type, init); - messageEvent.#eventInit = init; + static createFastMessageEvent(type, init2) { + const messageEvent = new _MessageEvent(kConstruct, type, init2); + messageEvent.#eventInit = init2; messageEvent.#eventInit.data ??= null; messageEvent.#eventInit.origin ??= ""; messageEvent.#eventInit.lastEventId ??= ""; @@ -16903,7 +16903,7 @@ var require_util7 = __commonJS({ function isClosed(ws) { return ws[kReadyState] === states.CLOSED; } - function fireEvent(e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { + function fireEvent(e, target, eventFactory = (type, init2) => new Event(type, init2), eventInitDict = {}) { const event = eventFactory(e, eventInitDict); target.dispatchEvent(event); } @@ -16981,7 +16981,7 @@ var require_util7 = __commonJS({ response.socket.destroy(); } if (reason) { - fireEvent("error", ws, (type, init) => new ErrorEvent(type, init), { + fireEvent("error", ws, (type, init2) => new ErrorEvent(type, init2), { error: new Error(reason), message: reason }); @@ -17289,7 +17289,7 @@ var require_connection = __commonJS({ code = 1006; } ws[kReadyState] = states.CLOSED; - fireEvent("close", ws, (type, init) => new CloseEvent(type, init), { + fireEvent("close", ws, (type, init2) => new CloseEvent(type, init2), { wasClean, code, reason @@ -18832,9 +18832,9 @@ var require_undici = __commonJS({ module2.exports.setGlobalDispatcher = setGlobalDispatcher; module2.exports.getGlobalDispatcher = getGlobalDispatcher; var fetchImpl = require_fetch().fetch; - module2.exports.fetch = async function fetch(init, options = void 0) { + module2.exports.fetch = async function fetch(init2, options = void 0) { try { - return await fetchImpl(init, options); + return await fetchImpl(init2, options); } catch (err) { if (err && typeof err === "object") { Error.captureStackTrace(err); @@ -37130,7 +37130,7 @@ var require_node = __commonJS({ "node_modules/debug/src/node.js"(exports2, module2) { var tty = require("tty"); var util3 = require("util"); - exports2.init = init; + exports2.init = init2; exports2.log = log; exports2.formatArgs = formatArgs; exports2.save = save; @@ -37279,7 +37279,7 @@ var require_node = __commonJS({ function load2() { return process.env.DEBUG; } - function init(debug6) { + function init2(debug6) { debug6.inspectOpts = {}; const keys = Object.keys(exports2.inspectOpts); for (let i = 0; i < keys.length; i++) { @@ -67055,8 +67055,8 @@ var require_operation = __commonJS({ return processResult ? processResult(response, state) : response; } async function initOperation(inputs) { - const { init, stateProxy, processResult, getOperationStatus, withOperationLocation, setErrorAsResult } = inputs; - const { operationLocation, resourceLocation, metadata, response } = await init(); + const { init: init2, stateProxy, processResult, getOperationStatus, withOperationLocation, setErrorAsResult } = inputs; + const { operationLocation, resourceLocation, metadata, response } = await init2(); if (operationLocation) withOperationLocation === null || withOperationLocation === void 0 ? void 0 : withOperationLocation(operationLocation, false); const config = { @@ -67450,7 +67450,7 @@ var require_poller = __commonJS({ }); function buildCreatePoller(inputs) { const { getOperationLocation, getStatusFromInitialResponse, getStatusFromPollResponse, isOperationError, getResourceLocation, getPollingInterval, getError, resolveOnUnsuccessful } = inputs; - return async ({ init, poll }, options) => { + return async ({ init: init2, poll }, options) => { const { processResult, updateState, withOperationLocation: withOperationLocationCallback, intervalInMs = constants_js_1.POLL_INTERVAL_IN_MS, restoreFrom } = options || {}; const stateProxy = createStateProxy(); const withOperationLocation = withOperationLocationCallback ? /* @__PURE__ */ (() => { @@ -67464,7 +67464,7 @@ var require_poller = __commonJS({ }; })() : void 0; const state = restoreFrom ? (0, operation_js_1.deserializeState)(restoreFrom) : await (0, operation_js_1.initOperation)({ - init, + init: init2, stateProxy, processResult, getOperationStatus: getStatusFromInitialResponse, @@ -115322,9 +115322,9 @@ var require_traverse = __commonJS({ this.value = walk(this.value, cb, false); return this.value; }; - Traverse.prototype.reduce = function(cb, init) { + Traverse.prototype.reduce = function(cb, init2) { var skip = arguments.length === 1; - var acc = skip ? this.value : init; + var acc = skip ? this.value : init2; this.forEach(function(x) { if (!this.isRoot || !skip) { acc = cb.call(this, acc, x); @@ -125762,7 +125762,7 @@ var require_aes = __commonJS({ }); }; forge.aes.Algorithm = function(name, mode) { - if (!init) { + if (!init2) { initialize(); } var self2 = this; @@ -125815,7 +125815,7 @@ var require_aes = __commonJS({ this._init = true; }; forge.aes._expandKey = function(key, decrypt) { - if (!init) { + if (!init2) { initialize(); } return _expandKey(key, decrypt); @@ -125833,7 +125833,7 @@ var require_aes = __commonJS({ }; forge.cipher.registerAlgorithm(name, factory); } - var init = false; + var init2 = false; var Nb = 4; var sbox; var isbox; @@ -125841,7 +125841,7 @@ var require_aes = __commonJS({ var mix; var imix; function initialize() { - init = true; + init2 = true; rcon = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54]; var xtime = new Array(256); for (var i = 0; i < 128; ++i) { @@ -139431,11 +139431,11 @@ var require_ed25519 = __commonJS({ q[i] ^= t; } } - function gf(init) { + function gf(init2) { var i, r = new Float64Array(16); - if (init) { - for (i = 0; i < init.length; ++i) { - r[i] = init[i]; + if (init2) { + for (i = 0; i < init2.length; ++i) { + r[i] = init2[i]; } } return r; @@ -159660,13 +159660,38 @@ async function runWrapper3() { // src/init-action.ts var fs28 = __toESM(require("fs")); var path24 = __toESM(require("path")); -var core20 = __toESM(require_core()); +var core21 = __toESM(require_core()); var github3 = __toESM(require_github()); var io7 = __toESM(require_io()); var semver10 = __toESM(require_semver2()); +// src/action-common.ts +var core19 = __toESM(require_core()); +async function runInActions(action) { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv + }); + } catch (error3) { + core19.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); + } +} + // src/config/file.ts -function getConfigFileInput(logger, actions, repositoryProperties, useRepositoryProperty) { +async function getConfigFileInput({ + logger, + actions, + features +}, repositoryProperties) { const input = actions.getOptionalInput("config-file"); if (input !== void 0) { logger.info(`Using configuration file input from workflow: ${input}`); @@ -159674,6 +159699,9 @@ function getConfigFileInput(logger, actions, repositoryProperties, useRepository } const propertyValue = repositoryProperties["github-codeql-config-file" /* CONFIG_FILE */]; if (propertyValue !== void 0 && propertyValue.trim().length > 0) { + const useRepositoryProperty = await features.getValue( + "config_file_repository_property" /* ConfigFileRepositoryProperty */ + ); if (useRepositoryProperty) { logger.info( `Using configuration file input from repository property: ${propertyValue}` @@ -159692,7 +159720,7 @@ function getConfigFileInput(logger, actions, repositoryProperties, useRepository var fs27 = __toESM(require("fs")); var path23 = __toESM(require("path")); var import_zlib3 = __toESM(require("zlib")); -var core19 = __toESM(require_core()); +var core20 = __toESM(require_core()); function toCodedErrors(errors) { return Object.entries(errors).reduce( (acc, [code, message]) => { @@ -159815,7 +159843,7 @@ async function validateWorkflow(codeql, logger) { } catch (e) { return `error: formatWorkflowErrors() failed: ${String(e)}`; } - core19.warning(message); + core20.warning(message); } return formatWorkflowCause(workflowErrors); } @@ -159944,7 +159972,7 @@ function getCheckoutPathInputOrThrow(workflow, jobName, matrixVars) { } async function checkWorkflow(logger, codeql) { if (!isDynamicWorkflow() && process.env["CODEQL_ACTION_SKIP_WORKFLOW_VALIDATION" /* SKIP_WORKFLOW_VALIDATION */] !== "true") { - core19.startGroup("Validating workflow"); + core20.startGroup("Validating workflow"); const validateWorkflowResult = await internal2.validateWorkflow( codeql, logger @@ -159956,7 +159984,7 @@ async function checkWorkflow(logger, codeql) { `Unable to validate code scanning workflow: ${validateWorkflowResult}` ); } - core19.endGroup(); + core20.endGroup(); } } var internal2 = { @@ -160026,9 +160054,9 @@ async function sendCompletedStatusReport2(startedAt, config, configFile, toolsDo await sendStatusReport({ ...initStatusReport, ...initToolsDownloadFields }); } } -async function run3(startedAt) { - const logger = getActionsLogger(); - const actionsEnv = getActionsEnv(); +async function run3(actionState) { + const startedAt = actionState.startedAt; + const logger = actionState.logger; let apiDetails; let config; let configFile; @@ -160066,16 +160094,11 @@ async function run3(startedAt) { const repositoryProperties = repositoryPropertiesResult.orElse({}); const jobRunUuid = v4_default(); logger.info(`Job run UUID is ${jobRunUuid}.`); - core20.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); - core20.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); - const useConfigFileProperty = await features.getValue( - "config_file_repository_property" /* ConfigFileRepositoryProperty */ - ); - configFile = getConfigFileInput( - logger, - actionsEnv, - repositoryProperties, - useConfigFileProperty + core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); + configFile = await getConfigFileInput( + { ...actionState, features }, + repositoryProperties ); sourceRoot = path24.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), @@ -160132,12 +160155,12 @@ async function run3(startedAt) { ); } if (semver10.lt(actualVer, publicPreview)) { - core20.exportVariable("CODEQL_ENABLE_EXPERIMENTAL_FEATURES" /* EXPERIMENTAL_FEATURES */, "true"); + core21.exportVariable("CODEQL_ENABLE_EXPERIMENTAL_FEATURES" /* EXPERIMENTAL_FEATURES */, "true"); logger.info("Experimental Rust analysis enabled"); } } analysisKinds = await getAnalysisKinds(logger, features); - const debugMode = getOptionalInput("debug") === "true" || core20.isDebug(); + const debugMode = getOptionalInput("debug") === "true" || core21.isDebug(); const fileCoverageResult = await getFileCoverageInformationEnabled( debugMode, codeql, @@ -160207,7 +160230,7 @@ async function run3(startedAt) { await checkInstallPython311(config.languages, codeql); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); - core20.setFailed(error3.message); + core21.setFailed(error3.message); const statusReportBase = await createStatusReportBase( "init" /* Init */, error3 instanceof ConfigurationError ? "user-error" : "aborted", @@ -160262,8 +160285,8 @@ async function run3(startedAt) { } const goFlags = process.env["GOFLAGS"]; if (goFlags) { - core20.exportVariable("GOFLAGS", goFlags); - core20.warning( + core21.exportVariable("GOFLAGS", goFlags); + core21.warning( "Passing the GOFLAGS env parameter to the init action is deprecated. Please move this to the analyze action." ); } @@ -160282,7 +160305,7 @@ async function run3(startedAt) { "bin" ); fs28.mkdirSync(tempBinPath, { recursive: true }); - core20.addPath(tempBinPath); + core21.addPath(tempBinPath); const goWrapperPath = path24.resolve(tempBinPath, "go"); fs28.writeFileSync( goWrapperPath, @@ -160291,14 +160314,14 @@ async function run3(startedAt) { exec ${goBinaryPath} "$@"` ); fs28.chmodSync(goWrapperPath, "755"); - core20.exportVariable("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goWrapperPath); + core21.exportVariable("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goWrapperPath); } catch (e) { logger.warning( `Analyzing Go on Linux, but failed to install wrapper script. Tracing custom builds may fail: ${e}` ); } } else { - core20.exportVariable("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goBinaryPath); + core21.exportVariable("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goBinaryPath); } } catch (e) { logger.warning( @@ -160325,23 +160348,23 @@ exec ${goBinaryPath} "$@"` } } } - core20.exportVariable( + core21.exportVariable( "CODEQL_RAM", process.env["CODEQL_RAM"] || getCodeQLMemoryLimit(getOptionalInput("ram"), logger).toString() ); - core20.exportVariable( + core21.exportVariable( "CODEQL_THREADS", process.env["CODEQL_THREADS"] || getThreadsFlagValue(getOptionalInput("threads"), logger).toString() ); if (await features.getValue("disable_kotlin_analysis_enabled" /* DisableKotlinAnalysisEnabled */)) { - core20.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true"); + core21.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true"); } if (await features.getValue("force_jgit" /* ForceJGit */)) { - core20.exportVariable("CODEQL_GIT_BACKEND", "jgit"); + core21.exportVariable("CODEQL_GIT_BACKEND", "jgit"); } const kotlinLimitVar = "CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT"; if (await codeQlVersionAtLeast(codeql, "2.20.3") && !await codeQlVersionAtLeast(codeql, "2.20.4")) { - core20.exportVariable(kotlinLimitVar, "2.1.20"); + core21.exportVariable(kotlinLimitVar, "2.1.20"); } if (shouldRestoreCache(config.dependencyCachingEnabled)) { const dependencyCachingResult = await downloadDependencyCaches( @@ -160368,7 +160391,7 @@ exec ${goBinaryPath} "$@"` `${"CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */} is already set to '${process.env["CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */]}', so the Action will not override it.` ); } else if (await codeQlVersionAtLeast(codeql, CODEQL_VERSION_JAR_MINIMIZATION) && config.dependencyCachingEnabled && config.buildMode === "none" /* None */ && config.languages.includes("java" /* java */)) { - core20.exportVariable( + core21.exportVariable( "CODEQL_EXTRACTOR_JAVA_OPTION_MINIMIZE_DEPENDENCY_JARS" /* JAVA_EXTRACTOR_MINIMIZE_DEPENDENCY_JARS */, "true" ); @@ -160412,23 +160435,23 @@ exec ${goBinaryPath} "$@"` const tracerConfig = await getCombinedTracerConfig(codeql, config); if (tracerConfig !== void 0) { for (const [key, value] of Object.entries(tracerConfig.env)) { - core20.exportVariable(key, value); + core21.exportVariable(key, value); } } if (await features.getValue("java_network_debugging" /* JavaNetworkDebugging */)) { const existingJavaToolOptions = getOptionalEnvVar("JAVA_TOOL_OPTIONS" /* JAVA_TOOL_OPTIONS */) || ""; - core20.exportVariable( + core21.exportVariable( "JAVA_TOOL_OPTIONS" /* JAVA_TOOL_OPTIONS */, `${existingJavaToolOptions} -Djavax.net.debug=all` ); } flushDiagnostics(config); await saveConfig(config, logger); - core20.setOutput("codeql-path", config.codeQLCmd); - core20.setOutput("codeql-version", (await codeql.getVersion()).version); + core21.setOutput("codeql-path", config.codeQLCmd); + core21.setOutput("codeql-version", (await codeql.getVersion()).version); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); - core20.setFailed(error3.message); + core21.setFailed(error3.message); await sendCompletedStatusReport2( startedAt, config, @@ -160490,25 +160513,17 @@ async function recordZstdAvailability(config, zstdAvailability) { ) ); } +var init = { + name: "init" /* Init */, + run: run3 +}; async function runWrapper4() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run3(startedAt); - } catch (error3) { - core20.setFailed(`init action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport( - "init" /* Init */, - startedAt, - error3, - logger - ); - } + await runInActions(init); await checkForTimeout(); } // src/init-action-post.ts -var core21 = __toESM(require_core()); +var core22 = __toESM(require_core()); // src/init-action-post-helper.ts var fs29 = __toESM(require("fs")); @@ -160856,7 +160871,7 @@ async function run4(startedAt) { } } catch (unwrappedError) { const error3 = wrapError(unwrappedError); - core21.setFailed(error3.message); + core22.setFailed(error3.message); const statusReportBase2 = await createStatusReportBase( "init-post" /* InitPost */, getActionsStatus(error3), @@ -160901,14 +160916,14 @@ function getFinalJobStatus(config) { } let jobStatus; if (process.env["CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */] === "true") { - core21.exportVariable("CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, "JOB_STATUS_SUCCESS" /* SuccessStatus */); + core22.exportVariable("CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, "JOB_STATUS_SUCCESS" /* SuccessStatus */); jobStatus = "JOB_STATUS_SUCCESS" /* SuccessStatus */; } else if (config !== void 0) { jobStatus = "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */; } else { jobStatus = "JOB_STATUS_UNKNOWN" /* UnknownStatus */; } - core21.exportVariable("CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, jobStatus); + core22.exportVariable("CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, jobStatus); return jobStatus; } function getJobStatusFromEnvironment() { @@ -160927,7 +160942,7 @@ async function runWrapper5() { try { await run4(startedAt); } catch (error3) { - core21.setFailed(`init post action failed: ${wrapError(error3).message}`); + core22.setFailed(`init post action failed: ${wrapError(error3).message}`); await sendUnhandledErrorStatusReport( "init-post" /* InitPost */, startedAt, @@ -160938,7 +160953,7 @@ async function runWrapper5() { } // src/resolve-environment-action.ts -var core22 = __toESM(require_core()); +var core23 = __toESM(require_core()); // src/resolve-environment.ts async function runResolveBuildEnvironment(cmd, logger, workingDir, language) { @@ -160985,16 +161000,16 @@ async function run5(startedAt) { workingDirectory, getRequiredInput("language") ); - core22.setOutput(ENVIRONMENT_OUTPUT_NAME, result); + core23.setOutput(ENVIRONMENT_OUTPUT_NAME, result); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); if (error3 instanceof CliError) { - core22.setOutput(ENVIRONMENT_OUTPUT_NAME, {}); + core23.setOutput(ENVIRONMENT_OUTPUT_NAME, {}); logger.warning( `Failed to resolve a build environment suitable for automatically building your code. ${error3.message}` ); } else { - core22.setFailed( + core23.setFailed( `Failed to resolve a build environment suitable for automatically building your code. ${error3.message}` ); const statusReportBase2 = await createStatusReportBase( @@ -161031,7 +161046,7 @@ async function runWrapper6() { try { await run5(startedAt); } catch (error3) { - core22.setFailed( + core23.setFailed( `${"resolve-environment" /* ResolveEnvironment */} action failed: ${getErrorMessage( error3 )}` @@ -161048,29 +161063,6 @@ async function runWrapper6() { // src/setup-codeql-action.ts var core24 = __toESM(require_core()); - -// src/action-common.ts -var core23 = __toESM(require_core()); -async function runInActions(action) { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - const env = getEnv(); - const actionsEnv = getActionsEnv(); - try { - await action.run({ - name: action.name, - startedAt, - logger, - env, - actions: actionsEnv - }); - } catch (error3) { - core23.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); - } -} - -// src/setup-codeql-action.ts async function sendCompletedStatusReport3(startedAt, toolsDownloadStatusReport, toolsFeatureFlagsValid, toolsSource, toolsVersion, logger, error3) { const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, diff --git a/src/config/file.test.ts b/src/config/file.test.ts index fef6088297..3362d26c63 100644 --- a/src/config/file.test.ts +++ b/src/config/file.test.ts @@ -1,22 +1,19 @@ import test from "ava"; import sinon from "sinon"; +import { Feature } from "../feature-flags"; import { RepositoryPropertyName } from "../feature-flags/properties"; -import { - getTestActionsEnv, - RecordingLogger, - setupTests, -} from "../testing-utils"; +import { callee, setupTests } from "../testing-utils"; import { getConfigFileInput } from "./file"; setupTests(test); test("getConfigFileInput returns undefined by default", async (t) => { - const logger = new RecordingLogger(); - const actionsEnv = getTestActionsEnv(); - const result = getConfigFileInput(logger, actionsEnv, {}, true); - t.is(result, undefined); + await callee(getConfigFileInput) + .withArgs({}) + .withFeatures([Feature.ConfigFileRepositoryProperty]) + .passes(async (fn) => t.is(await fn(), undefined)); }); const repositoryProperties = { @@ -24,9 +21,12 @@ const repositoryProperties = { }; test("getConfigFileInput returns input value", async (t) => { - const logger = new RecordingLogger(); - const actionsEnv = getTestActionsEnv(); const testInput = "/some/path"; + const target = callee(getConfigFileInput).withFeatures([ + Feature.ConfigFileRepositoryProperty, + ]); + + const actionsEnv = target.getState().actions; sinon .stub(actionsEnv, "getOptionalInput") .withArgs("config-file") @@ -34,76 +34,63 @@ test("getConfigFileInput returns input value", async (t) => { // Even though both an input and repository property are configured, // we prefer the direct input to the Action. - const result = getConfigFileInput( - logger, - actionsEnv, - repositoryProperties, - true, - ); - t.is(result, testInput); + const targetWithArgs = target + .withActions(actionsEnv) + .withArgs(repositoryProperties); + await targetWithArgs.passes(async (fn) => t.is(await fn(), testInput)); // Check for the expected log message. - t.true(logger.hasMessage("Using configuration file input from workflow")); + t.true( + targetWithArgs + .getLogger() + .hasMessage("Using configuration file input from workflow"), + ); }); test("getConfigFileInput returns repository property value", async (t) => { - const logger = new RecordingLogger(); - const actionsEnv = getTestActionsEnv(); - // Since there is no direct input, we should use the repository property. - const result = getConfigFileInput( - logger, - actionsEnv, - repositoryProperties, - true, + const target = callee(getConfigFileInput) + .withFeatures([Feature.ConfigFileRepositoryProperty]) + .withArgs(repositoryProperties); + + await target.passes(async (fn) => + t.is(await fn(), repositoryProperties[RepositoryPropertyName.CONFIG_FILE]), ); - t.is(result, repositoryProperties[RepositoryPropertyName.CONFIG_FILE]); // Check for the expected log message. t.true( - logger.hasMessage( - "Using configuration file input from repository property", - ), + target + .getLogger() + .hasMessage("Using configuration file input from repository property"), ); }); test("getConfigFileInput ignores empty repository property value", async (t) => { - const logger = new RecordingLogger(); - const actionsEnv = getTestActionsEnv(); - // Since the repository property value is an empty/whitespace string, we should ignore it. - const result = getConfigFileInput( - logger, - actionsEnv, - { - [RepositoryPropertyName.CONFIG_FILE]: " ", - }, - true, - ); - t.is(result, undefined); + await callee(getConfigFileInput) + .withFeatures([Feature.ConfigFileRepositoryProperty]) + .withArgs({ [RepositoryPropertyName.CONFIG_FILE]: " " }) + .passes(async (fn) => t.is(await fn(), undefined)); }); test("getConfigFileInput ignores repository property value when FF is off", async (t) => { - const logger = new RecordingLogger(); - const actionsEnv = getTestActionsEnv(); - // Since the FF is off, we should ignore the repository property value. - const result = getConfigFileInput( - logger, - actionsEnv, - repositoryProperties, - false, - ); - t.is(result, undefined); + const target = callee(getConfigFileInput) + .withFeatures([]) + .withArgs(repositoryProperties); + + await target.passes(async (fn) => t.is(await fn(), undefined)); t.false( - logger.hasMessage( - "Using configuration file input from repository property", - ), + target + .getLogger() + .hasMessage("Using configuration file input from repository property"), ); t.true( - logger.hasMessage( - "Ignoring configuration file input from repository property, because the corresponding feature flag is disabled.", - ), + target + .getLogger() + .hasMessage( + "Ignoring configuration file input from repository property, because the corresponding feature flag is disabled.", + ), ); }); diff --git a/src/config/file.ts b/src/config/file.ts index 6b8dfdcdcb..d216d3fda1 100644 --- a/src/config/file.ts +++ b/src/config/file.ts @@ -1,19 +1,21 @@ -import { ActionsEnv } from "../actions-util"; +import { ActionState } from "../action-common"; +import { Feature } from "../feature-flags"; import { RepositoryProperties, RepositoryPropertyName, } from "../feature-flags/properties"; -import { Logger } from "../logging"; /** * Gets the value that is configured for the configuration file, if any. */ -export function getConfigFileInput( - logger: Logger, - actions: ActionsEnv, +export async function getConfigFileInput( + { + logger, + actions, + features, + }: ActionState<["Logger", "Actions", "FeatureFlags"]>, repositoryProperties: Partial, - useRepositoryProperty: boolean, -): string | undefined { +): Promise { const input = actions.getOptionalInput("config-file"); if (input !== undefined) { @@ -26,6 +28,10 @@ export function getConfigFileInput( if (propertyValue !== undefined && propertyValue.trim().length > 0) { // Only use the repository property value if the FF is enabled. + const useRepositoryProperty = await features.getValue( + Feature.ConfigFileRepositoryProperty, + ); + if (useRepositoryProperty) { logger.info( `Using configuration file input from repository property: ${propertyValue}`, diff --git a/src/init-action.ts b/src/init-action.ts index 114344b667..c13eb2da65 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -262,14 +262,9 @@ async function run(actionState: ActionState<["Logger", "Actions"]>) { core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); - const useConfigFileProperty = await features.getValue( - Feature.ConfigFileRepositoryProperty, - ); - configFile = getConfigFileInput( - logger, - actionsEnv, + configFile = await getConfigFileInput( + { ...actionState, features }, repositoryProperties, - useConfigFileProperty, ); // path.resolve() respects the intended semantics of source-root. If From fcd9f6cbacea57d7a1689cb24604c01bd7456ec4 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:41:03 +0100 Subject: [PATCH 11/14] Fix `logger` reference --- src/testing-utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index d3faf7ea63..e69ebf35e4 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -220,11 +220,11 @@ export class TestEnv< this.logger = new RecordingLogger(); this.state = cloneFrom !== undefined - ? { ...cloneFrom.state } + ? { ...cloneFrom.state, logger: this.logger } : { name: ActionName.Init, startedAt: new Date(), - logger: new RecordingLogger(), + logger: this.logger, env: getTestEnv(), actions: getActionsEnv(), features: createFeatures([]), From 772e8e931041128f89ff9eda75273579963368bc Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:47:10 +0100 Subject: [PATCH 12/14] Use the common entry point for `autobuild` --- lib/entry-points.js | 69 ++++++++++++++++++----------------------- src/autobuild-action.ts | 28 ++++++----------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 696b557764..9f3790fe5d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -159558,7 +159558,30 @@ async function runWrapper2() { } // src/autobuild-action.ts +var core19 = __toESM(require_core()); + +// src/action-common.ts var core18 = __toESM(require_core()); +async function runInActions(action) { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv + }); + } catch (error3) { + core18.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); + } +} + +// src/autobuild-action.ts async function sendCompletedStatusReport(config, logger, startedAt, allLanguages, failingLanguage, cause) { initializeEnvironment(getActionVersion()); const status = getActionsStatus(cause, failingLanguage); @@ -159581,8 +159604,7 @@ async function sendCompletedStatusReport(config, logger, startedAt, allLanguages await sendStatusReport(statusReport); } } -async function run2(startedAt) { - const logger = getActionsLogger(); +async function run2({ startedAt, logger }) { let config; let currentLanguage; let languages; @@ -159625,7 +159647,7 @@ async function run2(startedAt) { await endTracingForCluster(codeql, config, logger); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); - core18.setFailed( + core19.setFailed( `We were unable to automatically build your code. Please replace the call to the autobuild action with your custom build steps. ${error3.message}` ); await sendCompletedStatusReport( @@ -159638,23 +159660,15 @@ async function run2(startedAt) { ); return; } - core18.exportVariable("CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */, "true"); + core19.exportVariable("CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */, "true"); await sendCompletedStatusReport(config, logger, startedAt, languages ?? []); } +var autobuild = { + name: "autobuild" /* Autobuild */, + run: run2 +}; async function runWrapper3() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run2(startedAt); - } catch (error3) { - core18.setFailed(`autobuild action failed. ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport( - "autobuild" /* Autobuild */, - startedAt, - error3, - logger - ); - } + await runInActions(autobuild); } // src/init-action.ts @@ -159665,27 +159679,6 @@ var github3 = __toESM(require_github()); var io7 = __toESM(require_io()); var semver10 = __toESM(require_semver2()); -// src/action-common.ts -var core19 = __toESM(require_core()); -async function runInActions(action) { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - const env = getEnv(); - const actionsEnv = getActionsEnv(); - try { - await action.run({ - name: action.name, - startedAt, - logger, - env, - actions: actionsEnv - }); - } catch (error3) { - core19.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); - } -} - // src/config/file.ts async function getConfigFileInput({ logger, diff --git a/src/autobuild-action.ts b/src/autobuild-action.ts index dc20211379..afda0e236a 100644 --- a/src/autobuild-action.ts +++ b/src/autobuild-action.ts @@ -1,5 +1,6 @@ import * as core from "@actions/core"; +import { Action, ActionState, runInActions } from "./action-common"; import { getActionVersion, getOptionalInput, @@ -11,13 +12,12 @@ import { getCodeQL } from "./codeql"; import { Config, getConfig } from "./config-utils"; import { EnvVar } from "./environment"; import { Language } from "./languages"; -import { Logger, getActionsLogger } from "./logging"; +import { Logger } from "./logging"; import { StatusReportBase, getActionsStatus, createStatusReportBase, sendStatusReport, - sendUnhandledErrorStatusReport, ActionName, } from "./status-report"; import { endTracingForCluster } from "./tracer-config"; @@ -26,7 +26,6 @@ import { checkDiskUsage, checkGitHubVersionInRange, ConfigurationError, - getErrorMessage, initializeEnvironment, wrapError, } from "./util"; @@ -69,11 +68,10 @@ async function sendCompletedStatusReport( } } -async function run(startedAt: Date) { +async function run({ startedAt, logger }: ActionState<["Logger"]>) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. - const logger = getActionsLogger(); let config: Config | undefined; let currentLanguage: Language | undefined; let languages: Language[] | undefined; @@ -142,18 +140,12 @@ async function run(startedAt: Date) { await sendCompletedStatusReport(config, logger, startedAt, languages ?? []); } +/** Defines the `autobuild` Action. */ +const autobuild: Action = { + name: ActionName.Autobuild, + run, +}; + export async function runWrapper() { - const startedAt = new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error) { - core.setFailed(`autobuild action failed. ${getErrorMessage(error)}`); - await sendUnhandledErrorStatusReport( - ActionName.Autobuild, - startedAt, - error, - logger, - ); - } + await runInActions(autobuild); } From ceac4af134d68f39f4f97d31543840c5203b05ea Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:49:33 +0100 Subject: [PATCH 13/14] Use the common entry point for `analyze` --- lib/entry-points.js | 6627 ++++++++++++++++++++--------------------- src/analyze-action.ts | 25 +- 2 files changed, 3318 insertions(+), 3334 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 9f3790fe5d..8023ab6d55 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -141290,7 +141290,10 @@ module.exports = __toCommonJS(entry_points_exports); var fs22 = __toESM(require("fs")); var import_path4 = __toESM(require("path")); var import_perf_hooks4 = require("perf_hooks"); -var core15 = __toESM(require_core()); +var core16 = __toESM(require_core()); + +// src/action-common.ts +var core10 = __toESM(require_core()); // src/actions-util.ts var fs2 = __toESM(require("fs")); @@ -145243,13 +145246,53 @@ function fixCodeQualityCategory(logger, category) { return category; } -// src/feature-flags.ts -var fs5 = __toESM(require("fs")); -var path5 = __toESM(require("path")); -var semver4 = __toESM(require_semver2()); +// src/logging.ts +var core4 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core4.debug, + info: core4.info, + warning: core4.warning, + error: core4.error, + isDebug: core4.isDebug, + startGroup: core4.startGroup, + endGroup: core4.endGroup + }; +} +function withGroup(groupName, f) { + core4.startGroup(groupName); + try { + return f(); + } finally { + core4.endGroup(); + } +} +async function withGroupAsync(groupName, f) { + core4.startGroup(groupName); + try { + return await f(); + } finally { + core4.endGroup(); + } +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/status-report.ts +var os3 = __toESM(require("os")); +var core9 = __toESM(require_core()); // src/api-client.ts -var core4 = __toESM(require_core()); +var core5 = __toESM(require_core()); var githubUtils = __toESM(require_utils4()); // node_modules/@octokit/plugin-retry/dist-bundle/index.js @@ -145362,10 +145405,10 @@ function createApiClientWithDetails(apiDetails, { allowExternal = false } = {}) baseUrl: apiDetails.apiURL, userAgent: `CodeQL-Action/${getActionVersion()}`, log: { - debug: core4.debug, - info: core4.info, - warn: core4.warning, - error: core4.error + debug: core5.debug, + info: core5.info, + warn: core5.warning, + error: core5.error }, retry: { doNotRetry: DO_NOT_RETRY_STATUSES @@ -145446,7 +145489,7 @@ async function getAnalysisKey() { const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core4.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } async function getAutomationID() { @@ -145533,6 +145576,17 @@ function wrapApiConfigurationError(e) { return e; } +// src/config-utils.ts +var fs9 = __toESM(require("fs")); +var path10 = __toESM(require("path")); +var import_perf_hooks = require("perf_hooks"); +var core8 = __toESM(require_core()); + +// src/feature-flags.ts +var fs5 = __toESM(require("fs")); +var path5 = __toESM(require("path")); +var semver4 = __toESM(require_semver2()); + // src/defaults.json var bundleVersion = "codeql-bundle-v2.25.6"; var cliVersion = "2.25.6"; @@ -145545,7 +145599,7 @@ var path4 = __toESM(require("path")); var fs3 = __toESM(require("fs")); var os2 = __toESM(require("os")); var path3 = __toESM(require("path")); -var core5 = __toESM(require_core()); +var core6 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver2 = __toESM(require_semver2()); @@ -145576,7 +145630,7 @@ async function getGitVersionOrThrow() { var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; - core5.debug(`Running git command: git ${args.join(" ")}`); + core6.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -145597,7 +145651,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage, o if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core5.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core6.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -145760,7 +145814,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core5.debug( + core6.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -146641,364 +146695,95 @@ var SarifScanOrder = [ CodeScanning ]; -// src/analyze.ts -var fs16 = __toESM(require("fs")); -var path15 = __toESM(require("path")); -var import_perf_hooks3 = require("perf_hooks"); -var io5 = __toESM(require_io()); - -// src/autobuild.ts -var core11 = __toESM(require_core()); - -// src/codeql.ts -var fs15 = __toESM(require("fs")); -var path14 = __toESM(require("path")); -var core10 = __toESM(require_core()); -var toolrunner3 = __toESM(require_toolrunner()); - -// src/cli-errors.ts -var SUPPORTED_PLATFORMS = [ - ["linux", "x64"], - ["win32", "x64"], - ["darwin", "x64"], - ["darwin", "arm64"] -]; -var CliError = class extends Error { - exitCode; - stderr; - constructor({ cmd, args, exitCode, stderr }) { - const prettyCommand = prettyPrintInvocation(cmd, args); - const fatalErrors = extractFatalErrors(stderr); - const autobuildErrors = extractAutobuildErrors(stderr); - let message; - if (fatalErrors) { - message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and error was: ${ensureEndsInPeriod( - fatalErrors.trim() - )} See the logs for more details.`; - } else if (autobuildErrors) { - message = `We were unable to automatically build your code. Please provide manual build steps. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information. Encountered the following error: ${autobuildErrors}`; - } else { - const lastLine = ensureEndsInPeriod( - stderr.trim().split("\n").pop()?.trim() || "n/a" +// src/caching-utils.ts +var crypto2 = __toESM(require("crypto")); +var core7 = __toESM(require_core()); +async function getTotalCacheSize(paths, logger, quiet = false) { + const sizes = await Promise.all( + paths.map((cacheDir2) => tryGetFolderBytes(cacheDir2, logger, quiet)) + ); + return sizes.map((a) => a || 0).reduce((a, b) => a + b, 0); +} +function shouldStoreCache(kind) { + return kind === "full" /* Full */ || kind === "store" /* Store */; +} +function shouldRestoreCache(kind) { + return kind === "full" /* Full */ || kind === "restore" /* Restore */; +} +function getCachingKind(input) { + switch (input) { + case void 0: + case "none": + case "off": + case "false": + return "none" /* None */; + case "full": + case "on": + case "true": + return "full" /* Full */; + case "store": + return "store" /* Store */; + case "restore": + return "restore" /* Restore */; + default: + core7.warning( + `Unrecognized 'dependency-caching' input: ${input}. Defaulting to 'none'.` ); - message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and last log line was: ${lastLine} See the logs for more details.`; - } - super(message); - this.exitCode = exitCode; - this.stderr = stderr; - } -}; -function extractFatalErrors(error3) { - const fatalErrorRegex = /.*fatal (internal )?error occurr?ed(. Details)?:/gi; - let fatalErrors = []; - let lastFatalErrorIndex; - let match2; - while ((match2 = fatalErrorRegex.exec(error3)) !== null) { - if (lastFatalErrorIndex !== void 0) { - fatalErrors.push(error3.slice(lastFatalErrorIndex, match2.index).trim()); - } - lastFatalErrorIndex = match2.index; - } - if (lastFatalErrorIndex !== void 0) { - const lastError = error3.slice(lastFatalErrorIndex).trim(); - if (fatalErrors.length === 0) { - return lastError; - } - const isOneLiner = !fatalErrors.some((e) => e.includes("\n")); - if (isOneLiner) { - fatalErrors = fatalErrors.map(ensureEndsInPeriod); - } - return [ - ensureEndsInPeriod(lastError), - "Context:", - ...fatalErrors.reverse() - ].join(isOneLiner ? " " : "\n"); + return "none" /* None */; } - return void 0; } -function extractAutobuildErrors(error3) { - const pattern = /.*\[autobuild\] \[ERROR\] (.*)/gi; - let errorLines = [...error3.matchAll(pattern)].map((match2) => match2[1]); - if (errorLines.length > 10) { - errorLines = errorLines.slice(0, 10); - errorLines.push("(truncated)"); - } - return errorLines.join("\n") || void 0; -} -var cliErrorsConfig = { - ["AutobuildError" /* AutobuildError */]: { - cliErrorMessageCandidates: [ - new RegExp("We were unable to automatically build your code") - ] - }, - ["CouldNotCreateTempDir" /* CouldNotCreateTempDir */]: { - cliErrorMessageCandidates: [new RegExp("Could not create temp directory")] - }, - ["ExternalRepositoryCloneFailed" /* ExternalRepositoryCloneFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("Failed to clone external Git repository") - ] - }, - ["GradleBuildFailed" /* GradleBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("\\[autobuild\\] FAILURE: Build failed with an exception.") - ] - }, - // Version of CodeQL CLI is incompatible with this version of the CodeQL Action - ["IncompatibleWithActionVersion" /* IncompatibleWithActionVersion */]: { - cliErrorMessageCandidates: [ - new RegExp("is not compatible with this CodeQL CLI") - ] - }, - ["InitCalledTwice" /* InitCalledTwice */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Refusing to create databases .* but could not process any of it" - ) - ], - additionalErrorMessageToAppend: `Is the "init" action called twice in the same job?` - }, - ["InvalidConfigFile" /* InvalidConfigFile */]: { - cliErrorMessageCandidates: [ - new RegExp("Config file .* is not valid"), - new RegExp("The supplied config file is empty") - ] - }, - ["InvalidExternalRepoSpecifier" /* InvalidExternalRepoSpecifier */]: { - cliErrorMessageCandidates: [ - new RegExp("Specifier for external repository is invalid") - ] - }, - // Expected source location for database creation does not exist - ["InvalidSourceRoot" /* InvalidSourceRoot */]: { - cliErrorMessageCandidates: [new RegExp("Invalid source root")] - }, - ["MavenBuildFailed" /* MavenBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("\\[autobuild\\] \\[ERROR\\] Failed to execute goal") - ] - }, - ["NoBuildCommandAutodetected" /* NoBuildCommandAutodetected */]: { - cliErrorMessageCandidates: [ - new RegExp("Could not auto-detect a suitable build method") - ] - }, - ["NoBuildMethodAutodetected" /* NoBuildMethodAutodetected */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Could not detect a suitable build command for the source checkout" - ) - ] - }, - // Usually when a manual build script has failed, or if an autodetected language - // was unintended to have CodeQL analysis run on it. - ["NoSourceCodeSeen" /* NoSourceCodeSeen */]: { - exitCode: 32, - cliErrorMessageCandidates: [ - new RegExp( - "CodeQL detected code written in .* but could not process any of it" - ), - new RegExp( - "CodeQL did not detect any code written in languages supported by CodeQL" - ) - ] - }, - ["NoSupportedBuildCommandSucceeded" /* NoSupportedBuildCommandSucceeded */]: { - cliErrorMessageCandidates: [ - new RegExp("No supported build command succeeded") - ] - }, - ["NoSupportedBuildSystemDetected" /* NoSupportedBuildSystemDetected */]: { - cliErrorMessageCandidates: [ - new RegExp("No supported build system detected") - ] - }, - ["OutOfMemoryOrDisk" /* OutOfMemoryOrDisk */]: { - cliErrorMessageCandidates: [ - new RegExp("CodeQL is out of memory."), - new RegExp("out of disk"), - new RegExp("No space left on device") - ], - additionalErrorMessageToAppend: "For more information, see https://gh.io/troubleshooting-code-scanning/out-of-disk-or-memory" - }, - ["PackCannotBeFound" /* PackCannotBeFound */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Query pack .* cannot be found\\. Check the spelling of the pack\\." - ), - new RegExp( - "is not a .ql file, .qls file, a directory, or a query pack specification." - ) - ] - }, - ["PackMissingAuth" /* PackMissingAuth */]: { - cliErrorMessageCandidates: [ - new RegExp("GitHub Container registry .* 403 Forbidden"), - new RegExp( - "Do you need to specify a token to authenticate to the registry?" - ) - ] - }, - ["SwiftBuildFailed" /* SwiftBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp( - "\\[autobuilder/build\\] \\[build-command-failed\\] `autobuild` failed to run the build command" - ) - ] - }, - ["SwiftIncompatibleOs" /* SwiftIncompatibleOs */]: { - cliErrorMessageCandidates: [ - new RegExp("\\[incompatible-os\\]"), - new RegExp("Swift analysis is only supported on macOS") - ] - }, - ["UnsupportedBuildMode" /* UnsupportedBuildMode */]: { - cliErrorMessageCandidates: [ - new RegExp( - "does not support the .* build mode. Please try using one of the following build modes instead" - ) - ] - }, - ["NotFoundInRegistry" /* NotFoundInRegistry */]: { - cliErrorMessageCandidates: [ - new RegExp("'.*' not found in the registry '.*'") - ] - } -}; -function getCliConfigCategoryIfExists(cliError) { - for (const [category, configuration] of Object.entries(cliErrorsConfig)) { - if (cliError.exitCode !== void 0 && configuration.exitCode !== void 0 && cliError.exitCode === configuration.exitCode) { - return category; - } - for (const e of configuration.cliErrorMessageCandidates) { - if (cliError.message.match(e) || cliError.stderr.match(e)) { - return category; - } - } - } - return void 0; -} -function isUnsupportedPlatform() { - return !SUPPORTED_PLATFORMS.some( - ([platform2, arch2]) => platform2 === process.platform && arch2 === process.arch - ); -} -function getUnsupportedPlatformError(cliError) { - return new ConfigurationError( - `The CodeQL CLI does not support the platform/architecture combination of ${process.platform}/${process.arch} (see ${"https://codeql.github.com/docs/codeql-overview/system-requirements/" /* SYSTEM_REQUIREMENTS */}). The underlying error was: ${cliError.message}` - ); -} -function wrapCliConfigurationError(cliError) { - if (isUnsupportedPlatform()) { - return getUnsupportedPlatformError(cliError); - } - const cliConfigErrorCategory = getCliConfigCategoryIfExists(cliError); - if (cliConfigErrorCategory === void 0) { - return cliError; - } - let errorMessageBuilder = cliError.message; - const additionalErrorMessageToAppend = cliErrorsConfig[cliConfigErrorCategory].additionalErrorMessageToAppend; - if (additionalErrorMessageToAppend !== void 0) { - errorMessageBuilder = `${errorMessageBuilder} ${additionalErrorMessageToAppend}`; - } - return new ConfigurationError(errorMessageBuilder); -} - -// src/config-utils.ts -var fs9 = __toESM(require("fs")); -var path10 = __toESM(require("path")); -var import_perf_hooks = require("perf_hooks"); -var core8 = __toESM(require_core()); - -// src/caching-utils.ts -var crypto2 = __toESM(require("crypto")); -var core6 = __toESM(require_core()); -async function getTotalCacheSize(paths, logger, quiet = false) { - const sizes = await Promise.all( - paths.map((cacheDir2) => tryGetFolderBytes(cacheDir2, logger, quiet)) - ); - return sizes.map((a) => a || 0).reduce((a, b) => a + b, 0); -} -function shouldStoreCache(kind) { - return kind === "full" /* Full */ || kind === "store" /* Store */; -} -function shouldRestoreCache(kind) { - return kind === "full" /* Full */ || kind === "restore" /* Restore */; -} -function getCachingKind(input) { - switch (input) { - case void 0: - case "none": - case "off": - case "false": - return "none" /* None */; - case "full": - case "on": - case "true": - return "full" /* Full */; - case "store": - return "store" /* Store */; - case "restore": - return "restore" /* Restore */; - default: - core6.warning( - `Unrecognized 'dependency-caching' input: ${input}. Defaulting to 'none'.` - ); - return "none" /* None */; - } -} -var cacheKeyHashLength = 16; -function createCacheKeyHash(components) { - const componentsJson = JSON.stringify(components); - return crypto2.createHash("sha256").update(componentsJson).digest("hex").substring(0, cacheKeyHashLength); -} -function getDependencyCachingEnabled() { - const dependencyCaching = getOptionalInput("dependency-caching") || process.env["CODEQL_ACTION_DEPENDENCY_CACHING" /* DEPENDENCY_CACHING */]; - if (dependencyCaching !== void 0) return getCachingKind(dependencyCaching); - if (!isHostedRunner()) return "none" /* None */; - if (!isDefaultSetup()) return "none" /* None */; - return "none" /* None */; -} - -// src/config/db-config.ts -var path6 = __toESM(require("path")); -var jsonschema = __toESM(require_lib2()); -var semver5 = __toESM(require_semver2()); - -// src/error-messages.ts -var PACKS_PROPERTY = "packs"; -function getConfigFileOutsideWorkspaceErrorMessage(configFile) { - return `The configuration file "${configFile}" is outside of the workspace`; -} -function getConfigFileDoesNotExistErrorMessage(configFile) { - return `The configuration file "${configFile}" does not exist`; -} -function getConfigFileParseErrorMessage(configFile, message) { - return `Cannot parse "${configFile}": ${message}`; -} -function getInvalidConfigFileMessage(configFile, messages) { - const andMore = messages.length > 10 ? `, and ${messages.length - 10} more.` : "."; - return `The configuration file "${configFile}" is invalid: ${messages.slice(0, 10).join(", ")}${andMore}`; -} -function getConfigFileRepoFormatInvalidMessage(configFile) { - let error3 = `The configuration file "${configFile}" is not a supported remote file reference.`; - error3 += " Expected format //@"; - return error3; -} -function getConfigFileFormatInvalidMessage(configFile) { - return `The configuration file "${configFile}" could not be read`; -} -function getConfigFileDirectoryGivenMessage(configFile) { - return `The configuration file "${configFile}" looks like a directory, not a file`; -} -function getEmptyCombinesError() { - return `A '+' was used to specify that you want to add extra arguments to the configuration, but no extra arguments were specified. Please either remove the '+' or specify some extra arguments.`; -} -function getConfigFilePropertyError(configFile, property, error3) { - if (configFile === void 0) { - return `The workflow property "${property}" is invalid: ${error3}`; - } else { - return `The configuration file "${configFile}" is invalid: property "${property}" ${error3}`; +var cacheKeyHashLength = 16; +function createCacheKeyHash(components) { + const componentsJson = JSON.stringify(components); + return crypto2.createHash("sha256").update(componentsJson).digest("hex").substring(0, cacheKeyHashLength); +} +function getDependencyCachingEnabled() { + const dependencyCaching = getOptionalInput("dependency-caching") || process.env["CODEQL_ACTION_DEPENDENCY_CACHING" /* DEPENDENCY_CACHING */]; + if (dependencyCaching !== void 0) return getCachingKind(dependencyCaching); + if (!isHostedRunner()) return "none" /* None */; + if (!isDefaultSetup()) return "none" /* None */; + return "none" /* None */; +} + +// src/config/db-config.ts +var path6 = __toESM(require("path")); +var jsonschema = __toESM(require_lib2()); +var semver5 = __toESM(require_semver2()); + +// src/error-messages.ts +var PACKS_PROPERTY = "packs"; +function getConfigFileOutsideWorkspaceErrorMessage(configFile) { + return `The configuration file "${configFile}" is outside of the workspace`; +} +function getConfigFileDoesNotExistErrorMessage(configFile) { + return `The configuration file "${configFile}" does not exist`; +} +function getConfigFileParseErrorMessage(configFile, message) { + return `Cannot parse "${configFile}": ${message}`; +} +function getInvalidConfigFileMessage(configFile, messages) { + const andMore = messages.length > 10 ? `, and ${messages.length - 10} more.` : "."; + return `The configuration file "${configFile}" is invalid: ${messages.slice(0, 10).join(", ")}${andMore}`; +} +function getConfigFileRepoFormatInvalidMessage(configFile) { + let error3 = `The configuration file "${configFile}" is not a supported remote file reference.`; + error3 += " Expected format //@"; + return error3; +} +function getConfigFileFormatInvalidMessage(configFile) { + return `The configuration file "${configFile}" could not be read`; +} +function getConfigFileDirectoryGivenMessage(configFile) { + return `The configuration file "${configFile}" looks like a directory, not a file`; +} +function getEmptyCombinesError() { + return `A '+' was used to specify that you want to add extra arguments to the configuration, but no extra arguments were specified. Please either remove the '+' or specify some extra arguments.`; +} +function getConfigFilePropertyError(configFile, property, error3) { + if (configFile === void 0) { + return `The workflow property "${property}" is invalid: ${error3}`; + } else { + return `The configuration file "${configFile}" is invalid: property "${property}" ${error3}`; } } function getRepoPropertyError(propertyName, error3) { @@ -147366,57 +147151,14 @@ function parseUserConfig(logger, pathInput, contents, validateConfig) { // src/diagnostics.ts var import_fs = require("fs"); var import_path = __toESM(require("path")); - -// src/logging.ts -var core7 = __toESM(require_core()); -function getActionsLogger() { +var unwrittenDiagnostics = []; +var unwrittenDefaultLanguageDiagnostics = []; +var diagnosticCounter = 0; +function makeDiagnostic(id, name, data = void 0) { return { - debug: core7.debug, - info: core7.info, - warning: core7.warning, - error: core7.error, - isDebug: core7.isDebug, - startGroup: core7.startGroup, - endGroup: core7.endGroup - }; -} -function withGroup(groupName, f) { - core7.startGroup(groupName); - try { - return f(); - } finally { - core7.endGroup(); - } -} -async function withGroupAsync(groupName, f) { - core7.startGroup(groupName); - try { - return await f(); - } finally { - core7.endGroup(); - } -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - -// src/diagnostics.ts -var unwrittenDiagnostics = []; -var unwrittenDefaultLanguageDiagnostics = []; -var diagnosticCounter = 0; -function makeDiagnostic(id, name, data = void 0) { - return { - ...data, - timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), - source: { ...data?.source, id, name } + ...data, + timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), + source: { ...data?.source, id, name } }; } function addDiagnostic(config, language, diagnostic) { @@ -149024,3183 +148766,3464 @@ async function logGeneratedFilesTelemetry(config, duration, generatedFilesCount) ); } -// src/setup-codeql.ts -var fs13 = __toESM(require("fs")); -var path12 = __toESM(require("path")); -var toolcache3 = __toESM(require_tool_cache()); -var import_fast_deep_equal = __toESM(require_fast_deep_equal()); -var semver9 = __toESM(require_semver2()); - -// node_modules/uuid/dist-node/stringify.js -var byteToHex = []; -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 256).toString(16).slice(1)); -} -function unsafeStringify(arr, offset = 0) { - return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); +// src/status-report.ts +function isFirstPartyAnalysis(actionName) { + if (actionName !== "upload-sarif" /* UploadSarif */) { + return true; + } + return process.env["CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */] === "true"; } - -// node_modules/uuid/dist-node/rng.js -var rnds8 = new Uint8Array(16); -function rng() { - return crypto.getRandomValues(rnds8); +function isThirdPartyAnalysis(actionName) { + return !isFirstPartyAnalysis(actionName); } - -// node_modules/uuid/dist-node/v4.js -function v4(options, buf, offset) { - if (!buf && !options && crypto.randomUUID) { - return crypto.randomUUID(); +var JobStatus = /* @__PURE__ */ ((JobStatus2) => { + JobStatus2["UnknownStatus"] = "JOB_STATUS_UNKNOWN"; + JobStatus2["SuccessStatus"] = "JOB_STATUS_SUCCESS"; + JobStatus2["FailureStatus"] = "JOB_STATUS_FAILURE"; + JobStatus2["ConfigErrorStatus"] = "JOB_STATUS_CONFIGURATION_ERROR"; + return JobStatus2; +})(JobStatus || {}); +function getActionsStatus(error3, otherFailureCause) { + if (error3 || otherFailureCause) { + return error3 instanceof ConfigurationError ? "user-error" : "failure"; + } else { + return "success"; } - return _v4(options, buf, offset); } -function _v4(options, buf, offset) { - options = options || {}; - const rnds = options.random ?? options.rng?.() ?? rng(); - if (rnds.length < 16) { - throw new Error("Random bytes length must be >= 16"); - } - rnds[6] = rnds[6] & 15 | 64; - rnds[8] = rnds[8] & 63 | 128; - if (buf) { - offset = offset || 0; - if (offset < 0 || offset + 16 > buf.length) { - throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); - } - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - return buf; +function getJobStatusDisplayName(status) { + switch (status) { + case "JOB_STATUS_SUCCESS" /* SuccessStatus */: + return "success"; + case "JOB_STATUS_FAILURE" /* FailureStatus */: + return "failure"; + case "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */: + return "configuration error"; + case "JOB_STATUS_UNKNOWN" /* UnknownStatus */: + return "unknown"; + default: + assertNever(status); } - return unsafeStringify(rnds); } -var v4_default = v4; - -// src/overlay/caching.ts -var fs10 = __toESM(require("fs")); -var actionsCache3 = __toESM(require_cache4()); -var semver6 = __toESM(require_semver2()); -var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; -var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6; -var CACHE_VERSION2 = 1; -var CACHE_PREFIX = "codeql-overlay-base-database"; -var MAX_CACHE_OPERATION_MS3 = 6e5; -async function checkOverlayBaseDatabase(codeql, config, logger, warningPrefix) { - const baseDatabaseOidsFilePath = getBaseDatabaseOidsFilePath(config); - if (!fs10.existsSync(baseDatabaseOidsFilePath)) { - logger.warning( - `${warningPrefix}: ${baseDatabaseOidsFilePath} does not exist` +function setJobStatusIfUnsuccessful(actionStatus) { + if (actionStatus === "user-error") { + core9.exportVariable( + "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, + process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */ + ); + } else if (actionStatus === "failure" || actionStatus === "aborted") { + core9.exportVariable( + "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, + process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_FAILURE" /* FailureStatus */ ); - return false; } - for (const language of config.languages) { - const dbPath = getCodeQLDatabasePath(config, language); +} +async function createStatusReportBase(actionName, status, actionStartedAt, config, diskInfo, logger, cause, exception) { + try { + const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || ""; + const ref = await getRef(); + const jobRunUUID = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */] || ""; + const workflowRunID = getWorkflowRunID(); + const workflowRunAttempt = getWorkflowRunAttempt(); + const workflowName = process.env["GITHUB_WORKFLOW"] || ""; + const jobName = process.env["GITHUB_JOB"] || ""; + const analysis_key = await getAnalysisKey(); + let workflowStartedAt = process.env["CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */]; + if (workflowStartedAt === void 0) { + workflowStartedAt = actionStartedAt.toISOString(); + core9.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt); + } + const runnerOs = getRequiredEnvParam("RUNNER_OS"); + const codeQlCliVersion = getCachedCodeQlVersion(); + const actionRef = process.env["GITHUB_ACTION_REF"] || ""; + const testingEnvironment = getTestingEnvironment(); + if (testingEnvironment) { + core9.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment); + } + const isSteadyStateDefaultSetupRun = process.env["CODE_SCANNING_IS_STEADY_STATE_DEFAULT_SETUP"] === "true"; + 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: getActionVersion(), + analysis_kinds: config?.analysisKinds?.join(","), + 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, + steady_state_default_setup: isSteadyStateDefaultSetupRun, + testing_environment: testingEnvironment || "", + workflow_name: workflowName, + workflow_run_attempt: workflowRunAttempt, + workflow_run_id: workflowRunID + }; try { - const resolveDatabaseOutput = await codeql.resolveDatabase(dbPath); - if (resolveDatabaseOutput === void 0 || !("overlayBaseSpecifier" in resolveDatabaseOutput)) { - logger.info(`${warningPrefix}: no overlayBaseSpecifier defined`); - return false; - } else { - logger.debug( - `Overlay base specifier for ${language} overlay-base database found: ${resolveDatabaseOutput.overlayBaseSpecifier}` - ); - } + statusReport.actions_event_name = getWorkflowEventName(); } catch (e) { - logger.warning(`${warningPrefix}: failed to resolve database: ${e}`); - return false; + logger.warning( + `Could not determine the workflow event name: ${getErrorMessage(e)}.` + ); } - } - return true; -} -async function cleanupAndUploadOverlayBaseDatabaseToCache(codeql, config, logger) { - const overlayDatabaseMode = config.overlayDatabaseMode; - if (overlayDatabaseMode !== "overlay-base" /* OverlayBase */) { - logger.debug( - `Overlay database mode is ${overlayDatabaseMode}. Skip uploading overlay-base database to cache.` - ); - return false; - } - if (!config.useOverlayDatabaseCaching) { - logger.debug( - "Overlay database caching is disabled. Skip uploading overlay-base database to cache." + 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; + } + if (cause) { + statusReport.cause = cause; + } + if (exception) { + statusReport.exception = exception; + } + if (status === "success" || status === "failure" || status === "aborted" || status === "user-error") { + statusReport.completed_at = (/* @__PURE__ */ new Date()).toISOString(); + } + const matrix = getRequiredInput("matrix"); + if (matrix) { + statusReport.matrix_vars = matrix; + } + if ("RUNNER_ARCH" in process.env) { + statusReport.runner_arch = process.env["RUNNER_ARCH"]; + } + if (!(runnerOs === "Linux" && isSelfHostedRunner())) { + statusReport.runner_os_release = os3.release(); + } + if (codeQlCliVersion !== void 0) { + statusReport.codeql_version = codeQlCliVersion.version; + } + const imageVersion = process.env["ImageVersion"]; + if (imageVersion) { + statusReport.runner_image_version = imageVersion; + } + return statusReport; + } catch (e) { + logger.warning( + `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` ); - return false; + if (isInTestMode()) { + throw e; + } + return void 0; } +} +var OUT_OF_DATE_MSG = "CodeQL Action is out-of-date. Please upgrade to the latest version of `codeql-action`."; +var INCOMPATIBLE_MSG = "CodeQL Action version is incompatible with the API endpoint. Please update to a compatible version of `codeql-action`."; +async function sendStatusReport(statusReport) { + setJobStatusIfUnsuccessful(statusReport.status); + const statusReportJSON = JSON.stringify(statusReport); + core9.debug(`Sending status report: ${statusReportJSON}`); if (isInTestMode()) { - logger.debug( - "In test mode. Skip uploading overlay-base database to cache." - ); - return false; - } - const databaseIsValid = await checkOverlayBaseDatabase( - codeql, - config, - logger, - "Abort uploading overlay-base database to cache" - ); - if (!databaseIsValid) { - return false; - } - await withGroupAsync("Cleaning up databases", async () => { - await codeql.databaseCleanupCluster(config, "overlay" /* Overlay */); - }); - const dbLocation = config.dbLocation; - const databaseSizeBytes = await tryGetFolderBytes(dbLocation, logger); - if (databaseSizeBytes === void 0) { - logger.warning( - "Failed to determine database size. Skip uploading overlay-base database to cache." - ); - return false; - } - if (databaseSizeBytes > OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES) { - const databaseSizeMB = Math.round(databaseSizeBytes / 1e6); - logger.warning( - `Database size (${databaseSizeMB} MB) exceeds maximum upload size (${OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB} MB). Skip uploading overlay-base database to cache.` - ); - return false; + core9.debug("In test mode. Status reports are not uploaded."); + return; } - const codeQlVersion = (await codeql.getVersion()).version; - const checkoutPath = getRequiredInput("checkout_path"); - const cacheSaveKey = await getCacheSaveKey( - config, - codeQlVersion, - checkoutPath, - logger - ); - logger.info( - `Uploading overlay-base database to Actions cache with key ${cacheSaveKey}` - ); + const nwo = getRepositoryNwo(); + const client = getApiClient(); try { - const cacheId = await waitForResultWithTimeLimit( - MAX_CACHE_OPERATION_MS3, - actionsCache3.saveCache([dbLocation], cacheSaveKey), - () => { + await client.request( + "PUT /repos/:owner/:repo/code-scanning/analysis/status", + { + owner: nwo.owner, + repo: nwo.repo, + data: statusReportJSON } ); - if (cacheId === void 0) { - logger.warning("Timed out while uploading overlay-base database"); - return false; + } catch (e) { + const httpError = asHTTPError(e); + if (httpError !== void 0) { + switch (httpError.status) { + case 403: + if (getWorkflowEventName() === "push" && process.env["GITHUB_ACTOR"] === "dependabot[bot]") { + core9.warning( + `Workflows triggered by Dependabot on the "push" event run with read-only access. Uploading CodeQL results requires write access. To use CodeQL 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/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#scanning-on-push" /* SCANNING_ON_PUSH */} for more information on how to configure these events.` + ); + } else { + core9.warning( + `This run of the CodeQL Action does not have permission to access the CodeQL Action API endpoints. This could be because the Action is running on a pull request from a fork. If not, please ensure the workflow has at least the 'security-events: read' permission. Details: ${httpError.message}` + ); + } + return; + case 404: + core9.warning(httpError.message); + return; + case 422: + if (getRequiredEnvParam("GITHUB_SERVER_URL") !== GITHUB_DOTCOM_URL) { + core9.debug(INCOMPATIBLE_MSG); + } else { + core9.debug(OUT_OF_DATE_MSG); + } + return; + } } - } catch (error3) { - logger.warning( - `Failed to upload overlay-base database to cache: ${error3 instanceof Error ? error3.message : String(error3)}` + core9.warning( + `An unexpected error occurred when sending a status report: ${getErrorMessage( + e + )}` ); - return false; } - logger.info(`Successfully uploaded overlay-base database from ${dbLocation}`); - return true; } -async function downloadOverlayBaseDatabaseFromCache(codeql, config, logger) { - const overlayDatabaseMode = config.overlayDatabaseMode; - if (overlayDatabaseMode !== "overlay" /* Overlay */) { - logger.debug( - `Overlay database mode is ${overlayDatabaseMode}. Skip downloading overlay-base database from cache.` - ); - return void 0; - } - if (!config.useOverlayDatabaseCaching) { - logger.debug( - "Overlay database caching is disabled. Skip downloading overlay-base database from cache." - ); - return void 0; - } - if (isInTestMode()) { - logger.debug( - "In test mode. Skip downloading overlay-base database from cache." - ); - return void 0; - } - const dbLocation = config.dbLocation; - const codeQlVersion = (await codeql.getVersion()).version; - const cacheRestoreKeyPrefix = await getCacheRestoreKeyPrefix( - config, - codeQlVersion - ); - logger.info( - `Looking in Actions cache for overlay-base database with restore key ${cacheRestoreKeyPrefix}` +async function createInitWithConfigStatusReport(config, initStatusReport, configFile, totalCacheSize, overlayBaseDatabaseStats, dependencyCachingResults) { + const languages = config.languages.join(","); + const paths = (config.originalUserInput.paths || []).join(","); + const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join( + "," ); - let databaseDownloadDurationMs = 0; - try { - const databaseDownloadStart = performance.now(); - const foundKey = await waitForResultWithTimeLimit( - // This ten-minute limit for the cache restore operation is mainly to - // guard against the possibility that the cache service is unresponsive - // and hangs outside the data download. - // - // Data download (which is normally the most time-consuming part of the - // restore operation) should not run long enough to hit this limit. Even - // for an extremely large 10GB database, at a download speed of 40MB/s - // (see below), the download should complete within five minutes. If we - // do hit this limit, there are likely more serious problems other than - // mere slow download speed. - // - // This is important because we don't want any ongoing file operations - // on the database directory when we do hit this limit. Hitting this - // time limit takes us to a fallback path where we re-initialize the - // database from scratch at dbLocation, and having the cache restore - // operation continue to write into dbLocation in the background would - // really mess things up. We want to hit this limit only in the case - // of a hung cache service, not just slow download speed. - MAX_CACHE_OPERATION_MS3, - actionsCache3.restoreCache( - [dbLocation], - cacheRestoreKeyPrefix, - void 0, - { - // Azure SDK download (which is the default) uses 128MB segments; see - // https://github.com/actions/toolkit/blob/main/packages/cache/README.md. - // Setting segmentTimeoutInMs to 3000 translates to segment download - // speed of about 40 MB/s, which should be achievable unless the - // download is unreliable (in which case we do want to abort). - segmentTimeoutInMs: 3e3 - } - ), - () => { - logger.info("Timed out downloading overlay-base database from cache"); - } - ); - databaseDownloadDurationMs = Math.round( - performance.now() - databaseDownloadStart - ); - if (foundKey === void 0) { - logger.info("No overlay-base database found in Actions cache"); - return void 0; - } - logger.info( - `Downloaded overlay-base database in cache with key ${foundKey}` - ); - } catch (error3) { - logger.warning( - `Failed to download overlay-base database from cache: ${error3 instanceof Error ? error3.message : String(error3)}` + const disableDefaultQueries = config.originalUserInput["disable-default-queries"] ? languages : ""; + const queries = []; + let queriesInput = getOptionalInput("queries")?.trim(); + if (queriesInput === void 0 || queriesInput.startsWith("+")) { + queries.push( + ...(config.originalUserInput.queries || []).map((q) => q.uses) ); - return void 0; } - const databaseIsValid = await checkOverlayBaseDatabase( - codeql, - config, - logger, - "Downloaded overlay-base database is invalid" - ); - if (!databaseIsValid) { - logger.warning("Downloaded overlay-base database failed validation"); - return void 0; + if (queriesInput !== void 0) { + queriesInput = queriesInput.startsWith("+") ? queriesInput.slice(1) : queriesInput; + queries.push(...queriesInput.split(",")); } - const databaseSizeBytes = await tryGetFolderBytes(dbLocation, logger); - if (databaseSizeBytes === void 0) { - logger.info( - "Filesystem error while accessing downloaded overlay-base database" - ); - return void 0; + let packs = {}; + if (Array.isArray(config.computedConfig.packs)) { + packs[config.languages[0]] = config.computedConfig.packs; + } else if (config.computedConfig.packs !== void 0) { + packs = config.computedConfig.packs; } - logger.info(`Successfully downloaded overlay-base database to ${dbLocation}`); return { - databaseSizeBytes: Math.round(databaseSizeBytes), - databaseDownloadDurationMs + ...initStatusReport, + config_file: configFile ?? "", + disable_default_queries: disableDefaultQueries, + paths, + paths_ignore: pathsIgnore, + queries: queries.join(","), + packs: JSON.stringify(packs), + trap_cache_languages: Object.keys(config.trapCaches).join(","), + trap_cache_download_size_bytes: totalCacheSize, + trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime), + overlay_base_database_download_size_bytes: overlayBaseDatabaseStats?.databaseSizeBytes, + overlay_base_database_download_duration_ms: overlayBaseDatabaseStats?.databaseDownloadDurationMs, + dependency_caching_restore_results: dependencyCachingResults, + query_filters: JSON.stringify( + config.originalUserInput["query-filters"] ?? [] + ), + registries: JSON.stringify( + parseRegistriesWithoutCredentials(getOptionalInput("registries")) ?? [] + ) }; } -async function getCacheSaveKey(config, codeQlVersion, checkoutPath, logger) { - let runId = 1; - let attemptId = 1; +async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { try { - runId = getWorkflowRunID(); - attemptId = getWorkflowRunAttempt(); + const statusReport = await createStatusReportBase( + actionName, + "failure", + actionStartedAt, + void 0, + void 0, + logger, + `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, + error3 instanceof Error ? error3.stack : void 0 + ); + if (statusReport !== void 0) { + await sendStatusReport(statusReport); + } } catch (e) { logger.warning( - `Failed to get workflow run ID or attempt ID. Reason: ${getErrorMessage(e)}` + `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` ); + if (isInTestMode()) { + throw e; + } } - const sha = await getCommitOid(checkoutPath); - const restoreKeyPrefix = await getCacheRestoreKeyPrefix( - config, - codeQlVersion - ); - return `${restoreKeyPrefix}${sha}-${runId}-${attemptId}`; } -async function getCacheRestoreKeyPrefix(config, codeQlVersion) { - return `${await getCacheKeyPrefixBase(config.languages)}${codeQlVersion}-`; -} -async function getCacheKeyPrefixBase(parsedLanguages) { - const languagesComponent = [...parsedLanguages].sort().join("_"); - const cacheKeyComponents = { - automationID: await getAutomationID() - // Add more components here as needed in the future - }; - const componentsHash = createCacheKeyHash(cacheKeyComponents); - return `${CACHE_PREFIX}-${CACHE_VERSION2}-${componentsHash}-${languagesComponent}-`; -} -async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger) { - const languages = rawLanguages.map(parseBuiltInLanguage); - if (languages.includes(void 0)) { - logger.warning( - "One or more provided languages are not recognized as built-in languages. Skipping searching for overlay-base databases in cache." - ); - return void 0; - } - const dedupedLanguages = [ - ...new Set(languages.filter((l) => l !== void 0)) - ]; - const cacheKeyPrefix = await getCacheKeyPrefixBase(dedupedLanguages); - logger.debug( - `Searching for overlay-base databases in Actions cache with prefix ${cacheKeyPrefix}` - ); - const caches = await listActionsCaches(cacheKeyPrefix); - if (caches.length === 0) { - logger.info("No overlay-base databases found in Actions cache."); - return []; - } - logger.info( - `Found ${caches.length} overlay-base ${caches.length === 1 ? "database" : "databases"} in the Actions cache.` - ); - const versionRegex = /^([\d.]+)-/; - const versionSet = /* @__PURE__ */ new Set(); - for (const cache of caches) { - if (!cache.key) continue; - const suffix = cache.key.substring(cacheKeyPrefix.length); - const match2 = suffix.match(versionRegex); - if (match2 && semver6.valid(match2[1])) { - versionSet.add(match2[1]); - } - } - if (versionSet.size === 0) { - logger.info( - "Could not parse any CodeQL versions from overlay-base database cache keys." - ); - return []; + +// src/action-common.ts +async function runInActions(action) { + const startedAt = /* @__PURE__ */ new Date(); + const logger = getActionsLogger(); + const env = getEnv(); + const actionsEnv = getActionsEnv(); + try { + await action.run({ + name: action.name, + startedAt, + logger, + env, + actions: actionsEnv + }); + } catch (error3) { + core10.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); + await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); } - const versions = [...versionSet].sort(semver6.rcompare); - logger.info( - `Found overlay databases for the following CodeQL versions in the Actions cache: ${versions.join(", ")}` - ); - return versions; } -// src/tar.ts -var import_child_process = require("child_process"); -var fs11 = __toESM(require("fs")); -var stream = __toESM(require("stream")); -var import_toolrunner = __toESM(require_toolrunner()); -var io4 = __toESM(require_io()); -var toolcache = __toESM(require_tool_cache()); -var semver7 = __toESM(require_semver2()); -var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; -var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; -async function getTarVersion() { - const tar = await io4.which("tar", true); - let stdout = ""; - const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], { - listeners: { - stdout: (data) => { - stdout += data.toString(); - } +// src/analyze.ts +var fs16 = __toESM(require("fs")); +var path15 = __toESM(require("path")); +var import_perf_hooks3 = require("perf_hooks"); +var io5 = __toESM(require_io()); + +// src/autobuild.ts +var core13 = __toESM(require_core()); + +// src/codeql.ts +var fs15 = __toESM(require("fs")); +var path14 = __toESM(require("path")); +var core12 = __toESM(require_core()); +var toolrunner3 = __toESM(require_toolrunner()); + +// src/cli-errors.ts +var SUPPORTED_PLATFORMS = [ + ["linux", "x64"], + ["win32", "x64"], + ["darwin", "x64"], + ["darwin", "arm64"] +]; +var CliError = class extends Error { + exitCode; + stderr; + constructor({ cmd, args, exitCode, stderr }) { + const prettyCommand = prettyPrintInvocation(cmd, args); + const fatalErrors = extractFatalErrors(stderr); + const autobuildErrors = extractAutobuildErrors(stderr); + let message; + if (fatalErrors) { + message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and error was: ${ensureEndsInPeriod( + fatalErrors.trim() + )} See the logs for more details.`; + } else if (autobuildErrors) { + message = `We were unable to automatically build your code. Please provide manual build steps. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information. Encountered the following error: ${autobuildErrors}`; + } else { + const lastLine = ensureEndsInPeriod( + stderr.trim().split("\n").pop()?.trim() || "n/a" + ); + message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and last log line was: ${lastLine} See the logs for more details.`; } - }).exec(); - if (exitCode !== 0) { - throw new Error("Failed to call tar --version"); + super(message); + this.exitCode = exitCode; + this.stderr = stderr; } - if (stdout.includes("GNU tar")) { - const match2 = stdout.match(/tar \(GNU tar\) ([0-9.]+)/); - if (!match2?.[1]) { - throw new Error("Failed to parse output of tar --version."); - } - return { type: "gnu", version: match2[1] }; - } else if (stdout.includes("bsdtar")) { - const match2 = stdout.match(/bsdtar ([0-9.]+)/); - if (!match2?.[1]) { - throw new Error("Failed to parse output of tar --version."); +}; +function extractFatalErrors(error3) { + const fatalErrorRegex = /.*fatal (internal )?error occurr?ed(. Details)?:/gi; + let fatalErrors = []; + let lastFatalErrorIndex; + let match2; + while ((match2 = fatalErrorRegex.exec(error3)) !== null) { + if (lastFatalErrorIndex !== void 0) { + fatalErrors.push(error3.slice(lastFatalErrorIndex, match2.index).trim()); } - return { type: "bsd", version: match2[1] }; - } else { - throw new Error("Unknown tar version"); + lastFatalErrorIndex = match2.index; } -} -async function isZstdAvailable(logger) { - const foundZstdBinary = await isBinaryAccessible("zstd", logger); - try { - const tarVersion = await getTarVersion(); - const { type, version } = tarVersion; - logger.info(`Found ${type} tar version ${version}.`); - switch (type) { - case "gnu": - return { - available: foundZstdBinary && // GNU tar only uses major and minor version numbers - semver7.gte( - semver7.coerce(version), - semver7.coerce(MIN_REQUIRED_GNU_TAR_VERSION) - ), - foundZstdBinary, - version: tarVersion - }; - case "bsd": - return { - available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain - // a patch version number. - semver7.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), - foundZstdBinary, - version: tarVersion - }; - default: - assertNever(type); + if (lastFatalErrorIndex !== void 0) { + const lastError = error3.slice(lastFatalErrorIndex).trim(); + if (fatalErrors.length === 0) { + return lastError; } - } catch (e) { - logger.warning( - `Failed to determine tar version, therefore will assume zstd is not available. The underlying error was: ${e}` - ); - return { available: false, foundZstdBinary }; + const isOneLiner = !fatalErrors.some((e) => e.includes("\n")); + if (isOneLiner) { + fatalErrors = fatalErrors.map(ensureEndsInPeriod); + } + return [ + ensureEndsInPeriod(lastError), + "Context:", + ...fatalErrors.reverse() + ].join(isOneLiner ? " " : "\n"); } + return void 0; } -async function extract(tarPath, dest, compressionMethod, tarVersion, logger) { - fs11.mkdirSync(dest, { recursive: true }); - switch (compressionMethod) { - case "gzip": - return await toolcache.extractTar(tarPath, dest); - case "zstd": { - if (!tarVersion) { - throw new Error( - "Could not determine tar version, which is required to extract a Zstandard archive." - ); - } - await extractTarZst(tarPath, dest, tarVersion, logger); - return dest; - } +function extractAutobuildErrors(error3) { + const pattern = /.*\[autobuild\] \[ERROR\] (.*)/gi; + let errorLines = [...error3.matchAll(pattern)].map((match2) => match2[1]); + if (errorLines.length > 10) { + errorLines = errorLines.slice(0, 10); + errorLines.push("(truncated)"); } + return errorLines.join("\n") || void 0; } -async function extractTarZst(tar, dest, tarVersion, logger) { - logger.debug( - `Extracting to ${dest}.${tar instanceof stream.Readable ? ` Input stream has high water mark ${tar.readableHighWaterMark}.` : ""}` - ); - try { - const args = ["-x", "--zstd", "--ignore-zeros"]; - if (tarVersion.type === "gnu") { - args.push("--warning=no-unknown-keyword"); - args.push("--overwrite"); - } - args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); - process.stdout.write(`[command]tar ${args.join(" ")} -`); - await new Promise((resolve14, reject) => { - const tarProcess = (0, import_child_process.spawn)("tar", args, { stdio: "pipe" }); - let stdout = ""; - tarProcess.stdout?.on("data", (data) => { - stdout += data.toString(); - process.stdout.write(data); - }); - let stderr = ""; - tarProcess.stderr?.on("data", (data) => { - stderr += data.toString(); - process.stdout.write(data); - }); - tarProcess.on("error", (err) => { - reject(new Error(`Error while extracting tar: ${err}`)); - }); - if (tar instanceof stream.Readable) { - tar.pipe(tarProcess.stdin).on("error", (err) => { - reject( - new Error(`Error while downloading and extracting tar: ${err}`) - ); - }); - } - tarProcess.on("exit", (code) => { - if (code !== 0) { - reject( - new CommandInvocationError( - "tar", - args, - code ?? void 0, - stdout, - stderr - ) - ); - } - resolve14(); - }); - }); - } catch (e) { - await cleanUpPath(dest, "extraction destination directory", logger); - throw e; +var cliErrorsConfig = { + ["AutobuildError" /* AutobuildError */]: { + cliErrorMessageCandidates: [ + new RegExp("We were unable to automatically build your code") + ] + }, + ["CouldNotCreateTempDir" /* CouldNotCreateTempDir */]: { + cliErrorMessageCandidates: [new RegExp("Could not create temp directory")] + }, + ["ExternalRepositoryCloneFailed" /* ExternalRepositoryCloneFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("Failed to clone external Git repository") + ] + }, + ["GradleBuildFailed" /* GradleBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("\\[autobuild\\] FAILURE: Build failed with an exception.") + ] + }, + // Version of CodeQL CLI is incompatible with this version of the CodeQL Action + ["IncompatibleWithActionVersion" /* IncompatibleWithActionVersion */]: { + cliErrorMessageCandidates: [ + new RegExp("is not compatible with this CodeQL CLI") + ] + }, + ["InitCalledTwice" /* InitCalledTwice */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Refusing to create databases .* but could not process any of it" + ) + ], + additionalErrorMessageToAppend: `Is the "init" action called twice in the same job?` + }, + ["InvalidConfigFile" /* InvalidConfigFile */]: { + cliErrorMessageCandidates: [ + new RegExp("Config file .* is not valid"), + new RegExp("The supplied config file is empty") + ] + }, + ["InvalidExternalRepoSpecifier" /* InvalidExternalRepoSpecifier */]: { + cliErrorMessageCandidates: [ + new RegExp("Specifier for external repository is invalid") + ] + }, + // Expected source location for database creation does not exist + ["InvalidSourceRoot" /* InvalidSourceRoot */]: { + cliErrorMessageCandidates: [new RegExp("Invalid source root")] + }, + ["MavenBuildFailed" /* MavenBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("\\[autobuild\\] \\[ERROR\\] Failed to execute goal") + ] + }, + ["NoBuildCommandAutodetected" /* NoBuildCommandAutodetected */]: { + cliErrorMessageCandidates: [ + new RegExp("Could not auto-detect a suitable build method") + ] + }, + ["NoBuildMethodAutodetected" /* NoBuildMethodAutodetected */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Could not detect a suitable build command for the source checkout" + ) + ] + }, + // Usually when a manual build script has failed, or if an autodetected language + // was unintended to have CodeQL analysis run on it. + ["NoSourceCodeSeen" /* NoSourceCodeSeen */]: { + exitCode: 32, + cliErrorMessageCandidates: [ + new RegExp( + "CodeQL detected code written in .* but could not process any of it" + ), + new RegExp( + "CodeQL did not detect any code written in languages supported by CodeQL" + ) + ] + }, + ["NoSupportedBuildCommandSucceeded" /* NoSupportedBuildCommandSucceeded */]: { + cliErrorMessageCandidates: [ + new RegExp("No supported build command succeeded") + ] + }, + ["NoSupportedBuildSystemDetected" /* NoSupportedBuildSystemDetected */]: { + cliErrorMessageCandidates: [ + new RegExp("No supported build system detected") + ] + }, + ["OutOfMemoryOrDisk" /* OutOfMemoryOrDisk */]: { + cliErrorMessageCandidates: [ + new RegExp("CodeQL is out of memory."), + new RegExp("out of disk"), + new RegExp("No space left on device") + ], + additionalErrorMessageToAppend: "For more information, see https://gh.io/troubleshooting-code-scanning/out-of-disk-or-memory" + }, + ["PackCannotBeFound" /* PackCannotBeFound */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Query pack .* cannot be found\\. Check the spelling of the pack\\." + ), + new RegExp( + "is not a .ql file, .qls file, a directory, or a query pack specification." + ) + ] + }, + ["PackMissingAuth" /* PackMissingAuth */]: { + cliErrorMessageCandidates: [ + new RegExp("GitHub Container registry .* 403 Forbidden"), + new RegExp( + "Do you need to specify a token to authenticate to the registry?" + ) + ] + }, + ["SwiftBuildFailed" /* SwiftBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp( + "\\[autobuilder/build\\] \\[build-command-failed\\] `autobuild` failed to run the build command" + ) + ] + }, + ["SwiftIncompatibleOs" /* SwiftIncompatibleOs */]: { + cliErrorMessageCandidates: [ + new RegExp("\\[incompatible-os\\]"), + new RegExp("Swift analysis is only supported on macOS") + ] + }, + ["UnsupportedBuildMode" /* UnsupportedBuildMode */]: { + cliErrorMessageCandidates: [ + new RegExp( + "does not support the .* build mode. Please try using one of the following build modes instead" + ) + ] + }, + ["NotFoundInRegistry" /* NotFoundInRegistry */]: { + cliErrorMessageCandidates: [ + new RegExp("'.*' not found in the registry '.*'") + ] } -} -var KNOWN_EXTENSIONS = { - "tar.gz": "gzip", - "tar.zst": "zstd" }; -function inferCompressionMethod(tarPath) { - for (const [ext2, method] of Object.entries(KNOWN_EXTENSIONS)) { - if (tarPath.endsWith(`.${ext2}`)) { - return method; +function getCliConfigCategoryIfExists(cliError) { + for (const [category, configuration] of Object.entries(cliErrorsConfig)) { + if (cliError.exitCode !== void 0 && configuration.exitCode !== void 0 && cliError.exitCode === configuration.exitCode) { + return category; + } + for (const e of configuration.cliErrorMessageCandidates) { + if (cliError.message.match(e) || cliError.stderr.match(e)) { + return category; + } } } return void 0; } - -// src/tools-download.ts -var fs12 = __toESM(require("fs")); -var os3 = __toESM(require("os")); -var path11 = __toESM(require("path")); -var import_perf_hooks2 = require("perf_hooks"); -var core9 = __toESM(require_core()); -var import_http_client = __toESM(require_lib()); -var toolcache2 = __toESM(require_tool_cache()); -var import_follow_redirects = __toESM(require_follow_redirects()); -var semver8 = __toESM(require_semver2()); -var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; -var TOOLCACHE_TOOL_NAME = "CodeQL"; -function makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs) { - return { - combinedDurationMs: downloadDurationMs + extractionDurationMs, - downloadDurationMs, - extractionDurationMs, - streamExtraction: false - }; -} -function makeStreamedToolsDownloadDurations(combinedDurationMs) { - return { - combinedDurationMs, - downloadDurationMs: void 0, - extractionDurationMs: void 0, - streamExtraction: true - }; +function isUnsupportedPlatform() { + return !SUPPORTED_PLATFORMS.some( + ([platform2, arch2]) => platform2 === process.platform && arch2 === process.arch + ); } -async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorization, headers, tarVersion, logger) { - logger.info( - `Downloading CodeQL tools from ${codeqlURL} . This may take a while.` +function getUnsupportedPlatformError(cliError) { + return new ConfigurationError( + `The CodeQL CLI does not support the platform/architecture combination of ${process.platform}/${process.arch} (see ${"https://codeql.github.com/docs/codeql-overview/system-requirements/" /* SYSTEM_REQUIREMENTS */}). The underlying error was: ${cliError.message}` ); - try { - if (compressionMethod === "zstd" && process.platform === "linux") { - logger.info(`Streaming the extraction of the CodeQL bundle.`); - const toolsInstallStart = import_perf_hooks2.performance.now(); - await downloadAndExtractZstdWithStreaming( - codeqlURL, - dest, - authorization, - headers, - tarVersion, - logger - ); - const combinedDurationMs = Math.round( - import_perf_hooks2.performance.now() - toolsInstallStart - ); - logger.info( - `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( - combinedDurationMs - )}).` - ); - return { - compressionMethod, - toolsUrl: sanitizeUrlForStatusReport(codeqlURL), - ...makeStreamedToolsDownloadDurations(combinedDurationMs) - }; - } - } catch (e) { - core9.warning( - `Failed to download and extract CodeQL bundle using streaming with error: ${getErrorMessage(e)}` - ); - core9.warning(`Falling back to downloading the bundle before extracting.`); - await cleanUpPath(dest, "CodeQL bundle", logger); +} +function wrapCliConfigurationError(cliError) { + if (isUnsupportedPlatform()) { + return getUnsupportedPlatformError(cliError); } - const toolsDownloadStart = import_perf_hooks2.performance.now(); - const archivedBundlePath = await toolcache2.downloadTool( - codeqlURL, - void 0, - authorization, - headers - ); - const downloadDurationMs = Math.round(import_perf_hooks2.performance.now() - toolsDownloadStart); - logger.info( - `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( - downloadDurationMs - )}).` - ); - let extractionDurationMs; - try { - logger.info("Extracting CodeQL bundle."); - const extractionStart = import_perf_hooks2.performance.now(); - await extract( - archivedBundlePath, - dest, - compressionMethod, - tarVersion, - logger - ); - extractionDurationMs = Math.round(import_perf_hooks2.performance.now() - extractionStart); - logger.info( - `Finished extracting CodeQL bundle to ${dest} (${formatDuration( - extractionDurationMs - )}).` - ); - } finally { - await cleanUpPath(archivedBundlePath, "CodeQL bundle archive", logger); + const cliConfigErrorCategory = getCliConfigCategoryIfExists(cliError); + if (cliConfigErrorCategory === void 0) { + return cliError; } - return { - compressionMethod, - toolsUrl: sanitizeUrlForStatusReport(codeqlURL), - ...makeDownloadFirstToolsDownloadDurations( - downloadDurationMs, - extractionDurationMs - ) - }; -} -async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { - fs12.mkdirSync(dest, { recursive: true }); - const agent = new import_http_client.HttpClient().getAgent(codeqlURL); - headers = Object.assign( - { "User-Agent": "CodeQL Action" }, - authorization ? { authorization } : {}, - headers - ); - const response = await new Promise( - (resolve14) => import_follow_redirects.https.get( - codeqlURL, - { - headers, - // Increase the high water mark to improve performance. - highWaterMark: STREAMING_HIGH_WATERMARK_BYTES, - // Use the agent to respect proxy settings. - agent - }, - (r) => resolve14(r) - ) - ); - if (response.statusCode !== 200) { - throw new Error( - `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.` - ); + let errorMessageBuilder = cliError.message; + const additionalErrorMessageToAppend = cliErrorsConfig[cliConfigErrorCategory].additionalErrorMessageToAppend; + if (additionalErrorMessageToAppend !== void 0) { + errorMessageBuilder = `${errorMessageBuilder} ${additionalErrorMessageToAppend}`; } - await extractTarZst(response, dest, tarVersion, logger); + return new ConfigurationError(errorMessageBuilder); } -function getToolcacheDirectory(version) { - return path11.join( - getRequiredEnvParam("RUNNER_TOOL_CACHE"), - TOOLCACHE_TOOL_NAME, - semver8.clean(version) || version, - os3.arch() || "" - ); + +// src/setup-codeql.ts +var fs13 = __toESM(require("fs")); +var path12 = __toESM(require("path")); +var toolcache3 = __toESM(require_tool_cache()); +var import_fast_deep_equal = __toESM(require_fast_deep_equal()); +var semver9 = __toESM(require_semver2()); + +// node_modules/uuid/dist-node/stringify.js +var byteToHex = []; +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); } -function writeToolcacheMarkerFile(extractedPath, logger) { - const markerFilePath = `${extractedPath}.complete`; - fs12.writeFileSync(markerFilePath, ""); - logger.info(`Created toolcache marker file ${markerFilePath}`); +function unsafeStringify(arr, offset = 0) { + return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); } -function sanitizeUrlForStatusReport(url2) { - return ["github/codeql-action", "dsp-testing/codeql-cli-nightlies"].some( - (repo) => url2.startsWith(`https://github.com/${repo}/releases/download/`) - ) ? url2 : "sanitized-value"; + +// node_modules/uuid/dist-node/rng.js +var rnds8 = new Uint8Array(16); +function rng() { + return crypto.getRandomValues(rnds8); } -// src/setup-codeql.ts -var CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action"; -var CODEQL_NIGHTLIES_REPOSITORY_OWNER = "dsp-testing"; -var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; -var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; -var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; -var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension(compressionMethod) { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - assertNever(compressionMethod); +// node_modules/uuid/dist-node/v4.js +function v4(options, buf, offset) { + if (!buf && !options && crypto.randomUUID) { + return crypto.randomUUID(); } + return _v4(options, buf, offset); } -function getCodeQLBundleName(compressionMethod) { - const extension = getCodeQLBundleExtension(compressionMethod); - let platform2; - if (process.platform === "win32") { - platform2 = "win64"; - } else if (process.platform === "linux") { - platform2 = "linux64"; - } else if (process.platform === "darwin") { - platform2 = "osx64"; - } else { - return `codeql-bundle${extension}`; +function _v4(options, buf, offset) { + options = options || {}; + const rnds = options.random ?? options.rng?.() ?? rng(); + if (rnds.length < 16) { + throw new Error("Random bytes length must be >= 16"); } - return `codeql-bundle-${platform2}${extension}`; + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + if (offset < 0 || offset + 16 > buf.length) { + throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); + } + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); } -function getCodeQLActionRepository(logger) { - if (isRunningLocalAction()) { - logger.info( - "The CodeQL Action is checked out locally. Using the default CodeQL Action repository." +var v4_default = v4; + +// src/overlay/caching.ts +var fs10 = __toESM(require("fs")); +var actionsCache3 = __toESM(require_cache4()); +var semver6 = __toESM(require_semver2()); +var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; +var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6; +var CACHE_VERSION2 = 1; +var CACHE_PREFIX = "codeql-overlay-base-database"; +var MAX_CACHE_OPERATION_MS3 = 6e5; +async function checkOverlayBaseDatabase(codeql, config, logger, warningPrefix) { + const baseDatabaseOidsFilePath = getBaseDatabaseOidsFilePath(config); + if (!fs10.existsSync(baseDatabaseOidsFilePath)) { + logger.warning( + `${warningPrefix}: ${baseDatabaseOidsFilePath} does not exist` ); - return CODEQL_DEFAULT_ACTION_REPOSITORY; + return false; } - return getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); -} -async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod, logger) { - const codeQLActionRepository = getCodeQLActionRepository(logger); - const potentialDownloadSources = [ - // This GitHub instance, and this Action. - [apiDetails.url, codeQLActionRepository], - // This GitHub instance, and the canonical Action. - [apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY], - // GitHub.com, and the canonical Action. - [GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY] - ]; - const uniqueDownloadSources = potentialDownloadSources.filter( - (source, index2, self2) => { - return !self2.slice(0, index2).some((other) => (0, import_fast_deep_equal.default)(source, other)); - } - ); - const codeQLBundleName = getCodeQLBundleName(compressionMethod); - for (const downloadSource of uniqueDownloadSources) { - const [apiURL, repository] = downloadSource; - if (apiURL === GITHUB_DOTCOM_URL && repository === CODEQL_DEFAULT_ACTION_REPOSITORY) { - break; - } - const [repositoryOwner, repositoryName] = repository.split("/"); + for (const language of config.languages) { + const dbPath = getCodeQLDatabasePath(config, language); try { - const release2 = await getApiClient().rest.repos.getReleaseByTag({ - owner: repositoryOwner, - repo: repositoryName, - tag: tagName - }); - for (const asset of release2.data.assets) { - if (asset.name === codeQLBundleName) { - logger.info( - `Found CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} with URL ${asset.url}.` - ); - return asset.url; - } + const resolveDatabaseOutput = await codeql.resolveDatabase(dbPath); + if (resolveDatabaseOutput === void 0 || !("overlayBaseSpecifier" in resolveDatabaseOutput)) { + logger.info(`${warningPrefix}: no overlayBaseSpecifier defined`); + return false; + } else { + logger.debug( + `Overlay base specifier for ${language} overlay-base database found: ${resolveDatabaseOutput.overlayBaseSpecifier}` + ); } } catch (e) { - logger.info( - `Looked for CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} but got error ${e}.` - ); + logger.warning(`${warningPrefix}: failed to resolve database: ${e}`); + return false; } } - return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; -} -function tryGetBundleVersionFromTagName(tagName, logger) { - const match2 = tagName.match(/^codeql-bundle-(.*)$/); - if (match2 === null || match2.length < 2) { - logger.debug(`Could not determine bundle version from tag ${tagName}.`); - return void 0; - } - return match2[1]; + return true; } -function tryGetTagNameFromUrl(url2, logger) { - const matches = [...url2.matchAll(/\/(codeql-bundle-[^/]*)\//g)]; - if (matches.length === 0) { - logger.debug(`Could not determine tag name for URL ${url2}.`); - return void 0; - } - const match2 = matches[matches.length - 1]; - if (match2?.length !== 2) { +async function cleanupAndUploadOverlayBaseDatabaseToCache(codeql, config, logger) { + const overlayDatabaseMode = config.overlayDatabaseMode; + if (overlayDatabaseMode !== "overlay-base" /* OverlayBase */) { logger.debug( - `Could not determine tag name for URL ${url2}. Matched ${JSON.stringify( - match2 - )}.` + `Overlay database mode is ${overlayDatabaseMode}. Skip uploading overlay-base database to cache.` ); - return void 0; + return false; } - return match2[1]; -} -function convertToSemVer(version, logger) { - if (!semver9.valid(version)) { + if (!config.useOverlayDatabaseCaching) { logger.debug( - `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` + "Overlay database caching is disabled. Skip uploading overlay-base database to cache." ); - version = `0.0.0-${version}`; - } - const s = semver9.clean(version); - if (!s) { - throw new Error(`Bundle version ${version} is not in SemVer format.`); + return false; } - return s; -} -async function findOverridingToolsInCache(humanReadableVersion, logger) { - const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ - folder: toolcache3.find("CodeQL", version), - version - })).filter(({ folder }) => fs13.existsSync(path12.join(folder, "pinned-version"))); - if (candidates.length === 1) { - const candidate = candidates[0]; - logger.debug( - `CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.` - ); - return { - codeqlFolder: candidate.folder, - sourceType: "toolcache", - toolsVersion: candidate.version - }; - } else if (candidates.length === 0) { + if (isInTestMode()) { logger.debug( - "Did not find any candidate pinned versions of the CodeQL tools in the toolcache." + "In test mode. Skip uploading overlay-base database to cache." ); - } else { - logger.debug( - "Could not use CodeQL tools from the toolcache since more than one candidate pinned version was found in the toolcache." + return false; + } + const databaseIsValid = await checkOverlayBaseDatabase( + codeql, + config, + logger, + "Abort uploading overlay-base database to cache" + ); + if (!databaseIsValid) { + return false; + } + await withGroupAsync("Cleaning up databases", async () => { + await codeql.databaseCleanupCluster(config, "overlay" /* Overlay */); + }); + const dbLocation = config.dbLocation; + const databaseSizeBytes = await tryGetFolderBytes(dbLocation, logger); + if (databaseSizeBytes === void 0) { + logger.warning( + "Failed to determine database size. Skip uploading overlay-base database to cache." ); + return false; } - return void 0; -} -async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, rawLanguages, features, logger) { - if (rawLanguages === void 0 || rawLanguages.length === 0) { - return []; + if (databaseSizeBytes > OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES) { + const databaseSizeMB = Math.round(databaseSizeBytes / 1e6); + logger.warning( + `Database size (${databaseSizeMB} MB) exceeds maximum upload size (${OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB} MB). Skip uploading overlay-base database to cache.` + ); + return false; } - const isEnabled = await features.getValue( - "overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */ + const codeQlVersion = (await codeql.getVersion()).version; + const checkoutPath = getRequiredInput("checkout_path"); + const cacheSaveKey = await getCacheSaveKey( + config, + codeQlVersion, + checkoutPath, + logger + ); + logger.info( + `Uploading overlay-base database to Actions cache with key ${cacheSaveKey}` ); - const isDryRun = !isEnabled && await features.getValue("overlay_analysis_match_codeql_version_dry_run" /* OverlayAnalysisMatchCodeqlVersionDryRun */); - if (!isEnabled && !isDryRun) { - return []; - } - let cachedVersions; try { - cachedVersions = await getCodeQlVersionsForOverlayBaseDatabases( - rawLanguages, - logger + const cacheId = await waitForResultWithTimeLimit( + MAX_CACHE_OPERATION_MS3, + actionsCache3.saveCache([dbLocation], cacheSaveKey), + () => { + } ); - } catch (e) { + if (cacheId === void 0) { + logger.warning("Timed out while uploading overlay-base database"); + return false; + } + } catch (error3) { logger.warning( - `Could not list overlay-base databases in the Actions cache while choosing a default CodeQL CLI version, falling back to the highest enabled version. Details: ${getErrorMessage(e)}` + `Failed to upload overlay-base database to cache: ${error3 instanceof Error ? error3.message : String(error3)}` ); - return []; - } - if (cachedVersions === void 0 || cachedVersions.length === 0) { - return []; + return false; } - const cachedVersionsSet = new Set(cachedVersions); - const overlayVersions = defaultCliVersion.enabledVersions.filter( - (v) => cachedVersionsSet.has(v.cliVersion) - ); - if (overlayVersions.length === 0) { - return []; + logger.info(`Successfully uploaded overlay-base database from ${dbLocation}`); + return true; +} +async function downloadOverlayBaseDatabaseFromCache(codeql, config, logger) { + const overlayDatabaseMode = config.overlayDatabaseMode; + if (overlayDatabaseMode !== "overlay" /* Overlay */) { + logger.debug( + `Overlay database mode is ${overlayDatabaseMode}. Skip downloading overlay-base database from cache.` + ); + return void 0; } - const isCachedVersionDifferent = overlayVersions[0].cliVersion !== defaultCliVersion.enabledVersions[0].cliVersion; - if (isCachedVersionDifferent) { - addNoLanguageDiagnostic( - void 0, - makeTelemetryDiagnostic( - "codeql-action/overlay-aware-default-codeql-version", - "Overlay-aware default CodeQL version selection", - { - cachedVersions, - enabledVersions: defaultCliVersion.enabledVersions.map( - (v) => v.cliVersion - ), - isDryRun, - overlayAwareVersion: overlayVersions[0].cliVersion - } - ) + if (!config.useOverlayDatabaseCaching) { + logger.debug( + "Overlay database caching is disabled. Skip downloading overlay-base database from cache." ); + return void 0; } - if (isDryRun) { + if (isInTestMode()) { logger.debug( - `Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.` + "In test mode. Skip downloading overlay-base database from cache." ); - return []; + return void 0; } - return overlayVersions; -} -async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { - if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) { - return defaultCliVersion.enabledVersions[0]; + const dbLocation = config.dbLocation; + const codeQlVersion = (await codeql.getVersion()).version; + const cacheRestoreKeyPrefix = await getCacheRestoreKeyPrefix( + config, + codeQlVersion + ); + logger.info( + `Looking in Actions cache for overlay-base database with restore key ${cacheRestoreKeyPrefix}` + ); + let databaseDownloadDurationMs = 0; + try { + const databaseDownloadStart = performance.now(); + const foundKey = await waitForResultWithTimeLimit( + // This ten-minute limit for the cache restore operation is mainly to + // guard against the possibility that the cache service is unresponsive + // and hangs outside the data download. + // + // Data download (which is normally the most time-consuming part of the + // restore operation) should not run long enough to hit this limit. Even + // for an extremely large 10GB database, at a download speed of 40MB/s + // (see below), the download should complete within five minutes. If we + // do hit this limit, there are likely more serious problems other than + // mere slow download speed. + // + // This is important because we don't want any ongoing file operations + // on the database directory when we do hit this limit. Hitting this + // time limit takes us to a fallback path where we re-initialize the + // database from scratch at dbLocation, and having the cache restore + // operation continue to write into dbLocation in the background would + // really mess things up. We want to hit this limit only in the case + // of a hung cache service, not just slow download speed. + MAX_CACHE_OPERATION_MS3, + actionsCache3.restoreCache( + [dbLocation], + cacheRestoreKeyPrefix, + void 0, + { + // Azure SDK download (which is the default) uses 128MB segments; see + // https://github.com/actions/toolkit/blob/main/packages/cache/README.md. + // Setting segmentTimeoutInMs to 3000 translates to segment download + // speed of about 40 MB/s, which should be achievable unless the + // download is unreliable (in which case we do want to abort). + segmentTimeoutInMs: 3e3 + } + ), + () => { + logger.info("Timed out downloading overlay-base database from cache"); + } + ); + databaseDownloadDurationMs = Math.round( + performance.now() - databaseDownloadStart + ); + if (foundKey === void 0) { + logger.info("No overlay-base database found in Actions cache"); + return void 0; + } + logger.info( + `Downloaded overlay-base database in cache with key ${foundKey}` + ); + } catch (error3) { + logger.warning( + `Failed to download overlay-base database from cache: ${error3 instanceof Error ? error3.message : String(error3)}` + ); + return void 0; } - const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases( - defaultCliVersion, - rawLanguages, - features, - logger + const databaseIsValid = await checkOverlayBaseDatabase( + codeql, + config, + logger, + "Downloaded overlay-base database is invalid" ); - if (overlayVersions.length > 0) { + if (!databaseIsValid) { + logger.warning("Downloaded overlay-base database failed validation"); + return void 0; + } + const databaseSizeBytes = await tryGetFolderBytes(dbLocation, logger); + if (databaseSizeBytes === void 0) { logger.info( - `Using CodeQL version ${overlayVersions[0].cliVersion} since this is the highest enabled version that has a cached overlay-base database.` + "Filesystem error while accessing downloaded overlay-base database" ); - return overlayVersions[0]; + return void 0; } - return defaultCliVersion.enabledVersions[0]; + logger.info(`Successfully downloaded overlay-base database to ${dbLocation}`); + return { + databaseSizeBytes: Math.round(databaseSizeBytes), + databaseDownloadDurationMs + }; } -async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { - if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { - logger.info(`Using CodeQL CLI from local path ${toolsInput}`); - const compressionMethod2 = inferCompressionMethod(toolsInput); - if (compressionMethod2 === void 0) { - throw new ConfigurationError( - `Could not infer compression method from path ${toolsInput}. Please specify a path ending in '.tar.gz' or '.tar.zst'.` - ); - } - return { - codeqlTarPath: toolsInput, - compressionMethod: compressionMethod2, - sourceType: "local", - toolsVersion: "local" - }; +async function getCacheSaveKey(config, codeQlVersion, checkoutPath, logger) { + let runId = 1; + let attemptId = 1; + try { + runId = getWorkflowRunID(); + attemptId = getWorkflowRunAttempt(); + } catch (e) { + logger.warning( + `Failed to get workflow run ID or attempt ID. Reason: ${getErrorMessage(e)}` + ); } - let cliVersion2; - let tagName; - let url2; - const canForceNightlyWithFF = isDynamicWorkflow() || isInTestMode(); - const forceNightlyValueFF = await features.getValue("force_nightly" /* ForceNightly */); - const forceNightly = forceNightlyValueFF && canForceNightlyWithFF; - const nightlyRequestedByToolsInput = toolsInput !== void 0 && CODEQL_NIGHTLY_TOOLS_INPUTS.includes(toolsInput); - if (forceNightly || nightlyRequestedByToolsInput) { - if (forceNightly) { - logger.info( - `Using the latest CodeQL CLI nightly, as forced by the ${"force_nightly" /* ForceNightly */} feature flag.` - ); - addNoLanguageDiagnostic( - void 0, - makeDiagnostic( - "codeql-action/forced-nightly-cli", - "A nightly release of CodeQL was used", - { - markdownMessage: "GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release.\n\nNightly releases do not undergo the same validation as regular releases and may lead to analysis instability.\n\nIf use of a nightly CodeQL release for this analysis is unexpected, please contact GitHub support.", - visibility: { - cliSummaryTable: true, - statusPage: true, - telemetry: true - }, - severity: "note" - } - ) - ); - } else { - logger.info( - `Using the latest CodeQL CLI nightly, as requested by 'tools: ${toolsInput}'.` - ); + const sha = await getCommitOid(checkoutPath); + const restoreKeyPrefix = await getCacheRestoreKeyPrefix( + config, + codeQlVersion + ); + return `${restoreKeyPrefix}${sha}-${runId}-${attemptId}`; +} +async function getCacheRestoreKeyPrefix(config, codeQlVersion) { + return `${await getCacheKeyPrefixBase(config.languages)}${codeQlVersion}-`; +} +async function getCacheKeyPrefixBase(parsedLanguages) { + const languagesComponent = [...parsedLanguages].sort().join("_"); + const cacheKeyComponents = { + automationID: await getAutomationID() + // Add more components here as needed in the future + }; + const componentsHash = createCacheKeyHash(cacheKeyComponents); + return `${CACHE_PREFIX}-${CACHE_VERSION2}-${componentsHash}-${languagesComponent}-`; +} +async function getCodeQlVersionsForOverlayBaseDatabases(rawLanguages, logger) { + const languages = rawLanguages.map(parseBuiltInLanguage); + if (languages.includes(void 0)) { + logger.warning( + "One or more provided languages are not recognized as built-in languages. Skipping searching for overlay-base databases in cache." + ); + return void 0; + } + const dedupedLanguages = [ + ...new Set(languages.filter((l) => l !== void 0)) + ]; + const cacheKeyPrefix = await getCacheKeyPrefixBase(dedupedLanguages); + logger.debug( + `Searching for overlay-base databases in Actions cache with prefix ${cacheKeyPrefix}` + ); + const caches = await listActionsCaches(cacheKeyPrefix); + if (caches.length === 0) { + logger.info("No overlay-base databases found in Actions cache."); + return []; + } + logger.info( + `Found ${caches.length} overlay-base ${caches.length === 1 ? "database" : "databases"} in the Actions cache.` + ); + const versionRegex = /^([\d.]+)-/; + const versionSet = /* @__PURE__ */ new Set(); + for (const cache of caches) { + if (!cache.key) continue; + const suffix = cache.key.substring(cacheKeyPrefix.length); + const match2 = suffix.match(versionRegex); + if (match2 && semver6.valid(match2[1])) { + versionSet.add(match2[1]); } - toolsInput = await getNightlyToolsUrl(logger); } - const forceShippedTools = toolsInput && CODEQL_BUNDLE_VERSION_ALIAS.includes(toolsInput); - if (forceShippedTools) { - cliVersion2 = cliVersion; - tagName = bundleVersion; + if (versionSet.size === 0) { logger.info( - `'tools: ${toolsInput}' was requested, so using CodeQL version ${cliVersion2}, the version shipped with the Action.` - ); - if (toolsInput === "latest") { - logger.warning( - "`tools: latest` has been renamed to `tools: linked`, but the old name is still supported. No action is required." - ); - } - } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { - let latestToolcacheVersion; - const allowToolcacheValueFF = await features.getValue( - "allow_toolcache_input" /* AllowToolcacheInput */ + "Could not parse any CodeQL versions from overlay-base database cache keys." ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); - if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); - latestToolcacheVersion = getLatestToolcacheVersion(logger); - if (latestToolcacheVersion) { - cliVersion2 = latestToolcacheVersion; + return []; + } + const versions = [...versionSet].sort(semver6.rcompare); + logger.info( + `Found overlay databases for the following CodeQL versions in the Actions cache: ${versions.join(", ")}` + ); + return versions; +} + +// src/tar.ts +var import_child_process = require("child_process"); +var fs11 = __toESM(require("fs")); +var stream = __toESM(require("stream")); +var import_toolrunner = __toESM(require_toolrunner()); +var io4 = __toESM(require_io()); +var toolcache = __toESM(require_tool_cache()); +var semver7 = __toESM(require_semver2()); +var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; +var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; +async function getTarVersion() { + const tar = await io4.which("tar", true); + let stdout = ""; + const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], { + listeners: { + stdout: (data) => { + stdout += data.toString(); } } - if (latestToolcacheVersion === void 0) { - if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); - } else { - if (allowToolcacheValueFF) { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); - } else { - logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` - ); - } - } - const version = await resolveDefaultCliVersion( - defaultCliVersion, - rawLanguages, - useOverlayAwareDefaultCliVersion, - features, - logger - ); - cliVersion2 = version.cliVersion; - tagName = version.tagName; + }).exec(); + if (exitCode !== 0) { + throw new Error("Failed to call tar --version"); + } + if (stdout.includes("GNU tar")) { + const match2 = stdout.match(/tar \(GNU tar\) ([0-9.]+)/); + if (!match2?.[1]) { + throw new Error("Failed to parse output of tar --version."); } - } else if (toolsInput !== void 0) { - tagName = tryGetTagNameFromUrl(toolsInput, logger); - url2 = toolsInput; - if (tagName) { - const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger); - if (bundleVersion3 && semver9.valid(bundleVersion3)) { - cliVersion2 = convertToSemVer(bundleVersion3, logger); - } + return { type: "gnu", version: match2[1] }; + } else if (stdout.includes("bsdtar")) { + const match2 = stdout.match(/bsdtar ([0-9.]+)/); + if (!match2?.[1]) { + throw new Error("Failed to parse output of tar --version."); } + return { type: "bsd", version: match2[1] }; } else { - const version = await resolveDefaultCliVersion( - defaultCliVersion, - rawLanguages, - useOverlayAwareDefaultCliVersion, - features, - logger + throw new Error("Unknown tar version"); + } +} +async function isZstdAvailable(logger) { + const foundZstdBinary = await isBinaryAccessible("zstd", logger); + try { + const tarVersion = await getTarVersion(); + const { type, version } = tarVersion; + logger.info(`Found ${type} tar version ${version}.`); + switch (type) { + case "gnu": + return { + available: foundZstdBinary && // GNU tar only uses major and minor version numbers + semver7.gte( + semver7.coerce(version), + semver7.coerce(MIN_REQUIRED_GNU_TAR_VERSION) + ), + foundZstdBinary, + version: tarVersion + }; + case "bsd": + return { + available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain + // a patch version number. + semver7.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), + foundZstdBinary, + version: tarVersion + }; + default: + assertNever(type); + } + } catch (e) { + logger.warning( + `Failed to determine tar version, therefore will assume zstd is not available. The underlying error was: ${e}` ); - cliVersion2 = version.cliVersion; - tagName = version.tagName; + return { available: false, foundZstdBinary }; } - const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger); - const humanReadableVersion = cliVersion2 ?? (bundleVersion2 && convertToSemVer(bundleVersion2, logger)) ?? tagName ?? url2 ?? "unknown"; +} +async function extract(tarPath, dest, compressionMethod, tarVersion, logger) { + fs11.mkdirSync(dest, { recursive: true }); + switch (compressionMethod) { + case "gzip": + return await toolcache.extractTar(tarPath, dest); + case "zstd": { + if (!tarVersion) { + throw new Error( + "Could not determine tar version, which is required to extract a Zstandard archive." + ); + } + await extractTarZst(tarPath, dest, tarVersion, logger); + return dest; + } + } +} +async function extractTarZst(tar, dest, tarVersion, logger) { logger.debug( - `Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.` + `Extracting to ${dest}.${tar instanceof stream.Readable ? ` Input stream has high water mark ${tar.readableHighWaterMark}.` : ""}` ); - let codeqlFolder; - if (cliVersion2) { - codeqlFolder = toolcache3.find("CodeQL", cliVersion2); - if (!codeqlFolder) { - logger.debug( - `Didn't find a version of the CodeQL tools in the toolcache with a version number exactly matching ${cliVersion2}.` - ); - const allVersions = toolcache3.findAllVersions("CodeQL"); - logger.debug( - `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( - allVersions - )}.` - ); - const candidateVersions = allVersions.filter( - (version) => version.startsWith(`${cliVersion2}-`) - ); - if (candidateVersions.length === 1) { - logger.debug( - `Exactly one version of the CodeQL tools starting with ${cliVersion2} found in the toolcache, using that.` - ); - codeqlFolder = toolcache3.find("CodeQL", candidateVersions[0]); - } else if (candidateVersions.length === 0) { - logger.debug( - `Didn't find any versions of the CodeQL tools starting with ${cliVersion2} in the toolcache. Trying next fallback method.` - ); - } else { - logger.warning( - `Found ${candidateVersions.length} versions of the CodeQL tools starting with ${cliVersion2} in the toolcache, but at most one was expected.` - ); - logger.debug("Trying next fallback method."); - } + try { + const args = ["-x", "--zstd", "--ignore-zeros"]; + if (tarVersion.type === "gnu") { + args.push("--warning=no-unknown-keyword"); + args.push("--overwrite"); } + args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); + process.stdout.write(`[command]tar ${args.join(" ")} +`); + await new Promise((resolve14, reject) => { + const tarProcess = (0, import_child_process.spawn)("tar", args, { stdio: "pipe" }); + let stdout = ""; + tarProcess.stdout?.on("data", (data) => { + stdout += data.toString(); + process.stdout.write(data); + }); + let stderr = ""; + tarProcess.stderr?.on("data", (data) => { + stderr += data.toString(); + process.stdout.write(data); + }); + tarProcess.on("error", (err) => { + reject(new Error(`Error while extracting tar: ${err}`)); + }); + if (tar instanceof stream.Readable) { + tar.pipe(tarProcess.stdin).on("error", (err) => { + reject( + new Error(`Error while downloading and extracting tar: ${err}`) + ); + }); + } + tarProcess.on("exit", (code) => { + if (code !== 0) { + reject( + new CommandInvocationError( + "tar", + args, + code ?? void 0, + stdout, + stderr + ) + ); + } + resolve14(); + }); + }); + } catch (e) { + await cleanUpPath(dest, "extraction destination directory", logger); + throw e; } - if (!codeqlFolder && tagName) { - const fallbackVersion = await tryGetFallbackToolcacheVersion( - cliVersion2, - tagName, - logger - ); - if (fallbackVersion) { - codeqlFolder = toolcache3.find("CodeQL", fallbackVersion); - } else { - logger.debug( - `Could not determine a fallback toolcache version number for CodeQL tools version ${humanReadableVersion}.` - ); +} +var KNOWN_EXTENSIONS = { + "tar.gz": "gzip", + "tar.zst": "zstd" +}; +function inferCompressionMethod(tarPath) { + for (const [ext2, method] of Object.entries(KNOWN_EXTENSIONS)) { + if (tarPath.endsWith(`.${ext2}`)) { + return method; } } - if (codeqlFolder) { - logger.info( - `Found CodeQL tools version ${humanReadableVersion} in the toolcache.` - ); - } else { - logger.info( - `Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.` - ); - } - if (codeqlFolder) { - if (cliVersion2) { + return void 0; +} + +// src/tools-download.ts +var fs12 = __toESM(require("fs")); +var os4 = __toESM(require("os")); +var path11 = __toESM(require("path")); +var import_perf_hooks2 = require("perf_hooks"); +var core11 = __toESM(require_core()); +var import_http_client = __toESM(require_lib()); +var toolcache2 = __toESM(require_tool_cache()); +var import_follow_redirects = __toESM(require_follow_redirects()); +var semver8 = __toESM(require_semver2()); +var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; +var TOOLCACHE_TOOL_NAME = "CodeQL"; +function makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs) { + return { + combinedDurationMs: downloadDurationMs + extractionDurationMs, + downloadDurationMs, + extractionDurationMs, + streamExtraction: false + }; +} +function makeStreamedToolsDownloadDurations(combinedDurationMs) { + return { + combinedDurationMs, + downloadDurationMs: void 0, + extractionDurationMs: void 0, + streamExtraction: true + }; +} +async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorization, headers, tarVersion, logger) { + logger.info( + `Downloading CodeQL tools from ${codeqlURL} . This may take a while.` + ); + try { + if (compressionMethod === "zstd" && process.platform === "linux") { + logger.info(`Streaming the extraction of the CodeQL bundle.`); + const toolsInstallStart = import_perf_hooks2.performance.now(); + await downloadAndExtractZstdWithStreaming( + codeqlURL, + dest, + authorization, + headers, + tarVersion, + logger + ); + const combinedDurationMs = Math.round( + import_perf_hooks2.performance.now() - toolsInstallStart + ); logger.info( - `Using CodeQL CLI version ${cliVersion2} from toolcache at ${codeqlFolder}` + `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( + combinedDurationMs + )}).` ); - } else { - logger.info(`Using CodeQL CLI from toolcache at ${codeqlFolder}`); + return { + compressionMethod, + toolsUrl: sanitizeUrlForStatusReport(codeqlURL), + ...makeStreamedToolsDownloadDurations(combinedDurationMs) + }; } - return { - codeqlFolder, - sourceType: "toolcache", - toolsVersion: cliVersion2 ?? humanReadableVersion - }; - } - if (variant === "GitHub Enterprise Server" /* GHES */ && !forceShippedTools && !toolsInput) { - const result = await findOverridingToolsInCache( - humanReadableVersion, - logger + } catch (e) { + core11.warning( + `Failed to download and extract CodeQL bundle using streaming with error: ${getErrorMessage(e)}` ); - if (result !== void 0) { - return result; - } + core11.warning(`Falling back to downloading the bundle before extracting.`); + await cleanUpPath(dest, "CodeQL bundle", logger); } - let compressionMethod; - if (!url2) { - compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; - url2 = await getCodeQLBundleDownloadURL( - tagName, - apiDetails, + const toolsDownloadStart = import_perf_hooks2.performance.now(); + const archivedBundlePath = await toolcache2.downloadTool( + codeqlURL, + void 0, + authorization, + headers + ); + const downloadDurationMs = Math.round(import_perf_hooks2.performance.now() - toolsDownloadStart); + logger.info( + `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( + downloadDurationMs + )}).` + ); + let extractionDurationMs; + try { + logger.info("Extracting CodeQL bundle."); + const extractionStart = import_perf_hooks2.performance.now(); + await extract( + archivedBundlePath, + dest, compressionMethod, + tarVersion, logger ); - } else { - const method = inferCompressionMethod(url2); - if (method === void 0) { - throw new ConfigurationError( - `Could not infer compression method from URL ${url2}. Please specify a URL ending in '.tar.gz' or '.tar.zst'.` - ); - } - compressionMethod = method; - } - if (cliVersion2) { - logger.info(`Using CodeQL CLI version ${cliVersion2} sourced from ${url2} .`); - } else { - logger.info(`Using CodeQL CLI sourced from ${url2} .`); + extractionDurationMs = Math.round(import_perf_hooks2.performance.now() - extractionStart); + logger.info( + `Finished extracting CodeQL bundle to ${dest} (${formatDuration( + extractionDurationMs + )}).` + ); + } finally { + await cleanUpPath(archivedBundlePath, "CodeQL bundle archive", logger); } return { - bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger), - cliVersion: cliVersion2, - codeqlURL: url2, compressionMethod, - sourceType: "download", - toolsVersion: cliVersion2 ?? humanReadableVersion + toolsUrl: sanitizeUrlForStatusReport(codeqlURL), + ...makeDownloadFirstToolsDownloadDurations( + downloadDurationMs, + extractionDurationMs + ) }; } -async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) { - const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger); - if (!bundleVersion2) { - return void 0; - } - const fallbackVersion = convertToSemVer(bundleVersion2, logger); - logger.debug( - `Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ${cliVersion2 ?? tagName}.` - ); - return fallbackVersion; -} -var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVersion, maybeCliVersion, apiDetails, tarVersion, tempDir, logger) { - const parsedCodeQLURL = new URL(codeqlURL); - const searchParams = new URLSearchParams(parsedCodeQLURL.search); - const headers = { - accept: "application/octet-stream" - }; - let authorization = void 0; - if (searchParams.has("token")) { - logger.debug("CodeQL tools URL contains an authorization token."); - } else { - authorization = getAuthorizationHeaderFor( - logger, - apiDetails, - codeqlURL - ); - } - const toolcacheInfo = getToolcacheDestinationInfo( - maybeBundleVersion, - maybeCliVersion, - logger +async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { + fs12.mkdirSync(dest, { recursive: true }); + const agent = new import_http_client.HttpClient().getAgent(codeqlURL); + headers = Object.assign( + { "User-Agent": "CodeQL Action" }, + authorization ? { authorization } : {}, + headers ); - const extractedBundlePath = toolcacheInfo?.path ?? getTempExtractionDir(tempDir); - const statusReport = await downloadAndExtract( - codeqlURL, - compressionMethod, - extractedBundlePath, - authorization, - { "User-Agent": "CodeQL Action", ...headers }, - tarVersion, - logger + const response = await new Promise( + (resolve14) => import_follow_redirects.https.get( + codeqlURL, + { + headers, + // Increase the high water mark to improve performance. + highWaterMark: STREAMING_HIGH_WATERMARK_BYTES, + // Use the agent to respect proxy settings. + agent + }, + (r) => resolve14(r) + ) ); - if (!toolcacheInfo) { - logger.debug( - `Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.` + if (response.statusCode !== 200) { + throw new Error( + `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.` ); - return { - codeqlFolder: extractedBundlePath, - statusReport, - toolsVersion: maybeCliVersion ?? "unknown" - }; } - writeToolcacheMarkerFile(toolcacheInfo.path, logger); - return { - codeqlFolder: extractedBundlePath, - statusReport, - toolsVersion: maybeCliVersion ?? toolcacheInfo.version - }; -}; -function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) { - if (maybeBundleVersion) { - const version = getCanonicalToolcacheVersion( - maybeCliVersion, - maybeBundleVersion, - logger - ); - return { - path: getToolcacheDirectory(version), - version - }; + await extractTarZst(response, dest, tarVersion, logger); +} +function getToolcacheDirectory(version) { + return path11.join( + getRequiredEnvParam("RUNNER_TOOL_CACHE"), + TOOLCACHE_TOOL_NAME, + semver8.clean(version) || version, + os4.arch() || "" + ); +} +function writeToolcacheMarkerFile(extractedPath, logger) { + const markerFilePath = `${extractedPath}.complete`; + fs12.writeFileSync(markerFilePath, ""); + logger.info(`Created toolcache marker file ${markerFilePath}`); +} +function sanitizeUrlForStatusReport(url2) { + return ["github/codeql-action", "dsp-testing/codeql-cli-nightlies"].some( + (repo) => url2.startsWith(`https://github.com/${repo}/releases/download/`) + ) ? url2 : "sanitized-value"; +} + +// src/setup-codeql.ts +var CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action"; +var CODEQL_NIGHTLIES_REPOSITORY_OWNER = "dsp-testing"; +var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; +var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; +var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; +var CODEQL_TOOLCACHE_INPUT = "toolcache"; +function getCodeQLBundleExtension(compressionMethod) { + switch (compressionMethod) { + case "gzip": + return ".tar.gz"; + case "zstd": + return ".tar.zst"; + default: + assertNever(compressionMethod); } - return void 0; } -function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { - if (!cliVersion2?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) { - return convertToSemVer(bundleVersion2, logger); +function getCodeQLBundleName(compressionMethod) { + const extension = getCodeQLBundleExtension(compressionMethod); + let platform2; + if (process.platform === "win32") { + platform2 = "win64"; + } else if (process.platform === "linux") { + platform2 = "linux64"; + } else if (process.platform === "darwin") { + platform2 = "osx64"; + } else { + return `codeql-bundle${extension}`; } - return cliVersion2; + return `codeql-bundle-${platform2}${extension}`; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { - if (!await isBinaryAccessible("tar", logger)) { - throw new ConfigurationError( - "Could not find tar in PATH, so unable to extract CodeQL bundle." +function getCodeQLActionRepository(logger) { + if (isRunningLocalAction()) { + logger.info( + "The CodeQL Action is checked out locally. Using the default CodeQL Action repository." ); + return CODEQL_DEFAULT_ACTION_REPOSITORY; } - const zstdAvailability = await isZstdAvailable(logger); - const source = await getCodeQLSource( - toolsInput, - defaultCliVersion, - rawLanguages, - useOverlayAwareDefaultCliVersion, - apiDetails, - variant, - zstdAvailability.available, - features, - logger + return getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); +} +async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod, logger) { + const codeQLActionRepository = getCodeQLActionRepository(logger); + const potentialDownloadSources = [ + // This GitHub instance, and this Action. + [apiDetails.url, codeQLActionRepository], + // This GitHub instance, and the canonical Action. + [apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY], + // GitHub.com, and the canonical Action. + [GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY] + ]; + const uniqueDownloadSources = potentialDownloadSources.filter( + (source, index2, self2) => { + return !self2.slice(0, index2).some((other) => (0, import_fast_deep_equal.default)(source, other)); + } ); - let codeqlFolder; - let toolsVersion = source.toolsVersion; - let toolsDownloadStatusReport; - let toolsSource; - switch (source.sourceType) { - case "local": { - codeqlFolder = await extract( - source.codeqlTarPath, - getTempExtractionDir(tempDir), - source.compressionMethod, - zstdAvailability.version, - logger - ); - toolsSource = "LOCAL" /* Local */; + const codeQLBundleName = getCodeQLBundleName(compressionMethod); + for (const downloadSource of uniqueDownloadSources) { + const [apiURL, repository] = downloadSource; + if (apiURL === GITHUB_DOTCOM_URL && repository === CODEQL_DEFAULT_ACTION_REPOSITORY) { break; } - case "toolcache": - codeqlFolder = source.codeqlFolder; - logger.debug(`CodeQL found in cache ${codeqlFolder}`); - toolsSource = "TOOLCACHE" /* Toolcache */; - break; - case "download": { - const result = await downloadCodeQL( - source.codeqlURL, - source.compressionMethod, - source.bundleVersion, - source.cliVersion, - apiDetails, - zstdAvailability.version, - tempDir, - logger + const [repositoryOwner, repositoryName] = repository.split("/"); + try { + const release2 = await getApiClient().rest.repos.getReleaseByTag({ + owner: repositoryOwner, + repo: repositoryName, + tag: tagName + }); + for (const asset of release2.data.assets) { + if (asset.name === codeQLBundleName) { + logger.info( + `Found CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} with URL ${asset.url}.` + ); + return asset.url; + } + } + } catch (e) { + logger.info( + `Looked for CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} but got error ${e}.` ); - toolsVersion = result.toolsVersion; - codeqlFolder = result.codeqlFolder; - toolsDownloadStatusReport = result.statusReport; - toolsSource = "DOWNLOAD" /* Download */; - break; } - default: - assertNever(source); } - return { - codeqlFolder, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability - }; -} -async function useZstdBundle(cliVersion2, tarSupportsZstd) { - return ( - // In testing, gzip performs better than zstd on Windows. - process.platform !== "win32" && tarSupportsZstd && semver9.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) - ); + return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; } -function getTempExtractionDir(tempDir) { - return path12.join(tempDir, v4_default()); +function tryGetBundleVersionFromTagName(tagName, logger) { + const match2 = tagName.match(/^codeql-bundle-(.*)$/); + if (match2 === null || match2.length < 2) { + logger.debug(`Could not determine bundle version from tag ${tagName}.`); + return void 0; + } + return match2[1]; } -async function getNightlyToolsUrl(logger) { - const zstdAvailability = await isZstdAvailable(logger); - const compressionMethod = await useZstdBundle( - CODEQL_VERSION_ZSTD_BUNDLE, - zstdAvailability.available - ) ? "zstd" : "gzip"; - try { - const release2 = await getApiClient().rest.repos.listReleases({ - owner: CODEQL_NIGHTLIES_REPOSITORY_OWNER, - repo: CODEQL_NIGHTLIES_REPOSITORY_NAME, - per_page: 1, - page: 1, - prerelease: true - }); - const latestRelease = release2.data[0]; - if (!latestRelease) { - throw new Error("Could not find the latest nightly release."); - } - return `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${getCodeQLBundleName(compressionMethod)}`; - } catch (e) { - throw new Error( - `Failed to retrieve the latest nightly release: ${wrapError(e)}` - ); +function tryGetTagNameFromUrl(url2, logger) { + const matches = [...url2.matchAll(/\/(codeql-bundle-[^/]*)\//g)]; + if (matches.length === 0) { + logger.debug(`Could not determine tag name for URL ${url2}.`); + return void 0; } -} -function getLatestToolcacheVersion(logger) { - const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver9.compare(b, a)); - logger.debug( - `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( - allVersions - )}.` - ); - if (allVersions.length > 0) { - const latestToolcacheVersion = allVersions[0]; - logger.info( - `CLI version ${latestToolcacheVersion} is the latest version in the toolcache.` + const match2 = matches[matches.length - 1]; + if (match2?.length !== 2) { + logger.debug( + `Could not determine tag name for URL ${url2}. Matched ${JSON.stringify( + match2 + )}.` ); - return latestToolcacheVersion; + return void 0; } - return void 0; -} -function isReservedToolsValue(tools) { - return CODEQL_BUNDLE_VERSION_ALIAS.includes(tools) || CODEQL_NIGHTLY_TOOLS_INPUTS.includes(tools) || tools === CODEQL_TOOLCACHE_INPUT; + return match2[1]; } - -// src/tracer-config.ts -var fs14 = __toESM(require("fs")); -var path13 = __toESM(require("path")); -async function shouldEnableIndirectTracing(codeql, config) { - if (config.buildMode === "none" /* None */) { - return false; +function convertToSemVer(version, logger) { + if (!semver9.valid(version)) { + logger.debug( + `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` + ); + version = `0.0.0-${version}`; } - if (config.buildMode === "autobuild" /* Autobuild */) { - return false; + const s = semver9.clean(version); + if (!s) { + throw new Error(`Bundle version ${version} is not in SemVer format.`); } - return asyncSome(config.languages, (l) => codeql.isTracedLanguage(l)); + return s; } -async function endTracingForCluster(codeql, config, logger) { - if (!await shouldEnableIndirectTracing(codeql, config)) return; - logger.info( - "Unsetting build tracing environment variables. Subsequent steps of this job will not be traced." - ); - const envVariablesFile = path13.resolve( - config.dbLocation, - "temp/tracingEnvironment/end-tracing.json" - ); - if (!fs14.existsSync(envVariablesFile)) { - throw new Error( - `Environment file for ending tracing not found: ${envVariablesFile}` +async function findOverridingToolsInCache(humanReadableVersion, logger) { + const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ + folder: toolcache3.find("CodeQL", version), + version + })).filter(({ folder }) => fs13.existsSync(path12.join(folder, "pinned-version"))); + if (candidates.length === 1) { + const candidate = candidates[0]; + logger.debug( + `CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.` ); - } - try { - const endTracingEnvVariables = JSON.parse( - fs14.readFileSync(envVariablesFile, "utf8") + return { + codeqlFolder: candidate.folder, + sourceType: "toolcache", + toolsVersion: candidate.version + }; + } else if (candidates.length === 0) { + logger.debug( + "Did not find any candidate pinned versions of the CodeQL tools in the toolcache." ); - for (const [key, value] of Object.entries(endTracingEnvVariables)) { - if (value !== null) { - process.env[key] = value; - } else { - delete process.env[key]; - } - } - } catch (e) { - throw new Error( - `Failed to parse file containing end tracing environment variables: ${e}` + } else { + logger.debug( + "Could not use CodeQL tools from the toolcache since more than one candidate pinned version was found in the toolcache." ); } + return void 0; } -async function getTracerConfigForCluster(config) { - const tracingEnvVariables = JSON.parse( - fs14.readFileSync( - path13.resolve( - config.dbLocation, - "temp/tracingEnvironment/start-tracing.json" - ), - "utf8" - ) +async function getEnabledVersionsWithOverlayBaseDatabases(defaultCliVersion, rawLanguages, features, logger) { + if (rawLanguages === void 0 || rawLanguages.length === 0) { + return []; + } + const isEnabled = await features.getValue( + "overlay_analysis_match_codeql_version" /* OverlayAnalysisMatchCodeqlVersion */ ); - return { - env: tracingEnvVariables - }; -} -async function getCombinedTracerConfig(codeql, config) { - if (!await shouldEnableIndirectTracing(codeql, config)) { - return void 0; + const isDryRun = !isEnabled && await features.getValue("overlay_analysis_match_codeql_version_dry_run" /* OverlayAnalysisMatchCodeqlVersionDryRun */); + if (!isEnabled && !isDryRun) { + return []; } - return await getTracerConfigForCluster(config); -} - -// src/codeql.ts -var cachedCodeQL = void 0; -var CODEQL_MINIMUM_VERSION = "2.19.4"; -var CODEQL_NEXT_MINIMUM_VERSION = "2.19.4"; -var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.15"; -var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-04-09"; -var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger, checkVersion) { + let cachedVersions; try { - const { - codeqlFolder, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability - } = await setupCodeQLBundle( - toolsInput, - apiDetails, - tempDir, - variant, - defaultCliVersion, + cachedVersions = await getCodeQlVersionsForOverlayBaseDatabases( rawLanguages, - useOverlayAwareDefaultCliVersion, - features, logger ); + } catch (e) { + logger.warning( + `Could not list overlay-base databases in the Actions cache while choosing a default CodeQL CLI version, falling back to the highest enabled version. Details: ${getErrorMessage(e)}` + ); + return []; + } + if (cachedVersions === void 0 || cachedVersions.length === 0) { + return []; + } + const cachedVersionsSet = new Set(cachedVersions); + const overlayVersions = defaultCliVersion.enabledVersions.filter( + (v) => cachedVersionsSet.has(v.cliVersion) + ); + if (overlayVersions.length === 0) { + return []; + } + const isCachedVersionDifferent = overlayVersions[0].cliVersion !== defaultCliVersion.enabledVersions[0].cliVersion; + if (isCachedVersionDifferent) { + addNoLanguageDiagnostic( + void 0, + makeTelemetryDiagnostic( + "codeql-action/overlay-aware-default-codeql-version", + "Overlay-aware default CodeQL version selection", + { + cachedVersions, + enabledVersions: defaultCliVersion.enabledVersions.map( + (v) => v.cliVersion + ), + isDryRun, + overlayAwareVersion: overlayVersions[0].cliVersion + } + ) + ); + } + if (isDryRun) { logger.debug( - `Bundle download status report: ${JSON.stringify( - toolsDownloadStatusReport - )}` + `Overlay-aware default CodeQL version selection is running in dry-run mode. Would have used version ${overlayVersions[0].cliVersion}.` ); - let codeqlCmd = path14.join(codeqlFolder, "codeql", "codeql"); - if (process.platform === "win32") { - codeqlCmd += ".exe"; - } else if (process.platform !== "linux" && process.platform !== "darwin") { + return []; + } + return overlayVersions; +} +async function resolveDefaultCliVersion(defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { + if (!useOverlayAwareDefaultCliVersion || !isAnalyzingPullRequest()) { + return defaultCliVersion.enabledVersions[0]; + } + const overlayVersions = await getEnabledVersionsWithOverlayBaseDatabases( + defaultCliVersion, + rawLanguages, + features, + logger + ); + if (overlayVersions.length > 0) { + logger.info( + `Using CodeQL version ${overlayVersions[0].cliVersion} since this is the highest enabled version that has a cached overlay-base database.` + ); + return overlayVersions[0]; + } + return defaultCliVersion.enabledVersions[0]; +} +async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { + if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { + logger.info(`Using CodeQL CLI from local path ${toolsInput}`); + const compressionMethod2 = inferCompressionMethod(toolsInput); + if (compressionMethod2 === void 0) { throw new ConfigurationError( - `Unsupported platform: ${process.platform}` + `Could not infer compression method from path ${toolsInput}. Please specify a path ending in '.tar.gz' or '.tar.zst'.` ); } - cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion); return { - codeql: cachedCodeQL, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability + codeqlTarPath: toolsInput, + compressionMethod: compressionMethod2, + sourceType: "local", + toolsVersion: "local" }; - } catch (rawError) { - const e = wrapApiConfigurationError(rawError); - const ErrorClass = e instanceof ConfigurationError || e instanceof Error && e.message.includes("ENOSPC") ? ConfigurationError : Error; - throw new ErrorClass( - `Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}${e instanceof Error && e.stack ? ` - -Details: ${e.stack}` : ""}` - ); } -} -async function getCodeQL(cmd) { - if (cachedCodeQL === void 0) { - cachedCodeQL = await getCodeQLForCmd(cmd, true); - } - return cachedCodeQL; -} -async function getCodeQLForCmd(cmd, checkVersion) { - const codeql = { - getPath() { - return cmd; - }, - async getVersion() { - let result = getCachedCodeQlVersion(cmd); - if (result === void 0) { - const output = await runCli(cmd, ["version", "--format=json"], { - noStreamStdout: true - }); - try { - result = JSON.parse(output); - } catch { - throw Error( - `Invalid JSON output from \`version --format=json\`: ${output}` - ); - } - cacheCodeQlVersion(cmd, result); - } - return result; - }, - async printVersion() { - core10.info(JSON.stringify(await this.getVersion(), null, 2)); - }, - async supportsFeature(feature) { - return isSupportedToolsFeature(await this.getVersion(), feature); - }, - async isTracedLanguage(language) { - const extractorPath = await this.resolveExtractor(language); - const tracingConfigPath = path14.join( - extractorPath, - "tools", - "tracing-config.lua" + let cliVersion2; + let tagName; + let url2; + const canForceNightlyWithFF = isDynamicWorkflow() || isInTestMode(); + const forceNightlyValueFF = await features.getValue("force_nightly" /* ForceNightly */); + const forceNightly = forceNightlyValueFF && canForceNightlyWithFF; + const nightlyRequestedByToolsInput = toolsInput !== void 0 && CODEQL_NIGHTLY_TOOLS_INPUTS.includes(toolsInput); + if (forceNightly || nightlyRequestedByToolsInput) { + if (forceNightly) { + logger.info( + `Using the latest CodeQL CLI nightly, as forced by the ${"force_nightly" /* ForceNightly */} feature flag.` ); - return fs15.existsSync(tracingConfigPath); - }, - async isScannedLanguage(language) { - return !await this.isTracedLanguage(language); - }, - async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) { - const extraArgs = config.languages.map( - (language) => `--language=${language}` + addNoLanguageDiagnostic( + void 0, + makeDiagnostic( + "codeql-action/forced-nightly-cli", + "A nightly release of CodeQL was used", + { + markdownMessage: "GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release.\n\nNightly releases do not undergo the same validation as regular releases and may lead to analysis instability.\n\nIf use of a nightly CodeQL release for this analysis is unexpected, please contact GitHub support.", + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true + }, + severity: "note" + } + ) ); - if (await shouldEnableIndirectTracing(codeql, config)) { - extraArgs.push("--begin-tracing"); - extraArgs.push(...await getTrapCachingExtractorConfigArgs(config)); - extraArgs.push(`--trace-process-name=${processName}`); - } - const codeScanningConfigFile = await writeCodeScanningConfigFile( - config, - logger + } else { + logger.info( + `Using the latest CodeQL CLI nightly, as requested by 'tools: ${toolsInput}'.` ); - const externalRepositoryToken = getOptionalInput( - "external-repository-token" + } + toolsInput = await getNightlyToolsUrl(logger); + } + const forceShippedTools = toolsInput && CODEQL_BUNDLE_VERSION_ALIAS.includes(toolsInput); + if (forceShippedTools) { + cliVersion2 = cliVersion; + tagName = bundleVersion; + logger.info( + `'tools: ${toolsInput}' was requested, so using CodeQL version ${cliVersion2}, the version shipped with the Action.` + ); + if (toolsInput === "latest") { + logger.warning( + "`tools: latest` has been renamed to `tools: linked`, but the old name is still supported. No action is required." ); - extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`); - if (externalRepositoryToken) { - extraArgs.push("--external-repository-token-stdin"); - } - if (config.buildMode !== void 0) { - extraArgs.push(`--build-mode=${config.buildMode}`); - } - if (qlconfigFile !== void 0) { - extraArgs.push(`--qlconfig-file=${qlconfigFile}`); + } + } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { + let latestToolcacheVersion; + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + if (allowToolcacheValue) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + latestToolcacheVersion = getLatestToolcacheVersion(logger); + if (latestToolcacheVersion) { + cliVersion2 = latestToolcacheVersion; } - const overlayDatabaseMode = config.overlayDatabaseMode; - if (overlayDatabaseMode === "overlay" /* Overlay */) { - const overlayChangesFile = await writeOverlayChangesFile( - config, - sourceRoot, - logger + } + if (latestToolcacheVersion === void 0) { + if (allowToolcacheValue) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); - extraArgs.push(`--overlay-changes=${overlayChangesFile}`); - } else if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { - extraArgs.push("--overlay-base"); + } else { + if (allowToolcacheValueFF) { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } else { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } } - const baselineFilesOptions = config.enableFileCoverageInformation ? [ - "--calculate-language-specific-baseline", - "--sublanguage-file-coverage" - ] : ["--no-calculate-baseline"]; - await runCli( - cmd, - [ - "database", - "init", - ...overlayDatabaseMode === "overlay" /* Overlay */ ? [] : ["--force-overwrite"], - "--db-cluster", - config.dbLocation, - `--source-root=${sourceRoot}`, - ...baselineFilesOptions, - "--extractor-include-aliases", - ...extraArgs, - ...getExtraOptionsFromEnv(["database", "init"], { - // Some user configs specify `--no-calculate-baseline` as an additional - // argument to `codeql database init`. Therefore ignore the baseline file - // options here to avoid specifying the same argument twice and erroring. - // - // Ignore `--overwrite` to avoid passing both `--force-overwrite` and `--overwrite` if - // the user has configured `--overwrite`. - ignoringOptions: [ - "--force-overwrite", - "--overwrite", - ...baselineFilesOptions - ] - }) - ], - { stdin: externalRepositoryToken } + const version = await resolveDefaultCliVersion( + defaultCliVersion, + rawLanguages, + useOverlayAwareDefaultCliVersion, + features, + logger ); - if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { - await writeBaseDatabaseOidsFile(config, sourceRoot); + cliVersion2 = version.cliVersion; + tagName = version.tagName; + } + } else if (toolsInput !== void 0) { + tagName = tryGetTagNameFromUrl(toolsInput, logger); + url2 = toolsInput; + if (tagName) { + const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger); + if (bundleVersion3 && semver9.valid(bundleVersion3)) { + cliVersion2 = convertToSemVer(bundleVersion3, logger); } - }, - async runAutobuild(config, language) { - applyAutobuildAzurePipelinesTimeoutFix(); - const autobuildCmd = path14.join( - await this.resolveExtractor(language), - "tools", - process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" + } + } else { + const version = await resolveDefaultCliVersion( + defaultCliVersion, + rawLanguages, + useOverlayAwareDefaultCliVersion, + features, + logger + ); + cliVersion2 = version.cliVersion; + tagName = version.tagName; + } + const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger); + const humanReadableVersion = cliVersion2 ?? (bundleVersion2 && convertToSemVer(bundleVersion2, logger)) ?? tagName ?? url2 ?? "unknown"; + logger.debug( + `Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.` + ); + let codeqlFolder; + if (cliVersion2) { + codeqlFolder = toolcache3.find("CodeQL", cliVersion2); + if (!codeqlFolder) { + logger.debug( + `Didn't find a version of the CodeQL tools in the toolcache with a version number exactly matching ${cliVersion2}.` ); - if (config.debugMode) { - process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] = process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] || EXTRACTION_DEBUG_MODE_VERBOSITY; + const allVersions = toolcache3.findAllVersions("CodeQL"); + logger.debug( + `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( + allVersions + )}.` + ); + const candidateVersions = allVersions.filter( + (version) => version.startsWith(`${cliVersion2}-`) + ); + if (candidateVersions.length === 1) { + logger.debug( + `Exactly one version of the CodeQL tools starting with ${cliVersion2} found in the toolcache, using that.` + ); + codeqlFolder = toolcache3.find("CodeQL", candidateVersions[0]); + } else if (candidateVersions.length === 0) { + logger.debug( + `Didn't find any versions of the CodeQL tools starting with ${cliVersion2} in the toolcache. Trying next fallback method.` + ); + } else { + logger.warning( + `Found ${candidateVersions.length} versions of the CodeQL tools starting with ${cliVersion2} in the toolcache, but at most one was expected.` + ); + logger.debug("Trying next fallback method."); } - await runCli(autobuildCmd); - }, - async extractScannedLanguage(config, language) { - await runCli(cmd, [ - "database", - "trace-command", - "--index-traceless-dbs", - ...await getTrapCachingExtractorConfigArgsForLang(config, language), - ...getExtractionVerbosityArguments(config.debugMode), - ...getExtraOptionsFromEnv(["database", "trace-command"]), - getCodeQLDatabasePath(config, language) - ]); - }, - async extractUsingBuildMode(config, language) { - if (config.buildMode === "autobuild" /* Autobuild */) { - applyAutobuildAzurePipelinesTimeoutFix(); - } - try { - await runCli(cmd, [ - "database", - "trace-command", - "--use-build-mode", - "--working-dir", - process.cwd(), - ...await getTrapCachingExtractorConfigArgsForLang(config, language), - ...getExtractionVerbosityArguments(config.debugMode), - ...getExtraOptionsFromEnv(["database", "trace-command"]), - getCodeQLDatabasePath(config, language) - ]); - } catch (e) { - if (config.buildMode === "autobuild" /* Autobuild */) { - const prefix = `We were unable to automatically build your code. Please change the build mode for this language to manual and specify build steps for your project. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information.`; - throw new ConfigurationError(`${prefix} ${getErrorMessage(e)}`); - } else { - throw e; - } - } - }, - async finalizeDatabase(databasePath, threadsFlag, memoryFlag, enableDebugLogging) { - const args = [ - "database", - "finalize", - "--finalize-dataset", - threadsFlag, - memoryFlag, - ...getExtractionVerbosityArguments(enableDebugLogging), - ...getExtraOptionsFromEnv(["database", "finalize"]), - databasePath - ]; - await runCli(cmd, args); - }, - async resolveLanguages({ - filterToLanguagesWithQueries - } = { filterToLanguagesWithQueries: false }) { - const codeqlArgs = [ - "resolve", - "languages", - "--format=betterjson", - "--extractor-options-verbosity=4", - "--extractor-include-aliases", - ...filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : [], - ...getExtraOptionsFromEnv(["resolve", "languages"]) - ]; - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve languages with --format=betterjson: ${e}` - ); - } - }, - async resolveBuildEnvironment(workingDir, language) { - const codeqlArgs = [ - "resolve", - "build-environment", - `--language=${language}`, - "--extractor-include-aliases", - ...getExtraOptionsFromEnv(["resolve", "build-environment"]) - ]; - if (workingDir !== void 0) { - codeqlArgs.push("--working-dir", workingDir); - } - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve build-environment: ${e} in -${output}` - ); - } - }, - async databaseRunQueries(databasePath, flags, queries = []) { - const codeqlArgs = [ - "database", - "run-queries", - ...flags, - databasePath, - "--min-disk-free=1024", - // Try to leave at least 1GB free - "-v", - ...queries, - ...getExtraOptionsFromEnv(["database", "run-queries"], { - ignoringOptions: ["--expect-discarded-cache"] - }) - ]; - await runCli(cmd, codeqlArgs); - }, - async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, threadsFlag, verbosityFlag, sarifRunPropertyFlag, automationDetailsId, config, features) { - const shouldExportDiagnostics = await features.getValue( - "export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, - this + } + } + if (!codeqlFolder && tagName) { + const fallbackVersion = await tryGetFallbackToolcacheVersion( + cliVersion2, + tagName, + logger + ); + if (fallbackVersion) { + codeqlFolder = toolcache3.find("CodeQL", fallbackVersion); + } else { + logger.debug( + `Could not determine a fallback toolcache version number for CodeQL tools version ${humanReadableVersion}.` ); - const codeqlArgs = [ - "database", - "interpret-results", - threadsFlag, - "--format=sarif-latest", - verbosityFlag, - `--output=${sarifFile}`, - "--print-diagnostics-summary", - "--print-metrics-summary", - "--sarif-add-baseline-file-info", - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config - )}`, - "--sarif-group-rules-by-pack", - "--sarif-include-query-help=always", - "--sublanguage-file-coverage", - ...await getJobRunUuidSarifOptions(), - ...getExtraOptionsFromEnv(["database", "interpret-results"]) - ]; - if (sarifRunPropertyFlag !== void 0) { - codeqlArgs.push(sarifRunPropertyFlag); - } - if (automationDetailsId !== void 0) { - codeqlArgs.push("--sarif-category", automationDetailsId); - } - if (shouldExportDiagnostics) { - codeqlArgs.push("--sarif-include-diagnostics"); - } else { - codeqlArgs.push("--no-sarif-include-diagnostics"); - } - codeqlArgs.push(databasePath); - if (querySuitePaths) { - codeqlArgs.push(...querySuitePaths); - } - return await runCli(cmd, codeqlArgs, { - noStreamStdout: true - }); - }, - async databaseCleanupCluster(config, cleanupLevel) { - for (const language of config.languages) { - const databasePath = getCodeQLDatabasePath(config, language); - const codeqlArgs = [ - "database", - "cleanup", - databasePath, - `--cache-cleanup=${cleanupLevel}`, - ...getExtraOptionsFromEnv(["database", "cleanup"]) - ]; - await runCli(cmd, codeqlArgs); - } - }, - async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) { - const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : []; - const args = [ - "database", - "bundle", - databasePath, - `--output=${outputFilePath}`, - `--name=${databaseName}`, - ...includeDiagnosticsArgs, - ...getExtraOptionsFromEnv(["database", "bundle"], { - ignoringOptions: includeDiagnosticsArgs - }) - ]; - if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) { - args.push( - ...alsoIncludeRelativePaths.flatMap((relativePath2) => [ - "--include", - relativePath2 - ]) - ); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { - const args = [ - "database", - "export-diagnostics", - `${databasePath}`, - "--db-cluster", - // Database is always a cluster for CodeQL versions that support diagnostics. - "--format=sarif-latest", - `--output=${sarifFile}`, - "--sarif-include-diagnostics", - // ExportDiagnosticsEnabled is always true if this command is run. - "-vvv", - ...getExtraOptionsFromEnv(["diagnostics", "export"]) - ]; - if (automationDetailsId !== void 0) { - args.push("--sarif-category", automationDetailsId); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async diagnosticsExport(sarifFile, automationDetailsId, config) { - const args = [ - "diagnostics", - "export", - "--format=sarif-latest", - `--output=${sarifFile}`, - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config - )}`, - ...getExtraOptionsFromEnv(["diagnostics", "export"]) - ]; - if (automationDetailsId !== void 0) { - args.push("--sarif-category", automationDetailsId); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async resolveExtractor(language) { - let extractorPath = ""; - await new toolrunner3.ToolRunner( - cmd, - [ - "resolve", - "extractor", - "--format=json", - `--language=${language}`, - "--extractor-include-aliases", - ...getExtraOptionsFromEnv(["resolve", "extractor"]) - ], - { - silent: true, - listeners: { - stdout: (data) => { - extractorPath += data.toString(); - }, - stderr: (data) => { - process.stderr.write(data); - } - } - } - ).exec(); - return JSON.parse(extractorPath); - }, - async resolveQueriesStartingPacks(queries) { - const codeqlArgs = [ - "resolve", - "queries", - "--format=startingpacks", - ...getExtraOptionsFromEnv(["resolve", "queries"]), - ...queries - ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve queries --format=startingpacks: ${e}` - ); - } - }, - async resolveDatabase(databasePath) { - const codeqlArgs = [ - "resolve", - "database", - databasePath, - "--format=json", - ...getExtraOptionsFromEnv(["resolve", "database"]) - ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve database --format=json: ${e}` - ); - } - }, - async mergeResults(sarifFiles, outputFile, { - mergeRunsFromEqualCategory = false - }) { - const args = [ - "github", - "merge-results", - "--output", - outputFile, - ...getExtraOptionsFromEnv(["github", "merge-results"]) - ]; - for (const sarifFile of sarifFiles) { - args.push("--sarif", sarifFile); - } - if (mergeRunsFromEqualCategory) { - args.push("--sarif-merge-runs-from-equal-category"); - } - await runCli(cmd, args); } - }; - if (checkVersion && !await codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) { - throw new ConfigurationError( - `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql.getVersion()).version}` + } + if (codeqlFolder) { + logger.info( + `Found CodeQL tools version ${humanReadableVersion} in the toolcache.` ); - } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { - const result = await codeql.getVersion(); - core10.warning( - `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. - -Alternatively, if you want to continue using CodeQL CLI version ${result.version}, you can replace 'github/codeql-action/*@v${getActionVersion().split(".")[0]}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to continue using this version of the CodeQL Action.` + } else { + logger.info( + `Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.` + ); + } + if (codeqlFolder) { + if (cliVersion2) { + logger.info( + `Using CodeQL CLI version ${cliVersion2} from toolcache at ${codeqlFolder}` + ); + } else { + logger.info(`Using CodeQL CLI from toolcache at ${codeqlFolder}`); + } + return { + codeqlFolder, + sourceType: "toolcache", + toolsVersion: cliVersion2 ?? humanReadableVersion + }; + } + if (variant === "GitHub Enterprise Server" /* GHES */ && !forceShippedTools && !toolsInput) { + const result = await findOverridingToolsInCache( + humanReadableVersion, + logger ); - core10.exportVariable("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); + if (result !== void 0) { + return result; + } } - return codeql; -} -function getExtraOptionsFromEnv(paths, { ignoringOptions } = {}) { - const options = getExtraOptionsEnvParam(); - return getExtraOptions(options, paths, []).filter( - (option) => !ignoringOptions?.includes(option) - ); -} -function asExtraOptions(options, pathInfo) { - if (options === void 0) { - return []; + let compressionMethod; + if (!url2) { + compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; + url2 = await getCodeQLBundleDownloadURL( + tagName, + apiDetails, + compressionMethod, + logger + ); + } else { + const method = inferCompressionMethod(url2); + if (method === void 0) { + throw new ConfigurationError( + `Could not infer compression method from URL ${url2}. Please specify a URL ending in '.tar.gz' or '.tar.zst'.` + ); + } + compressionMethod = method; } - if (!Array.isArray(options)) { - const msg = `The extra options for '${pathInfo.join( - "." - )}' ('${JSON.stringify(options)}') are not in an array.`; - throw new Error(msg); + if (cliVersion2) { + logger.info(`Using CodeQL CLI version ${cliVersion2} sourced from ${url2} .`); + } else { + logger.info(`Using CodeQL CLI sourced from ${url2} .`); } - return options.map((o) => { - const t = typeof o; - if (t !== "string" && t !== "number" && t !== "boolean") { - const msg = `The extra option for '${pathInfo.join( - "." - )}' ('${JSON.stringify(o)}') is not a primitive value.`; - throw new Error(msg); - } - return `${o}`; - }); + return { + bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger), + cliVersion: cliVersion2, + codeqlURL: url2, + compressionMethod, + sourceType: "download", + toolsVersion: cliVersion2 ?? humanReadableVersion + }; } -function getExtraOptions(options, paths, pathInfo) { - const all = asExtraOptions(options?.["*"], pathInfo.concat("*")); - const specific = paths.length === 0 ? asExtraOptions(options, pathInfo) : getExtraOptions( - options?.[paths[0]], - paths?.slice(1), - pathInfo.concat(paths[0]) +async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) { + const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger); + if (!bundleVersion2) { + return void 0; + } + const fallbackVersion = convertToSemVer(bundleVersion2, logger); + logger.debug( + `Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ${cliVersion2 ?? tagName}.` ); - return all.concat(specific); + return fallbackVersion; } -async function runCli(cmd, args = [], opts = {}) { - try { - return await runTool(cmd, args, opts); - } catch (e) { - if (e instanceof CommandInvocationError) { - throw wrapCliConfigurationError(new CliError(e)); - } - throw e; +var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVersion, maybeCliVersion, apiDetails, tarVersion, tempDir, logger) { + const parsedCodeQLURL = new URL(codeqlURL); + const searchParams = new URLSearchParams(parsedCodeQLURL.search); + const headers = { + accept: "application/octet-stream" + }; + let authorization = void 0; + if (searchParams.has("token")) { + logger.debug("CodeQL tools URL contains an authorization token."); + } else { + authorization = getAuthorizationHeaderFor( + logger, + apiDetails, + codeqlURL + ); } -} -async function writeCodeScanningConfigFile(config, logger) { - const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); - const augmentedConfig = appendExtraQueryExclusions( - config.extraQueryExclusions, - config.computedConfig + const toolcacheInfo = getToolcacheDestinationInfo( + maybeBundleVersion, + maybeCliVersion, + logger ); - logger.info( - `Writing augmented user configuration file to ${codeScanningConfigFile}` + const extractedBundlePath = toolcacheInfo?.path ?? getTempExtractionDir(tempDir); + const statusReport = await downloadAndExtract( + codeqlURL, + compressionMethod, + extractedBundlePath, + authorization, + { "User-Agent": "CodeQL Action", ...headers }, + tarVersion, + logger ); - logger.startGroup("Augmented user configuration file contents"); - logger.info(dump(augmentedConfig)); - logger.endGroup(); - fs15.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); - return codeScanningConfigFile; -} -var TRAP_CACHE_SIZE_MB = 1024; -async function getTrapCachingExtractorConfigArgs(config) { - const result = []; - for (const language of config.languages) - result.push( - await getTrapCachingExtractorConfigArgsForLang(config, language) + if (!toolcacheInfo) { + logger.debug( + `Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.` ); - return result.flat(); -} -async function getTrapCachingExtractorConfigArgsForLang(config, language) { - const cacheDir2 = config.trapCaches[language]; - if (cacheDir2 === void 0) return []; - const write = await isAnalyzingDefaultBranch(); - return [ - `-O=${language}.trap.cache.dir=${cacheDir2}`, - `-O=${language}.trap.cache.bound=${TRAP_CACHE_SIZE_MB}`, - `-O=${language}.trap.cache.write=${write}` - ]; -} -function getGeneratedCodeScanningConfigPath(config) { - return path14.resolve(config.tempDir, "user-config.yaml"); + return { + codeqlFolder: extractedBundlePath, + statusReport, + toolsVersion: maybeCliVersion ?? "unknown" + }; + } + writeToolcacheMarkerFile(toolcacheInfo.path, logger); + return { + codeqlFolder: extractedBundlePath, + statusReport, + toolsVersion: maybeCliVersion ?? toolcacheInfo.version + }; +}; +function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) { + if (maybeBundleVersion) { + const version = getCanonicalToolcacheVersion( + maybeCliVersion, + maybeBundleVersion, + logger + ); + return { + path: getToolcacheDirectory(version), + version + }; + } + return void 0; } -function getExtractionVerbosityArguments(enableDebugLogging) { - return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; +function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { + if (!cliVersion2?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) { + return convertToSemVer(bundleVersion2, logger); + } + return cliVersion2; } -function applyAutobuildAzurePipelinesTimeoutFix() { - const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; - process.env["JAVA_TOOL_OPTIONS"] = [ - ...javaToolOptions.split(/\s+/), - "-Dhttp.keepAlive=false", - "-Dmaven.wagon.http.pool=false" - ].join(" "); +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger) { + if (!await isBinaryAccessible("tar", logger)) { + throw new ConfigurationError( + "Could not find tar in PATH, so unable to extract CodeQL bundle." + ); + } + const zstdAvailability = await isZstdAvailable(logger); + const source = await getCodeQLSource( + toolsInput, + defaultCliVersion, + rawLanguages, + useOverlayAwareDefaultCliVersion, + apiDetails, + variant, + zstdAvailability.available, + features, + logger + ); + let codeqlFolder; + let toolsVersion = source.toolsVersion; + let toolsDownloadStatusReport; + let toolsSource; + switch (source.sourceType) { + case "local": { + codeqlFolder = await extract( + source.codeqlTarPath, + getTempExtractionDir(tempDir), + source.compressionMethod, + zstdAvailability.version, + logger + ); + toolsSource = "LOCAL" /* Local */; + break; + } + case "toolcache": + codeqlFolder = source.codeqlFolder; + logger.debug(`CodeQL found in cache ${codeqlFolder}`); + toolsSource = "TOOLCACHE" /* Toolcache */; + break; + case "download": { + const result = await downloadCodeQL( + source.codeqlURL, + source.compressionMethod, + source.bundleVersion, + source.cliVersion, + apiDetails, + zstdAvailability.version, + tempDir, + logger + ); + toolsVersion = result.toolsVersion; + codeqlFolder = result.codeqlFolder; + toolsDownloadStatusReport = result.statusReport; + toolsSource = "DOWNLOAD" /* Download */; + break; + } + default: + assertNever(source); + } + return { + codeqlFolder, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + }; } -async function getJobRunUuidSarifOptions() { - const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */]; - return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; +async function useZstdBundle(cliVersion2, tarSupportsZstd) { + return ( + // In testing, gzip performs better than zstd on Windows. + process.platform !== "win32" && tarSupportsZstd && semver9.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) + ); } - -// src/autobuild.ts -async function determineAutobuildLanguages(codeql, config, logger) { - if (config.buildMode === "none" /* None */ || config.buildMode === "manual" /* Manual */) { - logger.info( - `Using build mode "${config.buildMode}", nothing to autobuild. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes" /* CODEQL_BUILD_MODES */} for more information.` +function getTempExtractionDir(tempDir) { + return path12.join(tempDir, v4_default()); +} +async function getNightlyToolsUrl(logger) { + const zstdAvailability = await isZstdAvailable(logger); + const compressionMethod = await useZstdBundle( + CODEQL_VERSION_ZSTD_BUNDLE, + zstdAvailability.available + ) ? "zstd" : "gzip"; + try { + const release2 = await getApiClient().rest.repos.listReleases({ + owner: CODEQL_NIGHTLIES_REPOSITORY_OWNER, + repo: CODEQL_NIGHTLIES_REPOSITORY_NAME, + per_page: 1, + page: 1, + prerelease: true + }); + const latestRelease = release2.data[0]; + if (!latestRelease) { + throw new Error("Could not find the latest nightly release."); + } + return `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${getCodeQLBundleName(compressionMethod)}`; + } catch (e) { + throw new Error( + `Failed to retrieve the latest nightly release: ${wrapError(e)}` ); - return void 0; } - const autobuildLanguages = await asyncFilter( - config.languages, - async (language) => await codeql.isTracedLanguage(language) +} +function getLatestToolcacheVersion(logger) { + const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver9.compare(b, a)); + logger.debug( + `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( + allVersions + )}.` ); - if (autobuildLanguages.length === 0) { + if (allVersions.length > 0) { + const latestToolcacheVersion = allVersions[0]; logger.info( - "None of the languages in this project require extra build steps" + `CLI version ${latestToolcacheVersion} is the latest version in the toolcache.` ); - return void 0; - } - const autobuildLanguagesWithoutGo = autobuildLanguages.filter( - (l) => l !== "go" /* go */ - ); - const languages = []; - if (autobuildLanguagesWithoutGo[0] !== void 0) { - languages.push(autobuildLanguagesWithoutGo[0]); + return latestToolcacheVersion; } - if (autobuildLanguages.length !== autobuildLanguagesWithoutGo.length) { - languages.push("go" /* go */); + return void 0; +} +function isReservedToolsValue(tools) { + return CODEQL_BUNDLE_VERSION_ALIAS.includes(tools) || CODEQL_NIGHTLY_TOOLS_INPUTS.includes(tools) || tools === CODEQL_TOOLCACHE_INPUT; +} + +// src/tracer-config.ts +var fs14 = __toESM(require("fs")); +var path13 = __toESM(require("path")); +async function shouldEnableIndirectTracing(codeql, config) { + if (config.buildMode === "none" /* None */) { + return false; } - logger.debug(`Will autobuild ${languages.join(" and ")}.`); - if (autobuildLanguagesWithoutGo.length > 1) { - logger.warning( - `We will only automatically build ${languages.join( - " and " - )} code. If you wish to scan ${autobuildLanguagesWithoutGo.slice(1).join( - " and " - )}, you must replace the autobuild step of your workflow with custom build steps. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#about-specifying-build-steps-manually" /* SPECIFY_BUILD_STEPS_MANUALLY */} for more information.` - ); + if (config.buildMode === "autobuild" /* Autobuild */) { + return false; } - return languages; + return asyncSome(config.languages, (l) => codeql.isTracedLanguage(l)); } -async function setupCppAutobuild(codeql, logger) { - const envVar = featureConfig["cpp_dependency_installation_enabled" /* CppDependencyInstallation */].envVar; - const featureName = "C++ automatic installation of dependencies"; - const gitHubVersion = await getGitHubVersion(); - const repositoryNwo = getRepositoryNwo(); - const features = initFeatures( - gitHubVersion, - repositoryNwo, - getTemporaryDirectory(), - logger +async function endTracingForCluster(codeql, config, logger) { + if (!await shouldEnableIndirectTracing(codeql, config)) return; + logger.info( + "Unsetting build tracing environment variables. Subsequent steps of this job will not be traced." ); - if (await features.getValue("cpp_dependency_installation_enabled" /* CppDependencyInstallation */, codeql)) { - if (process.env["RUNNER_ENVIRONMENT"] === "self-hosted" && process.env[envVar] !== "true") { - logger.info( - `Disabling ${featureName} as we are on a self-hosted runner.${getWorkflowEventName() !== "dynamic" ? ` To override this, set the ${envVar} environment variable to 'true' in your workflow. See ${"https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow" /* DEFINE_ENV_VARIABLES */} for more information.` : ""}` - ); - core11.exportVariable(envVar, "false"); - } else { - logger.info( - `Enabling ${featureName}. This can be disabled by setting the ${envVar} environment variable to 'false'. See ${"https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow" /* DEFINE_ENV_VARIABLES */} for more information.` - ); - core11.exportVariable(envVar, "true"); - } - } else { - logger.info(`Disabling ${featureName}.`); - core11.exportVariable(envVar, "false"); - } -} -async function runAutobuild(config, language, logger) { - logger.startGroup(`Attempting to automatically build ${language} code`); - const codeQL = await getCodeQL(config.codeQLCmd); - if (language === "cpp" /* cpp */) { - await setupCppAutobuild(codeQL, logger); - } - if (config.buildMode) { - await codeQL.extractUsingBuildMode(config, language); - } else { - await codeQL.runAutobuild(config, language); + const envVariablesFile = path13.resolve( + config.dbLocation, + "temp/tracingEnvironment/end-tracing.json" + ); + if (!fs14.existsSync(envVariablesFile)) { + throw new Error( + `Environment file for ending tracing not found: ${envVariablesFile}` + ); } - if (language === "go" /* go */) { - core11.exportVariable("CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */, "true"); + try { + const endTracingEnvVariables = JSON.parse( + fs14.readFileSync(envVariablesFile, "utf8") + ); + for (const [key, value] of Object.entries(endTracingEnvVariables)) { + if (value !== null) { + process.env[key] = value; + } else { + delete process.env[key]; + } + } + } catch (e) { + throw new Error( + `Failed to parse file containing end tracing environment variables: ${e}` + ); } - logger.endGroup(); -} - -// src/dependency-caching.ts -var os4 = __toESM(require("os")); -var import_path2 = require("path"); -var actionsCache4 = __toESM(require_cache4()); -var glob = __toESM(require_glob()); -var CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies"; -var CODEQL_DEPENDENCY_CACHE_VERSION = 1; -function getJavaTempDependencyDir() { - return (0, import_path2.join)(getTemporaryDirectory(), "codeql_java", "repository"); -} -async function getJavaDependencyDirs() { - return [ - // Maven - (0, import_path2.join)(os4.homedir(), ".m2", "repository"), - // Gradle - (0, import_path2.join)(os4.homedir(), ".gradle", "caches"), - // CodeQL Java build-mode: none - getJavaTempDependencyDir() - ]; -} -function getCsharpTempDependencyDir() { - return (0, import_path2.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); } -async function getCsharpDependencyDirs(codeql, features) { - const dirs = [ - // Nuget - (0, import_path2.join)(os4.homedir(), ".nuget", "packages") - ]; - if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { - dirs.push(getCsharpTempDependencyDir()); - } - return dirs; +async function getTracerConfigForCluster(config) { + const tracingEnvVariables = JSON.parse( + fs14.readFileSync( + path13.resolve( + config.dbLocation, + "temp/tracingEnvironment/start-tracing.json" + ), + "utf8" + ) + ); + return { + env: tracingEnvVariables + }; } -async function makePatternCheck(patterns) { - const globber = await makeGlobber(patterns); - if ((await globber.glob()).length === 0) { +async function getCombinedTracerConfig(codeql, config) { + if (!await shouldEnableIndirectTracing(codeql, config)) { return void 0; } - return patterns; -} -var CSHARP_BASE_PATTERNS = [ - // NuGet - "**/packages.lock.json", - // Paket - "**/paket.lock" -]; -var CSHARP_EXTRA_PATTERNS = [ - "**/*.csproj", - "**/packages.config", - "**/nuget.config" -]; -async function getCsharpHashPatterns(codeql, features) { - const basePatterns = await internal.makePatternCheck(CSHARP_BASE_PATTERNS); - if (basePatterns !== void 0) { - return basePatterns; - } - if (await features.getValue("csharp_new_cache_key" /* CsharpNewCacheKey */, codeql)) { - return internal.makePatternCheck(CSHARP_EXTRA_PATTERNS); - } - return void 0; + return await getTracerConfigForCluster(config); } -var defaultCacheConfigs = { - java: { - getDependencyPaths: getJavaDependencyDirs, - getHashPatterns: async () => internal.makePatternCheck([ - // Maven - "**/pom.xml", - // Gradle - "**/*.gradle*", - "**/gradle-wrapper.properties", - "buildSrc/**/Versions.kt", - "buildSrc/**/Dependencies.kt", - "gradle/*.versions.toml", - "**/versions.properties" - ]) - }, - csharp: { - getDependencyPaths: getCsharpDependencyDirs, - getHashPatterns: getCsharpHashPatterns - }, - go: { - getDependencyPaths: async () => [(0, import_path2.join)(os4.homedir(), "go", "pkg", "mod")], - getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) + +// src/codeql.ts +var cachedCodeQL = void 0; +var CODEQL_MINIMUM_VERSION = "2.19.4"; +var CODEQL_NEXT_MINIMUM_VERSION = "2.19.4"; +var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.15"; +var GHES_MOST_RECENT_DEPRECATION_DATE = "2026-04-09"; +var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, useOverlayAwareDefaultCliVersion, features, logger, checkVersion) { + try { + const { + codeqlFolder, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + } = await setupCodeQLBundle( + toolsInput, + apiDetails, + tempDir, + variant, + defaultCliVersion, + rawLanguages, + useOverlayAwareDefaultCliVersion, + features, + logger + ); + logger.debug( + `Bundle download status report: ${JSON.stringify( + toolsDownloadStatusReport + )}` + ); + let codeqlCmd = path14.join(codeqlFolder, "codeql", "codeql"); + if (process.platform === "win32") { + codeqlCmd += ".exe"; + } else if (process.platform !== "linux" && process.platform !== "darwin") { + throw new ConfigurationError( + `Unsupported platform: ${process.platform}` + ); + } + cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion); + return { + codeql: cachedCodeQL, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + }; + } catch (rawError) { + const e = wrapApiConfigurationError(rawError); + const ErrorClass = e instanceof ConfigurationError || e instanceof Error && e.message.includes("ENOSPC") ? ConfigurationError : Error; + throw new ErrorClass( + `Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}${e instanceof Error && e.stack ? ` + +Details: ${e.stack}` : ""}` + ); } -}; -async function makeGlobber(patterns) { - return glob.create(patterns.join("\n")); } -async function checkHashPatterns(codeql, features, language, cacheConfig, checkType, logger) { - const patterns = await cacheConfig.getHashPatterns(codeql, features); - if (patterns === void 0) { - logger.info( - `Skipping ${checkType} of dependency cache for ${language} as we cannot calculate a hash for the cache key.` - ); +async function getCodeQL(cmd) { + if (cachedCodeQL === void 0) { + cachedCodeQL = await getCodeQLForCmd(cmd, true); } - return patterns; + return cachedCodeQL; } -async function downloadDependencyCaches(codeql, features, languages, logger) { - const status = []; - const restoredKeys = []; - for (const language of languages) { - const cacheConfig = defaultCacheConfigs[language]; - if (cacheConfig === void 0) { - logger.info( - `Skipping download of dependency cache for ${language} as we have no caching configuration for it.` +async function getCodeQLForCmd(cmd, checkVersion) { + const codeql = { + getPath() { + return cmd; + }, + async getVersion() { + let result = getCachedCodeQlVersion(cmd); + if (result === void 0) { + const output = await runCli(cmd, ["version", "--format=json"], { + noStreamStdout: true + }); + try { + result = JSON.parse(output); + } catch { + throw Error( + `Invalid JSON output from \`version --format=json\`: ${output}` + ); + } + cacheCodeQlVersion(cmd, result); + } + return result; + }, + async printVersion() { + core12.info(JSON.stringify(await this.getVersion(), null, 2)); + }, + async supportsFeature(feature) { + return isSupportedToolsFeature(await this.getVersion(), feature); + }, + async isTracedLanguage(language) { + const extractorPath = await this.resolveExtractor(language); + const tracingConfigPath = path14.join( + extractorPath, + "tools", + "tracing-config.lua" + ); + return fs15.existsSync(tracingConfigPath); + }, + async isScannedLanguage(language) { + return !await this.isTracedLanguage(language); + }, + async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) { + const extraArgs = config.languages.map( + (language) => `--language=${language}` + ); + if (await shouldEnableIndirectTracing(codeql, config)) { + extraArgs.push("--begin-tracing"); + extraArgs.push(...await getTrapCachingExtractorConfigArgs(config)); + extraArgs.push(`--trace-process-name=${processName}`); + } + const codeScanningConfigFile = await writeCodeScanningConfigFile( + config, + logger + ); + const externalRepositoryToken = getOptionalInput( + "external-repository-token" + ); + extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`); + if (externalRepositoryToken) { + extraArgs.push("--external-repository-token-stdin"); + } + if (config.buildMode !== void 0) { + extraArgs.push(`--build-mode=${config.buildMode}`); + } + if (qlconfigFile !== void 0) { + extraArgs.push(`--qlconfig-file=${qlconfigFile}`); + } + const overlayDatabaseMode = config.overlayDatabaseMode; + if (overlayDatabaseMode === "overlay" /* Overlay */) { + const overlayChangesFile = await writeOverlayChangesFile( + config, + sourceRoot, + logger + ); + extraArgs.push(`--overlay-changes=${overlayChangesFile}`); + } else if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { + extraArgs.push("--overlay-base"); + } + const baselineFilesOptions = config.enableFileCoverageInformation ? [ + "--calculate-language-specific-baseline", + "--sublanguage-file-coverage" + ] : ["--no-calculate-baseline"]; + await runCli( + cmd, + [ + "database", + "init", + ...overlayDatabaseMode === "overlay" /* Overlay */ ? [] : ["--force-overwrite"], + "--db-cluster", + config.dbLocation, + `--source-root=${sourceRoot}`, + ...baselineFilesOptions, + "--extractor-include-aliases", + ...extraArgs, + ...getExtraOptionsFromEnv(["database", "init"], { + // Some user configs specify `--no-calculate-baseline` as an additional + // argument to `codeql database init`. Therefore ignore the baseline file + // options here to avoid specifying the same argument twice and erroring. + // + // Ignore `--overwrite` to avoid passing both `--force-overwrite` and `--overwrite` if + // the user has configured `--overwrite`. + ignoringOptions: [ + "--force-overwrite", + "--overwrite", + ...baselineFilesOptions + ] + }) + ], + { stdin: externalRepositoryToken } + ); + if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { + await writeBaseDatabaseOidsFile(config, sourceRoot); + } + }, + async runAutobuild(config, language) { + applyAutobuildAzurePipelinesTimeoutFix(); + const autobuildCmd = path14.join( + await this.resolveExtractor(language), + "tools", + process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" + ); + if (config.debugMode) { + process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] = process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] || EXTRACTION_DEBUG_MODE_VERBOSITY; + } + await runCli(autobuildCmd); + }, + async extractScannedLanguage(config, language) { + await runCli(cmd, [ + "database", + "trace-command", + "--index-traceless-dbs", + ...await getTrapCachingExtractorConfigArgsForLang(config, language), + ...getExtractionVerbosityArguments(config.debugMode), + ...getExtraOptionsFromEnv(["database", "trace-command"]), + getCodeQLDatabasePath(config, language) + ]); + }, + async extractUsingBuildMode(config, language) { + if (config.buildMode === "autobuild" /* Autobuild */) { + applyAutobuildAzurePipelinesTimeoutFix(); + } + try { + await runCli(cmd, [ + "database", + "trace-command", + "--use-build-mode", + "--working-dir", + process.cwd(), + ...await getTrapCachingExtractorConfigArgsForLang(config, language), + ...getExtractionVerbosityArguments(config.debugMode), + ...getExtraOptionsFromEnv(["database", "trace-command"]), + getCodeQLDatabasePath(config, language) + ]); + } catch (e) { + if (config.buildMode === "autobuild" /* Autobuild */) { + const prefix = `We were unable to automatically build your code. Please change the build mode for this language to manual and specify build steps for your project. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information.`; + throw new ConfigurationError(`${prefix} ${getErrorMessage(e)}`); + } else { + throw e; + } + } + }, + async finalizeDatabase(databasePath, threadsFlag, memoryFlag, enableDebugLogging) { + const args = [ + "database", + "finalize", + "--finalize-dataset", + threadsFlag, + memoryFlag, + ...getExtractionVerbosityArguments(enableDebugLogging), + ...getExtraOptionsFromEnv(["database", "finalize"]), + databasePath + ]; + await runCli(cmd, args); + }, + async resolveLanguages({ + filterToLanguagesWithQueries + } = { filterToLanguagesWithQueries: false }) { + const codeqlArgs = [ + "resolve", + "languages", + "--format=betterjson", + "--extractor-options-verbosity=4", + "--extractor-include-aliases", + ...filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : [], + ...getExtraOptionsFromEnv(["resolve", "languages"]) + ]; + const output = await runCli(cmd, codeqlArgs); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve languages with --format=betterjson: ${e}` + ); + } + }, + async resolveBuildEnvironment(workingDir, language) { + const codeqlArgs = [ + "resolve", + "build-environment", + `--language=${language}`, + "--extractor-include-aliases", + ...getExtraOptionsFromEnv(["resolve", "build-environment"]) + ]; + if (workingDir !== void 0) { + codeqlArgs.push("--working-dir", workingDir); + } + const output = await runCli(cmd, codeqlArgs); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve build-environment: ${e} in +${output}` + ); + } + }, + async databaseRunQueries(databasePath, flags, queries = []) { + const codeqlArgs = [ + "database", + "run-queries", + ...flags, + databasePath, + "--min-disk-free=1024", + // Try to leave at least 1GB free + "-v", + ...queries, + ...getExtraOptionsFromEnv(["database", "run-queries"], { + ignoringOptions: ["--expect-discarded-cache"] + }) + ]; + await runCli(cmd, codeqlArgs); + }, + async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, threadsFlag, verbosityFlag, sarifRunPropertyFlag, automationDetailsId, config, features) { + const shouldExportDiagnostics = await features.getValue( + "export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, + this ); - continue; - } - const patterns = await checkHashPatterns( - codeql, - features, - language, - cacheConfig, - "download", - logger - ); - if (patterns === void 0) { - status.push({ language, hit_kind: "no-hash" /* NoHash */ }); - continue; - } - const primaryKey = await cacheKey2(codeql, features, language, patterns); - const restoreKeys = [ - await cachePrefix2(codeql, features, language) - ]; - logger.info( - `Downloading cache for ${language} with key ${primaryKey} and restore keys ${restoreKeys.join( - ", " - )}` - ); - const start = performance.now(); - const hitKey = await actionsCache4.restoreCache( - await cacheConfig.getDependencyPaths(codeql, features), - primaryKey, - restoreKeys - ); - const download_duration_ms = Math.round(performance.now() - start); - if (hitKey !== void 0) { - logger.info(`Cache hit on key ${hitKey} for ${language}.`); - let hit_kind = "partial" /* Partial */; - if (hitKey === primaryKey) { - hit_kind = "exact" /* Exact */; + const codeqlArgs = [ + "database", + "interpret-results", + threadsFlag, + "--format=sarif-latest", + verbosityFlag, + `--output=${sarifFile}`, + "--print-diagnostics-summary", + "--print-metrics-summary", + "--sarif-add-baseline-file-info", + `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( + config + )}`, + "--sarif-group-rules-by-pack", + "--sarif-include-query-help=always", + "--sublanguage-file-coverage", + ...await getJobRunUuidSarifOptions(), + ...getExtraOptionsFromEnv(["database", "interpret-results"]) + ]; + if (sarifRunPropertyFlag !== void 0) { + codeqlArgs.push(sarifRunPropertyFlag); + } + if (automationDetailsId !== void 0) { + codeqlArgs.push("--sarif-category", automationDetailsId); + } + if (shouldExportDiagnostics) { + codeqlArgs.push("--sarif-include-diagnostics"); + } else { + codeqlArgs.push("--no-sarif-include-diagnostics"); + } + codeqlArgs.push(databasePath); + if (querySuitePaths) { + codeqlArgs.push(...querySuitePaths); + } + return await runCli(cmd, codeqlArgs, { + noStreamStdout: true + }); + }, + async databaseCleanupCluster(config, cleanupLevel) { + for (const language of config.languages) { + const databasePath = getCodeQLDatabasePath(config, language); + const codeqlArgs = [ + "database", + "cleanup", + databasePath, + `--cache-cleanup=${cleanupLevel}`, + ...getExtraOptionsFromEnv(["database", "cleanup"]) + ]; + await runCli(cmd, codeqlArgs); + } + }, + async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) { + const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : []; + const args = [ + "database", + "bundle", + databasePath, + `--output=${outputFilePath}`, + `--name=${databaseName}`, + ...includeDiagnosticsArgs, + ...getExtraOptionsFromEnv(["database", "bundle"], { + ignoringOptions: includeDiagnosticsArgs + }) + ]; + if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) { + args.push( + ...alsoIncludeRelativePaths.flatMap((relativePath2) => [ + "--include", + relativePath2 + ]) + ); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { + const args = [ + "database", + "export-diagnostics", + `${databasePath}`, + "--db-cluster", + // Database is always a cluster for CodeQL versions that support diagnostics. + "--format=sarif-latest", + `--output=${sarifFile}`, + "--sarif-include-diagnostics", + // ExportDiagnosticsEnabled is always true if this command is run. + "-vvv", + ...getExtraOptionsFromEnv(["diagnostics", "export"]) + ]; + if (automationDetailsId !== void 0) { + args.push("--sarif-category", automationDetailsId); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async diagnosticsExport(sarifFile, automationDetailsId, config) { + const args = [ + "diagnostics", + "export", + "--format=sarif-latest", + `--output=${sarifFile}`, + `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( + config + )}`, + ...getExtraOptionsFromEnv(["diagnostics", "export"]) + ]; + if (automationDetailsId !== void 0) { + args.push("--sarif-category", automationDetailsId); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async resolveExtractor(language) { + let extractorPath = ""; + await new toolrunner3.ToolRunner( + cmd, + [ + "resolve", + "extractor", + "--format=json", + `--language=${language}`, + "--extractor-include-aliases", + ...getExtraOptionsFromEnv(["resolve", "extractor"]) + ], + { + silent: true, + listeners: { + stdout: (data) => { + extractorPath += data.toString(); + }, + stderr: (data) => { + process.stderr.write(data); + } + } + } + ).exec(); + return JSON.parse(extractorPath); + }, + async resolveQueriesStartingPacks(queries) { + const codeqlArgs = [ + "resolve", + "queries", + "--format=startingpacks", + ...getExtraOptionsFromEnv(["resolve", "queries"]), + ...queries + ]; + const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve queries --format=startingpacks: ${e}` + ); + } + }, + async resolveDatabase(databasePath) { + const codeqlArgs = [ + "resolve", + "database", + databasePath, + "--format=json", + ...getExtraOptionsFromEnv(["resolve", "database"]) + ]; + const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve database --format=json: ${e}` + ); + } + }, + async mergeResults(sarifFiles, outputFile, { + mergeRunsFromEqualCategory = false + }) { + const args = [ + "github", + "merge-results", + "--output", + outputFile, + ...getExtraOptionsFromEnv(["github", "merge-results"]) + ]; + for (const sarifFile of sarifFiles) { + args.push("--sarif", sarifFile); } - status.push({ - language, - hit_kind, - download_duration_ms - }); - restoredKeys.push(hitKey); - } else { - status.push({ language, hit_kind: "miss" /* Miss */ }); - logger.info(`No suitable cache found for ${language}.`); - } - } - return { statusReport: status, restoredKeys }; -} -async function uploadDependencyCaches(codeql, features, config, logger) { - const status = []; - for (const language of config.languages) { - const cacheConfig = defaultCacheConfigs[language]; - if (cacheConfig === void 0) { - logger.info( - `Skipping upload of dependency cache for ${language} as we have no caching configuration for it.` - ); - continue; - } - const patterns = await checkHashPatterns( - codeql, - features, - language, - cacheConfig, - "upload", - logger - ); - if (patterns === void 0) { - status.push({ language, result: "no-hash" /* NoHash */ }); - continue; - } - const key = await cacheKey2(codeql, features, language, patterns); - if (config.dependencyCachingRestoredKeys.includes(key)) { - status.push({ language, result: "duplicate" /* Duplicate */ }); - continue; + if (mergeRunsFromEqualCategory) { + args.push("--sarif-merge-runs-from-equal-category"); + } + await runCli(cmd, args); } - const size = await getTotalCacheSize( - await cacheConfig.getDependencyPaths(codeql, features), - logger, - true + }; + if (checkVersion && !await codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) { + throw new ConfigurationError( + `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql.getVersion()).version}` ); - if (size === 0) { - status.push({ language, result: "empty" /* Empty */ }); - logger.info( - `Skipping upload of dependency cache for ${language} since it is empty.` - ); - continue; - } - logger.info( - `Uploading cache of size ${size} for ${language} with key ${key}...` + } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { + const result = await codeql.getVersion(); + core12.warning( + `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. + +Alternatively, if you want to continue using CodeQL CLI version ${result.version}, you can replace 'github/codeql-action/*@v${getActionVersion().split(".")[0]}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to continue using this version of the CodeQL Action.` ); - try { - const start = performance.now(); - await actionsCache4.saveCache( - await cacheConfig.getDependencyPaths(codeql, features), - key - ); - const upload_duration_ms = Math.round(performance.now() - start); - status.push({ - language, - result: "stored" /* Stored */, - upload_size_bytes: Math.round(size), - upload_duration_ms - }); - } catch (error3) { - if (error3 instanceof actionsCache4.ReserveCacheError) { - logger.info( - `Not uploading cache for ${language}, because ${key} is already in use.` - ); - logger.debug(error3.message); - status.push({ language, result: "duplicate" /* Duplicate */ }); - } else { - throw error3; - } - } + core12.exportVariable("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); } - return status; + return codeql; } -async function cacheKey2(codeql, features, language, patterns) { - const hash2 = await glob.hashFiles(patterns.join("\n")); - return `${await cachePrefix2(codeql, features, language)}${hash2}`; +function getExtraOptionsFromEnv(paths, { ignoringOptions } = {}) { + const options = getExtraOptionsEnvParam(); + return getExtraOptions(options, paths, []).filter( + (option) => !ignoringOptions?.includes(option) + ); } -async function getFeaturePrefix(codeql, features, language) { - const enabledFeatures = []; - const addFeatureIfEnabled = async (feature) => { - if (await features.getValue(feature, codeql)) { - enabledFeatures.push(feature); - } - }; - if (language === "csharp" /* csharp */) { - await addFeatureIfEnabled("csharp_new_cache_key" /* CsharpNewCacheKey */); - await addFeatureIfEnabled("csharp_cache_bmn" /* CsharpCacheBuildModeNone */); +function asExtraOptions(options, pathInfo) { + if (options === void 0) { + return []; } - if (enabledFeatures.length > 0) { - return `${createCacheKeyHash(enabledFeatures)}-`; + if (!Array.isArray(options)) { + const msg = `The extra options for '${pathInfo.join( + "." + )}' ('${JSON.stringify(options)}') are not in an array.`; + throw new Error(msg); } - return ""; + return options.map((o) => { + const t = typeof o; + if (t !== "string" && t !== "number" && t !== "boolean") { + const msg = `The extra option for '${pathInfo.join( + "." + )}' ('${JSON.stringify(o)}') is not a primitive value.`; + throw new Error(msg); + } + return `${o}`; + }); } -async function cachePrefix2(codeql, features, language) { - const runnerOs = getRequiredEnvParam("RUNNER_OS"); - const customPrefix = process.env["CODEQL_ACTION_DEPENDENCY_CACHE_PREFIX" /* DEPENDENCY_CACHING_PREFIX */]; - let prefix = CODEQL_DEPENDENCY_CACHE_PREFIX; - if (customPrefix !== void 0 && customPrefix.length > 0) { - prefix = `${prefix}-${customPrefix}`; - } - const featurePrefix = await getFeaturePrefix(codeql, features, language); - return `${prefix}-${featurePrefix}${CODEQL_DEPENDENCY_CACHE_VERSION}-${runnerOs}-${language}-`; +function getExtraOptions(options, paths, pathInfo) { + const all = asExtraOptions(options?.["*"], pathInfo.concat("*")); + const specific = paths.length === 0 ? asExtraOptions(options, pathInfo) : getExtraOptions( + options?.[paths[0]], + paths?.slice(1), + pathInfo.concat(paths[0]) + ); + return all.concat(specific); } -async function getDependencyCacheUsage(logger) { +async function runCli(cmd, args = [], opts = {}) { try { - const caches = await listActionsCaches(CODEQL_DEPENDENCY_CACHE_PREFIX); - const totalSize = caches.reduce( - (acc, cache) => acc + (cache.size_in_bytes ?? 0), - 0 - ); - return { count: caches.length, size_bytes: totalSize }; - } catch (err) { - logger.warning( - `Unable to retrieve information about dependency cache usage: ${getErrorMessage(err)}` - ); + return await runTool(cmd, args, opts); + } catch (e) { + if (e instanceof CommandInvocationError) { + throw wrapCliConfigurationError(new CliError(e)); + } + throw e; } - return void 0; } -var internal = { - makePatternCheck -}; - -// src/analyze.ts -var CodeQLAnalysisError = class extends Error { - constructor(queriesStatusReport, message, error3) { - super(message); - this.queriesStatusReport = queriesStatusReport; - this.message = message; - this.error = error3; - this.name = "CodeQLAnalysisError"; - } - queriesStatusReport; - message; - error; -}; -async function setupPythonExtractor(logger) { - const codeqlPython = process.env["CODEQL_PYTHON"]; - if (codeqlPython === void 0 || codeqlPython.length === 0) { - return; - } - logger.warning( - "The CODEQL_PYTHON environment variable is no longer supported. Please remove it from your workflow. This environment variable was originally used to specify a Python executable that included the dependencies of your Python code, however Python analysis no longer uses these dependencies.\nIf you used CODEQL_PYTHON to force the version of Python to analyze as, please use CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION instead, such as 'CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION=2.7' or 'CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION=3.11'." +async function writeCodeScanningConfigFile(config, logger) { + const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); + const augmentedConfig = appendExtraQueryExclusions( + config.extraQueryExclusions, + config.computedConfig ); - return; + logger.info( + `Writing augmented user configuration file to ${codeScanningConfigFile}` + ); + logger.startGroup("Augmented user configuration file contents"); + logger.info(dump(augmentedConfig)); + logger.endGroup(); + fs15.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); + return codeScanningConfigFile; } -async function runExtraction(codeql, features, config, logger) { - for (const language of config.languages) { - if (dbIsFinalized(config, language, logger)) { - logger.debug( - `Database for ${language} has already been finalized, skipping extraction.` - ); - continue; - } - if (await shouldExtractLanguage(codeql, config, language)) { - logger.startGroup(`Extracting ${language}`); - if (language === "python" /* python */) { - await setupPythonExtractor(logger); - } - if (config.buildMode) { - if (language === "cpp" /* cpp */ && config.buildMode === "autobuild" /* Autobuild */) { - await setupCppAutobuild(codeql, logger); - } - if (language === "java" /* java */ && config.buildMode === "none" /* None */) { - process.env["CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_DEPENDENCY_DIR"] = getJavaTempDependencyDir(); - } - if (language === "csharp" /* csharp */ && config.buildMode === "none" /* None */ && await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */)) { - process.env["CODEQL_EXTRACTOR_CSHARP_OPTION_BUILDLESS_DEPENDENCY_DIR"] = getCsharpTempDependencyDir(); - } - await codeql.extractUsingBuildMode(config, language); - } else { - await codeql.extractScannedLanguage(config, language); - } - logger.endGroup(); - } - } +var TRAP_CACHE_SIZE_MB = 1024; +async function getTrapCachingExtractorConfigArgs(config) { + const result = []; + for (const language of config.languages) + result.push( + await getTrapCachingExtractorConfigArgsForLang(config, language) + ); + return result.flat(); +} +async function getTrapCachingExtractorConfigArgsForLang(config, language) { + const cacheDir2 = config.trapCaches[language]; + if (cacheDir2 === void 0) return []; + const write = await isAnalyzingDefaultBranch(); + return [ + `-O=${language}.trap.cache.dir=${cacheDir2}`, + `-O=${language}.trap.cache.bound=${TRAP_CACHE_SIZE_MB}`, + `-O=${language}.trap.cache.write=${write}` + ]; } -async function shouldExtractLanguage(codeql, config, language) { - return config.buildMode === "none" /* None */ || config.buildMode === "autobuild" /* Autobuild */ && process.env["CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */] !== "true" || !config.buildMode && await codeql.isScannedLanguage(language); +function getGeneratedCodeScanningConfigPath(config) { + return path14.resolve(config.tempDir, "user-config.yaml"); } -function dbIsFinalized(config, language, logger) { - const dbPath = getCodeQLDatabasePath(config, language); - try { - const dbInfo = load( - fs16.readFileSync(path15.resolve(dbPath, "codeql-database.yml"), "utf8") +function getExtractionVerbosityArguments(enableDebugLogging) { + return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; +} +function applyAutobuildAzurePipelinesTimeoutFix() { + const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; + process.env["JAVA_TOOL_OPTIONS"] = [ + ...javaToolOptions.split(/\s+/), + "-Dhttp.keepAlive=false", + "-Dmaven.wagon.http.pool=false" + ].join(" "); +} +async function getJobRunUuidSarifOptions() { + const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */]; + return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; +} + +// src/autobuild.ts +async function determineAutobuildLanguages(codeql, config, logger) { + if (config.buildMode === "none" /* None */ || config.buildMode === "manual" /* Manual */) { + logger.info( + `Using build mode "${config.buildMode}", nothing to autobuild. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes" /* CODEQL_BUILD_MODES */} for more information.` ); - return !("inProgress" in dbInfo); - } catch { + return void 0; + } + const autobuildLanguages = await asyncFilter( + config.languages, + async (language) => await codeql.isTracedLanguage(language) + ); + if (autobuildLanguages.length === 0) { + logger.info( + "None of the languages in this project require extra build steps" + ); + return void 0; + } + const autobuildLanguagesWithoutGo = autobuildLanguages.filter( + (l) => l !== "go" /* go */ + ); + const languages = []; + if (autobuildLanguagesWithoutGo[0] !== void 0) { + languages.push(autobuildLanguagesWithoutGo[0]); + } + if (autobuildLanguages.length !== autobuildLanguagesWithoutGo.length) { + languages.push("go" /* go */); + } + logger.debug(`Will autobuild ${languages.join(" and ")}.`); + if (autobuildLanguagesWithoutGo.length > 1) { logger.warning( - `Could not check whether database for ${language} was finalized. Assuming it is not.` + `We will only automatically build ${languages.join( + " and " + )} code. If you wish to scan ${autobuildLanguagesWithoutGo.slice(1).join( + " and " + )}, you must replace the autobuild step of your workflow with custom build steps. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#about-specifying-build-steps-manually" /* SPECIFY_BUILD_STEPS_MANUALLY */} for more information.` ); - return false; } + return languages; } -async function finalizeDatabaseCreation(codeql, features, config, threadsFlag, memoryFlag, logger) { - const extractionStart = import_perf_hooks3.performance.now(); - await runExtraction(codeql, features, config, logger); - const extractionTime = import_perf_hooks3.performance.now() - extractionStart; - const trapImportStart = import_perf_hooks3.performance.now(); - for (const language of config.languages) { - if (dbIsFinalized(config, language, logger)) { +async function setupCppAutobuild(codeql, logger) { + const envVar = featureConfig["cpp_dependency_installation_enabled" /* CppDependencyInstallation */].envVar; + const featureName = "C++ automatic installation of dependencies"; + const gitHubVersion = await getGitHubVersion(); + const repositoryNwo = getRepositoryNwo(); + const features = initFeatures( + gitHubVersion, + repositoryNwo, + getTemporaryDirectory(), + logger + ); + if (await features.getValue("cpp_dependency_installation_enabled" /* CppDependencyInstallation */, codeql)) { + if (process.env["RUNNER_ENVIRONMENT"] === "self-hosted" && process.env[envVar] !== "true") { logger.info( - `There is already a finalized database for ${language} at the location where the CodeQL Action places databases, so we did not create one.` + `Disabling ${featureName} as we are on a self-hosted runner.${getWorkflowEventName() !== "dynamic" ? ` To override this, set the ${envVar} environment variable to 'true' in your workflow. See ${"https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow" /* DEFINE_ENV_VARIABLES */} for more information.` : ""}` ); + core13.exportVariable(envVar, "false"); } else { - logger.startGroup(`Finalizing ${language}`); - await codeql.finalizeDatabase( - getCodeQLDatabasePath(config, language), - threadsFlag, - memoryFlag, - config.debugMode - ); - logger.endGroup(); - } - } - const trapImportTime = import_perf_hooks3.performance.now() - trapImportStart; - return { - scanned_language_extraction_duration_ms: Math.round(extractionTime), - trap_import_duration_ms: Math.round(trapImportTime) - }; -} -async function setupDiffInformedQueryRun(logger) { - return await withGroupAsync( - "Generating diff range extension pack", - async () => { - const diffRanges = readDiffRangesJsonFile(logger); - if (diffRanges === void 0) { - logger.info( - "No precomputed diff ranges found; skipping diff-informed analysis stage." - ); - return void 0; - } - const checkoutPath = getRequiredInput("checkout_path"); - const packDir = writeDiffRangeDataExtensionPack( - logger, - diffRanges, - checkoutPath - ); logger.info( - `Successfully created diff range extension pack at ${packDir}.` + `Enabling ${featureName}. This can be disabled by setting the ${envVar} environment variable to 'false'. See ${"https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow" /* DEFINE_ENV_VARIABLES */} for more information.` ); - return packDir; + core13.exportVariable(envVar, "true"); } - ); -} -function diffRangeExtensionPackContents(ranges, checkoutPath) { - const header = ` -extensions: - - addsTo: - pack: codeql/util - extensible: restrictAlertsTo - checkPresence: false - data: -`; - let data = ranges.map((range2) => { - const filename = path15.join(checkoutPath, range2.path).replaceAll(path15.sep, "/"); - return ` - [${dump(filename, { quoteStyle: "single" }).trim()}, ${range2.startLine}, ${range2.endLine}] -`; - }).join(""); - if (!data) { - data = ' - ["", 0, 0]\n'; + } else { + logger.info(`Disabling ${featureName}.`); + core13.exportVariable(envVar, "false"); } - return header + data; } -function writeDiffRangeDataExtensionPack(logger, ranges, checkoutPath) { - if (ranges.length === 0) { - ranges = [{ path: "", startLine: 0, endLine: 0 }]; +async function runAutobuild(config, language, logger) { + logger.startGroup(`Attempting to automatically build ${language} code`); + const codeQL = await getCodeQL(config.codeQLCmd); + if (language === "cpp" /* cpp */) { + await setupCppAutobuild(codeQL, logger); } - const diffRangeDir = path15.join(getTemporaryDirectory(), "pr-diff-range"); - fs16.mkdirSync(diffRangeDir, { recursive: true }); - fs16.writeFileSync( - path15.join(diffRangeDir, "qlpack.yml"), - ` -name: codeql-action/pr-diff-range -version: 0.0.0 -library: true -extensionTargets: - codeql/util: '*' -dataExtensions: - - pr-diff-range.yml -` - ); - const extensionContents = diffRangeExtensionPackContents( - ranges, - checkoutPath - ); - const extensionFilePath = path15.join(diffRangeDir, "pr-diff-range.yml"); - fs16.writeFileSync(extensionFilePath, extensionContents); - logger.debug( - `Wrote pr-diff-range extension pack to ${extensionFilePath}: -${extensionContents}` - ); - return diffRangeDir; + if (config.buildMode) { + await codeQL.extractUsingBuildMode(config, language); + } else { + await codeQL.runAutobuild(config, language); + } + if (language === "go" /* go */) { + core13.exportVariable("CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */, "true"); + } + logger.endGroup(); } -var defaultSuites = /* @__PURE__ */ new Set([ - "security-experimental", - "security-extended", - "security-and-quality", - "code-quality", - "code-scanning" -]); -function resolveQuerySuiteAlias(language, maybeSuite) { - if (defaultSuites.has(maybeSuite)) { - return `${language}-${maybeSuite}.qls`; + +// src/dependency-caching.ts +var os5 = __toESM(require("os")); +var import_path2 = require("path"); +var actionsCache4 = __toESM(require_cache4()); +var glob = __toESM(require_glob()); +var CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies"; +var CODEQL_DEPENDENCY_CACHE_VERSION = 1; +function getJavaTempDependencyDir() { + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_java", "repository"); +} +async function getJavaDependencyDirs() { + return [ + // Maven + (0, import_path2.join)(os5.homedir(), ".m2", "repository"), + // Gradle + (0, import_path2.join)(os5.homedir(), ".gradle", "caches"), + // CodeQL Java build-mode: none + getJavaTempDependencyDir() + ]; +} +function getCsharpTempDependencyDir() { + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); +} +async function getCsharpDependencyDirs(codeql, features) { + const dirs = [ + // Nuget + (0, import_path2.join)(os5.homedir(), ".nuget", "packages") + ]; + if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { + dirs.push(getCsharpTempDependencyDir()); } - return maybeSuite; + return dirs; } -function addSarifExtension(analysis, base) { - return `${base}${analysis.sarifExtension}`; +async function makePatternCheck(patterns) { + const globber = await makeGlobber(patterns); + if ((await globber.glob()).length === 0) { + return void 0; + } + return patterns; } -async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir, automationDetailsId, codeql, config, logger, features) { - const statusReport = {}; - const queryFlags = [memoryFlag, threadsFlag]; - const incrementalMode = []; - if (config.overlayDatabaseMode !== "overlay-base" /* OverlayBase */) { - queryFlags.push("--expect-discarded-cache"); +var CSHARP_BASE_PATTERNS = [ + // NuGet + "**/packages.lock.json", + // Paket + "**/paket.lock" +]; +var CSHARP_EXTRA_PATTERNS = [ + "**/*.csproj", + "**/packages.config", + "**/nuget.config" +]; +async function getCsharpHashPatterns(codeql, features) { + const basePatterns = await internal.makePatternCheck(CSHARP_BASE_PATTERNS); + if (basePatterns !== void 0) { + return basePatterns; } - statusReport.analysis_is_diff_informed = diffRangePackDir !== void 0; - if (diffRangePackDir) { - queryFlags.push(`--additional-packs=${diffRangePackDir}`); - queryFlags.push("--extension-packs=codeql-action/pr-diff-range"); - incrementalMode.push("diff-informed"); + if (await features.getValue("csharp_new_cache_key" /* CsharpNewCacheKey */, codeql)) { + return internal.makePatternCheck(CSHARP_EXTRA_PATTERNS); } - statusReport.analysis_is_overlay = config.overlayDatabaseMode === "overlay" /* Overlay */; - statusReport.analysis_builds_overlay_base_database = config.overlayDatabaseMode === "overlay-base" /* OverlayBase */; - if (config.overlayDatabaseMode === "overlay" /* Overlay */) { - incrementalMode.push("overlay"); + return void 0; +} +var defaultCacheConfigs = { + java: { + getDependencyPaths: getJavaDependencyDirs, + getHashPatterns: async () => internal.makePatternCheck([ + // Maven + "**/pom.xml", + // Gradle + "**/*.gradle*", + "**/gradle-wrapper.properties", + "buildSrc/**/Versions.kt", + "buildSrc/**/Dependencies.kt", + "gradle/*.versions.toml", + "**/versions.properties" + ]) + }, + csharp: { + getDependencyPaths: getCsharpDependencyDirs, + getHashPatterns: getCsharpHashPatterns + }, + go: { + getDependencyPaths: async () => [(0, import_path2.join)(os5.homedir(), "go", "pkg", "mod")], + getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) } - const sarifRunPropertyFlag = incrementalMode.length > 0 ? `--sarif-run-property=incrementalMode=${incrementalMode.join(",")}` : void 0; - const dbAnalysisConfig = getPrimaryAnalysisConfig(config); - for (const language of config.languages) { - try { - const queries = []; - if (config.analysisKinds.length > 1) { - queries.push(getGeneratedSuitePath(config, language)); - if (isCodeQualityEnabled(config)) { - for (const qualityQuery of codeQualityQueries) { - queries.push(resolveQuerySuiteAlias(language, qualityQuery)); - } - } - } - logger.startGroup(`Running queries for ${language}`); - const startTimeRunQueries = (/* @__PURE__ */ new Date()).getTime(); - const databasePath = getCodeQLDatabasePath(config, language); - await codeql.databaseRunQueries(databasePath, queryFlags, queries); - logger.debug(`Finished running queries for ${language}.`); - statusReport[`analyze_builtin_queries_${language}_duration_ms`] = (/* @__PURE__ */ new Date()).getTime() - startTimeRunQueries; - const startTimeInterpretResults = /* @__PURE__ */ new Date(); - const { summary: analysisSummary, sarifFile } = await runInterpretResultsFor( - dbAnalysisConfig, - language, - void 0, - config.debugMode +}; +async function makeGlobber(patterns) { + return glob.create(patterns.join("\n")); +} +async function checkHashPatterns(codeql, features, language, cacheConfig, checkType, logger) { + const patterns = await cacheConfig.getHashPatterns(codeql, features); + if (patterns === void 0) { + logger.info( + `Skipping ${checkType} of dependency cache for ${language} as we cannot calculate a hash for the cache key.` + ); + } + return patterns; +} +async function downloadDependencyCaches(codeql, features, languages, logger) { + const status = []; + const restoredKeys = []; + for (const language of languages) { + const cacheConfig = defaultCacheConfigs[language]; + if (cacheConfig === void 0) { + logger.info( + `Skipping download of dependency cache for ${language} as we have no caching configuration for it.` ); - let qualityAnalysisSummary; - if (config.analysisKinds.length > 1 && isCodeQualityEnabled(config)) { - const qualityResult = await runInterpretResultsFor( - CodeQuality, - language, - codeQualityQueries.map( - (i) => resolveQuerySuiteAlias(language, i) - ), - config.debugMode - ); - qualityAnalysisSummary = qualityResult.summary; - } - const endTimeInterpretResults = /* @__PURE__ */ new Date(); - statusReport[`interpret_results_${language}_duration_ms`] = endTimeInterpretResults.getTime() - startTimeInterpretResults.getTime(); - logger.endGroup(); - if (analysisSummary.trim()) { - logger.info(analysisSummary); - } - if (qualityAnalysisSummary?.trim()) { - logger.info(qualityAnalysisSummary); - } - if (!config.enableFileCoverageInformation) { - logger.info( - "To speed up pull request analysis, file coverage information is only enabled when analyzing the default branch and protected branches." - ); - } - if (await features.getValue("qa_telemetry_enabled" /* QaTelemetryEnabled */)) { - const perQueryAlertCounts = getPerQueryAlertCounts(sarifFile); - const perQueryAlertCountEventReport = { - event: "codeql database interpret-results", - started_at: startTimeInterpretResults.toISOString(), - completed_at: endTimeInterpretResults.toISOString(), - exit_status: "success", - language, - properties: { - alertCounts: perQueryAlertCounts - } - }; - if (statusReport["event_reports"] === void 0) { - statusReport["event_reports"] = []; - } - statusReport["event_reports"].push(perQueryAlertCountEventReport); + continue; + } + const patterns = await checkHashPatterns( + codeql, + features, + language, + cacheConfig, + "download", + logger + ); + if (patterns === void 0) { + status.push({ language, hit_kind: "no-hash" /* NoHash */ }); + continue; + } + const primaryKey = await cacheKey2(codeql, features, language, patterns); + const restoreKeys = [ + await cachePrefix2(codeql, features, language) + ]; + logger.info( + `Downloading cache for ${language} with key ${primaryKey} and restore keys ${restoreKeys.join( + ", " + )}` + ); + const start = performance.now(); + const hitKey = await actionsCache4.restoreCache( + await cacheConfig.getDependencyPaths(codeql, features), + primaryKey, + restoreKeys + ); + const download_duration_ms = Math.round(performance.now() - start); + if (hitKey !== void 0) { + logger.info(`Cache hit on key ${hitKey} for ${language}.`); + let hit_kind = "partial" /* Partial */; + if (hitKey === primaryKey) { + hit_kind = "exact" /* Exact */; } - } catch (e) { - statusReport.analyze_failure_language = language; - throw new CodeQLAnalysisError( - statusReport, - `Error running analysis for ${language}: ${getErrorMessage(e)}`, - wrapError(e) - ); + status.push({ + language, + hit_kind, + download_duration_ms + }); + restoredKeys.push(hitKey); + } else { + status.push({ language, hit_kind: "miss" /* Miss */ }); + logger.info(`No suitable cache found for ${language}.`); } } - return statusReport; - async function runInterpretResultsFor(analysis, language, queries, enableDebugLogging) { - logger.info(`Interpreting ${analysis.name} results for ${language}`); - const category = analysis.fixCategory(logger, automationDetailsId); - const sarifFile = path15.join( - sarifFolder, - addSarifExtension(analysis, language) - ); - const summary = await runInterpretResults( + return { statusReport: status, restoredKeys }; +} +async function uploadDependencyCaches(codeql, features, config, logger) { + const status = []; + for (const language of config.languages) { + const cacheConfig = defaultCacheConfigs[language]; + if (cacheConfig === void 0) { + logger.info( + `Skipping upload of dependency cache for ${language} as we have no caching configuration for it.` + ); + continue; + } + const patterns = await checkHashPatterns( + codeql, + features, language, - queries, - sarifFile, - enableDebugLogging, - category + cacheConfig, + "upload", + logger ); - return { summary, sarifFile }; - } - async function runInterpretResults(language, queries, sarifFile, enableDebugLogging, category) { - const databasePath = getCodeQLDatabasePath(config, language); - return await codeql.databaseInterpretResults( - databasePath, - queries, - sarifFile, - threadsFlag, - enableDebugLogging ? "-vv" : "-v", - sarifRunPropertyFlag, - category, - config, - features + if (patterns === void 0) { + status.push({ language, result: "no-hash" /* NoHash */ }); + continue; + } + const key = await cacheKey2(codeql, features, language, patterns); + if (config.dependencyCachingRestoredKeys.includes(key)) { + status.push({ language, result: "duplicate" /* Duplicate */ }); + continue; + } + const size = await getTotalCacheSize( + await cacheConfig.getDependencyPaths(codeql, features), + logger, + true ); - } - function getPerQueryAlertCounts(sarifPath) { - const sarifObject = JSON.parse( - fs16.readFileSync(sarifPath, "utf8") + if (size === 0) { + status.push({ language, result: "empty" /* Empty */ }); + logger.info( + `Skipping upload of dependency cache for ${language} since it is empty.` + ); + continue; + } + logger.info( + `Uploading cache of size ${size} for ${language} with key ${key}...` ); - const perQueryAlertCounts = {}; - for (const sarifRun of sarifObject.runs) { - if (sarifRun.results) { - for (const result of sarifRun.results) { - const query = result.rule?.id || result.ruleId; - if (query) { - perQueryAlertCounts[query] = (perQueryAlertCounts[query] || 0) + 1; - } - } + try { + const start = performance.now(); + await actionsCache4.saveCache( + await cacheConfig.getDependencyPaths(codeql, features), + key + ); + const upload_duration_ms = Math.round(performance.now() - start); + status.push({ + language, + result: "stored" /* Stored */, + upload_size_bytes: Math.round(size), + upload_duration_ms + }); + } catch (error3) { + if (error3 instanceof actionsCache4.ReserveCacheError) { + logger.info( + `Not uploading cache for ${language}, because ${key} is already in use.` + ); + logger.debug(error3.message); + status.push({ language, result: "duplicate" /* Duplicate */ }); + } else { + throw error3; } } - return perQueryAlertCounts; } + return status; } -async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql, config, logger) { - try { - await fs16.promises.rm(outputDir, { force: true, recursive: true }); - } catch (error3) { - if (error3?.code !== "ENOENT") { - throw error3; +async function cacheKey2(codeql, features, language, patterns) { + const hash2 = await glob.hashFiles(patterns.join("\n")); + return `${await cachePrefix2(codeql, features, language)}${hash2}`; +} +async function getFeaturePrefix(codeql, features, language) { + const enabledFeatures = []; + const addFeatureIfEnabled = async (feature) => { + if (await features.getValue(feature, codeql)) { + enabledFeatures.push(feature); } + }; + if (language === "csharp" /* csharp */) { + await addFeatureIfEnabled("csharp_new_cache_key" /* CsharpNewCacheKey */); + await addFeatureIfEnabled("csharp_cache_bmn" /* CsharpCacheBuildModeNone */); } - await fs16.promises.mkdir(outputDir, { recursive: true }); - const timings = await finalizeDatabaseCreation( - codeql, - features, - config, - threadsFlag, - memoryFlag, - logger - ); - if (process.env["CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */] !== "true") { - await endTracingForCluster(codeql, config, logger); + if (enabledFeatures.length > 0) { + return `${createCacheKeyHash(enabledFeatures)}-`; } - return timings; + return ""; } -async function warnIfGoInstalledAfterInit(config, logger) { - const goInitPath = process.env["CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */]; - if (process.env["CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */] !== "true" && goInitPath !== void 0) { - const goBinaryPath = await io5.which("go", true); - if (goInitPath !== goBinaryPath) { - logger.warning( - `Expected \`which go\` to return ${goInitPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.` - ); - addDiagnostic( - config, - "go" /* go */, - makeDiagnostic( - "go/workflow/go-installed-after-codeql-init", - "Go was installed after the `codeql-action/init` Action was run", - { - markdownMessage: "To avoid interfering with the CodeQL analysis, perform all installation steps before calling the `github/codeql-action/init` Action.", - visibility: { - statusPage: true, - telemetry: true, - cliSummaryTable: true - }, - severity: "warning" - } - ) - ); - } +async function cachePrefix2(codeql, features, language) { + const runnerOs = getRequiredEnvParam("RUNNER_OS"); + const customPrefix = process.env["CODEQL_ACTION_DEPENDENCY_CACHE_PREFIX" /* DEPENDENCY_CACHING_PREFIX */]; + let prefix = CODEQL_DEPENDENCY_CACHE_PREFIX; + if (customPrefix !== void 0 && customPrefix.length > 0) { + prefix = `${prefix}-${customPrefix}`; } + const featurePrefix = await getFeaturePrefix(codeql, features, language); + return `${prefix}-${featurePrefix}${CODEQL_DEPENDENCY_CACHE_VERSION}-${runnerOs}-${language}-`; } - -// src/database-upload.ts -var fs17 = __toESM(require("fs")); -async function cleanupAndUploadDatabases(repositoryNwo, codeql, config, apiDetails, features, logger) { - if (getRequiredInput("upload-database") !== "true") { - logger.debug("Database upload disabled in workflow. Skipping upload."); - return []; - } - if (!config.analysisKinds.includes("code-scanning" /* CodeScanning */)) { - logger.debug( - `Not uploading database because 'analysis-kinds: ${"code-scanning" /* CodeScanning */}' is not enabled.` +async function getDependencyCacheUsage(logger) { + try { + const caches = await listActionsCaches(CODEQL_DEPENDENCY_CACHE_PREFIX); + const totalSize = caches.reduce( + (acc, cache) => acc + (cache.size_in_bytes ?? 0), + 0 + ); + return { count: caches.length, size_bytes: totalSize }; + } catch (err) { + logger.warning( + `Unable to retrieve information about dependency cache usage: ${getErrorMessage(err)}` ); - return []; - } - if (isInTestMode()) { - logger.debug("In test mode. Skipping database upload."); - return []; } - if (config.gitHubVersion.type !== "GitHub.com" /* DOTCOM */ && config.gitHubVersion.type !== "GitHub Enterprise Cloud with data residency" /* GHEC_DR */) { - logger.debug("Not running against github.com or GHEC-DR. Skipping upload."); - return []; + return void 0; +} +var internal = { + makePatternCheck +}; + +// src/analyze.ts +var CodeQLAnalysisError = class extends Error { + constructor(queriesStatusReport, message, error3) { + super(message); + this.queriesStatusReport = queriesStatusReport; + this.message = message; + this.error = error3; + this.name = "CodeQLAnalysisError"; } - if (!await isAnalyzingDefaultBranch()) { - logger.debug("Not analyzing default branch. Skipping upload."); - return []; + queriesStatusReport; + message; + error; +}; +async function setupPythonExtractor(logger) { + const codeqlPython = process.env["CODEQL_PYTHON"]; + if (codeqlPython === void 0 || codeqlPython.length === 0) { + return; } - const shouldUploadOverlayBase = config.overlayDatabaseMode === "overlay-base" /* OverlayBase */ && await features.getValue("upload_overlay_db_to_api" /* UploadOverlayDbToApi */, codeql); - const cleanupLevel = shouldUploadOverlayBase ? "overlay" /* Overlay */ : "clear" /* Clear */; - await withGroupAsync("Cleaning up databases", async () => { - await codeql.databaseCleanupCluster(config, cleanupLevel); - }); - const reports = []; + logger.warning( + "The CODEQL_PYTHON environment variable is no longer supported. Please remove it from your workflow. This environment variable was originally used to specify a Python executable that included the dependencies of your Python code, however Python analysis no longer uses these dependencies.\nIf you used CODEQL_PYTHON to force the version of Python to analyze as, please use CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION instead, such as 'CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION=2.7' or 'CODEQL_EXTRACTOR_PYTHON_ANALYSIS_VERSION=3.11'." + ); + return; +} +async function runExtraction(codeql, features, config, logger) { for (const language of config.languages) { - let bundledDbSize = void 0; - try { - const bundledDb = await bundleDb(config, language, codeql, language, { - includeDiagnostics: false - }); - bundledDbSize = fs17.statSync(bundledDb).size; - const commitOid = await getCommitOid( - getRequiredInput("checkout_path") + if (dbIsFinalized(config, language, logger)) { + logger.debug( + `Database for ${language} has already been finalized, skipping extraction.` ); - const maxAttempts = 4; - let uploadDurationMs; - for (let attempt = 1; attempt <= maxAttempts; attempt++) { - try { - uploadDurationMs = await uploadBundledDatabase( - repositoryNwo, - language, - commitOid, - bundledDb, - bundledDbSize, - apiDetails - ); - break; - } catch (e) { - const httpError = asHTTPError(e); - const isRetryable = !httpError || !DO_NOT_RETRY_STATUSES.includes(httpError.status); - if (!isRetryable) { - throw e; - } else if (attempt === maxAttempts) { - logger.error( - `Maximum retry attempts exhausted (${attempt}), aborting database upload` - ); - throw e; - } - const backoffMs = 15e3 * Math.pow(2, attempt - 1); - logger.debug( - `Database upload attempt ${attempt} of ${maxAttempts} failed for ${language}: ${getErrorMessage(e)}. Retrying in ${backoffMs / 1e3}s...` - ); - await new Promise((resolve14) => setTimeout(resolve14, backoffMs)); + continue; + } + if (await shouldExtractLanguage(codeql, config, language)) { + logger.startGroup(`Extracting ${language}`); + if (language === "python" /* python */) { + await setupPythonExtractor(logger); + } + if (config.buildMode) { + if (language === "cpp" /* cpp */ && config.buildMode === "autobuild" /* Autobuild */) { + await setupCppAutobuild(codeql, logger); } + if (language === "java" /* java */ && config.buildMode === "none" /* None */) { + process.env["CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_DEPENDENCY_DIR"] = getJavaTempDependencyDir(); + } + if (language === "csharp" /* csharp */ && config.buildMode === "none" /* None */ && await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */)) { + process.env["CODEQL_EXTRACTOR_CSHARP_OPTION_BUILDLESS_DEPENDENCY_DIR"] = getCsharpTempDependencyDir(); + } + await codeql.extractUsingBuildMode(config, language); + } else { + await codeql.extractScannedLanguage(config, language); } - reports.push({ - language, - zipped_upload_size_bytes: bundledDbSize, - is_overlay_base: shouldUploadOverlayBase, - upload_duration_ms: uploadDurationMs - }); - logger.debug(`Successfully uploaded database for ${language}`); - } catch (e) { - logger.warning( - `Failed to upload database for ${language}: ${getErrorMessage(e)}` - ); - reports.push({ - language, - error: getErrorMessage(e), - ...bundledDbSize !== void 0 ? { zipped_upload_size_bytes: bundledDbSize } : {} - }); + logger.endGroup(); } } - if (shouldUploadOverlayBase && !config.debugMode) { - await withGroupAsync( - "Measuring database size at the clear cleanup level", - () => recordClearCleanupSizes(codeql, config, reports, logger) - ); - } - return reports; } -async function recordClearCleanupSizes(codeql, config, reports, logger) { - const startTime = performance.now(); +async function shouldExtractLanguage(codeql, config, language) { + return config.buildMode === "none" /* None */ || config.buildMode === "autobuild" /* Autobuild */ && process.env["CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */] !== "true" || !config.buildMode && await codeql.isScannedLanguage(language); +} +function dbIsFinalized(config, language, logger) { + const dbPath = getCodeQLDatabasePath(config, language); try { - await codeql.databaseCleanupCluster(config, "clear" /* Clear */); - } catch (e) { + const dbInfo = load( + fs16.readFileSync(path15.resolve(dbPath, "codeql-database.yml"), "utf8") + ); + return !("inProgress" in dbInfo); + } catch { logger.warning( - `Failed to clean up databases at the '${"clear" /* Clear */}' level for size measurement: ${getErrorMessage(e)}` + `Could not check whether database for ${language} was finalized. Assuming it is not.` ); - return; + return false; } +} +async function finalizeDatabaseCreation(codeql, features, config, threadsFlag, memoryFlag, logger) { + const extractionStart = import_perf_hooks3.performance.now(); + await runExtraction(codeql, features, config, logger); + const extractionTime = import_perf_hooks3.performance.now() - extractionStart; + const trapImportStart = import_perf_hooks3.performance.now(); for (const language of config.languages) { - const report = reports.find((r) => r.language === language); - if (report === void 0) { - continue; - } - try { - const bundledDb = await bundleDb(config, language, codeql, language, { - includeDiagnostics: false - }); - report.clear_cleanup_zipped_size_bytes = fs17.statSync(bundledDb).size; - logger.debug( - `Database for ${language} is ${report.clear_cleanup_zipped_size_bytes} bytes zipped at the '${"clear" /* Clear */}' cleanup level (vs. ${report.zipped_upload_size_bytes ?? "unknown"} bytes at the '${"overlay" /* Overlay */}' level).` + if (dbIsFinalized(config, language, logger)) { + logger.info( + `There is already a finalized database for ${language} at the location where the CodeQL Action places databases, so we did not create one.` ); - } catch (e) { - logger.warning( - `Failed to measure the '${"clear" /* Clear */}' cleanup database size for ${language}: ${getErrorMessage(e)}` + } else { + logger.startGroup(`Finalizing ${language}`); + await codeql.finalizeDatabase( + getCodeQLDatabasePath(config, language), + threadsFlag, + memoryFlag, + config.debugMode ); + logger.endGroup(); } } - const durationMs = performance.now() - startTime; - for (const report of reports) { - report.clear_cleanup_measurement_duration_ms = durationMs; - } + const trapImportTime = import_perf_hooks3.performance.now() - trapImportStart; + return { + scanned_language_extraction_duration_ms: Math.round(extractionTime), + trap_import_duration_ms: Math.round(trapImportTime) + }; } -async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails) { - const client = getApiClient(); - const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url)); - uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`; - let uploadsBaseUrl = uploadsUrl.toString(); - if (uploadsBaseUrl.endsWith("/")) { - uploadsBaseUrl = uploadsBaseUrl.slice(0, -1); - } - const bundledDbReadStream = fs17.createReadStream(bundledDb); - try { - const startTime = performance.now(); - await client.request( - `POST /repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name&commit_oid=:commit_oid`, - { - baseUrl: uploadsBaseUrl, - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - language, - name: `${language}-database`, - commit_oid: commitOid, - data: bundledDbReadStream, - headers: { - authorization: `token ${apiDetails.auth}`, - "Content-Type": "application/zip", - "Content-Length": bundledDbSize - }, - // Disable `octokit/plugin-retry.js`, since the request body is a ReadStream which can only be consumed once. - request: { - retries: 0 - } +async function setupDiffInformedQueryRun(logger) { + return await withGroupAsync( + "Generating diff range extension pack", + async () => { + const diffRanges = readDiffRangesJsonFile(logger); + if (diffRanges === void 0) { + logger.info( + "No precomputed diff ranges found; skipping diff-informed analysis stage." + ); + return void 0; } - ); - return performance.now() - startTime; - } finally { - bundledDbReadStream.close(); + const checkoutPath = getRequiredInput("checkout_path"); + const packDir = writeDiffRangeDataExtensionPack( + logger, + diffRanges, + checkoutPath + ); + logger.info( + `Successfully created diff range extension pack at ${packDir}.` + ); + return packDir; + } + ); +} +function diffRangeExtensionPackContents(ranges, checkoutPath) { + const header = ` +extensions: + - addsTo: + pack: codeql/util + extensible: restrictAlertsTo + checkPresence: false + data: +`; + let data = ranges.map((range2) => { + const filename = path15.join(checkoutPath, range2.path).replaceAll(path15.sep, "/"); + return ` - [${dump(filename, { quoteStyle: "single" }).trim()}, ${range2.startLine}, ${range2.endLine}] +`; + }).join(""); + if (!data) { + data = ' - ["", 0, 0]\n'; } + return header + data; } - -// src/status-report.ts -var os5 = __toESM(require("os")); -var core12 = __toESM(require_core()); -function isFirstPartyAnalysis(actionName) { - if (actionName !== "upload-sarif" /* UploadSarif */) { - return true; +function writeDiffRangeDataExtensionPack(logger, ranges, checkoutPath) { + if (ranges.length === 0) { + ranges = [{ path: "", startLine: 0, endLine: 0 }]; } - return process.env["CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */] === "true"; + const diffRangeDir = path15.join(getTemporaryDirectory(), "pr-diff-range"); + fs16.mkdirSync(diffRangeDir, { recursive: true }); + fs16.writeFileSync( + path15.join(diffRangeDir, "qlpack.yml"), + ` +name: codeql-action/pr-diff-range +version: 0.0.0 +library: true +extensionTargets: + codeql/util: '*' +dataExtensions: + - pr-diff-range.yml +` + ); + const extensionContents = diffRangeExtensionPackContents( + ranges, + checkoutPath + ); + const extensionFilePath = path15.join(diffRangeDir, "pr-diff-range.yml"); + fs16.writeFileSync(extensionFilePath, extensionContents); + logger.debug( + `Wrote pr-diff-range extension pack to ${extensionFilePath}: +${extensionContents}` + ); + return diffRangeDir; } -function isThirdPartyAnalysis(actionName) { - return !isFirstPartyAnalysis(actionName); +var defaultSuites = /* @__PURE__ */ new Set([ + "security-experimental", + "security-extended", + "security-and-quality", + "code-quality", + "code-scanning" +]); +function resolveQuerySuiteAlias(language, maybeSuite) { + if (defaultSuites.has(maybeSuite)) { + return `${language}-${maybeSuite}.qls`; + } + return maybeSuite; } -var JobStatus = /* @__PURE__ */ ((JobStatus2) => { - JobStatus2["UnknownStatus"] = "JOB_STATUS_UNKNOWN"; - JobStatus2["SuccessStatus"] = "JOB_STATUS_SUCCESS"; - JobStatus2["FailureStatus"] = "JOB_STATUS_FAILURE"; - JobStatus2["ConfigErrorStatus"] = "JOB_STATUS_CONFIGURATION_ERROR"; - return JobStatus2; -})(JobStatus || {}); -function getActionsStatus(error3, otherFailureCause) { - if (error3 || otherFailureCause) { - return error3 instanceof ConfigurationError ? "user-error" : "failure"; - } else { - return "success"; +function addSarifExtension(analysis, base) { + return `${base}${analysis.sarifExtension}`; +} +async function runQueries(sarifFolder, memoryFlag, threadsFlag, diffRangePackDir, automationDetailsId, codeql, config, logger, features) { + const statusReport = {}; + const queryFlags = [memoryFlag, threadsFlag]; + const incrementalMode = []; + if (config.overlayDatabaseMode !== "overlay-base" /* OverlayBase */) { + queryFlags.push("--expect-discarded-cache"); + } + statusReport.analysis_is_diff_informed = diffRangePackDir !== void 0; + if (diffRangePackDir) { + queryFlags.push(`--additional-packs=${diffRangePackDir}`); + queryFlags.push("--extension-packs=codeql-action/pr-diff-range"); + incrementalMode.push("diff-informed"); + } + statusReport.analysis_is_overlay = config.overlayDatabaseMode === "overlay" /* Overlay */; + statusReport.analysis_builds_overlay_base_database = config.overlayDatabaseMode === "overlay-base" /* OverlayBase */; + if (config.overlayDatabaseMode === "overlay" /* Overlay */) { + incrementalMode.push("overlay"); + } + const sarifRunPropertyFlag = incrementalMode.length > 0 ? `--sarif-run-property=incrementalMode=${incrementalMode.join(",")}` : void 0; + const dbAnalysisConfig = getPrimaryAnalysisConfig(config); + for (const language of config.languages) { + try { + const queries = []; + if (config.analysisKinds.length > 1) { + queries.push(getGeneratedSuitePath(config, language)); + if (isCodeQualityEnabled(config)) { + for (const qualityQuery of codeQualityQueries) { + queries.push(resolveQuerySuiteAlias(language, qualityQuery)); + } + } + } + logger.startGroup(`Running queries for ${language}`); + const startTimeRunQueries = (/* @__PURE__ */ new Date()).getTime(); + const databasePath = getCodeQLDatabasePath(config, language); + await codeql.databaseRunQueries(databasePath, queryFlags, queries); + logger.debug(`Finished running queries for ${language}.`); + statusReport[`analyze_builtin_queries_${language}_duration_ms`] = (/* @__PURE__ */ new Date()).getTime() - startTimeRunQueries; + const startTimeInterpretResults = /* @__PURE__ */ new Date(); + const { summary: analysisSummary, sarifFile } = await runInterpretResultsFor( + dbAnalysisConfig, + language, + void 0, + config.debugMode + ); + let qualityAnalysisSummary; + if (config.analysisKinds.length > 1 && isCodeQualityEnabled(config)) { + const qualityResult = await runInterpretResultsFor( + CodeQuality, + language, + codeQualityQueries.map( + (i) => resolveQuerySuiteAlias(language, i) + ), + config.debugMode + ); + qualityAnalysisSummary = qualityResult.summary; + } + const endTimeInterpretResults = /* @__PURE__ */ new Date(); + statusReport[`interpret_results_${language}_duration_ms`] = endTimeInterpretResults.getTime() - startTimeInterpretResults.getTime(); + logger.endGroup(); + if (analysisSummary.trim()) { + logger.info(analysisSummary); + } + if (qualityAnalysisSummary?.trim()) { + logger.info(qualityAnalysisSummary); + } + if (!config.enableFileCoverageInformation) { + logger.info( + "To speed up pull request analysis, file coverage information is only enabled when analyzing the default branch and protected branches." + ); + } + if (await features.getValue("qa_telemetry_enabled" /* QaTelemetryEnabled */)) { + const perQueryAlertCounts = getPerQueryAlertCounts(sarifFile); + const perQueryAlertCountEventReport = { + event: "codeql database interpret-results", + started_at: startTimeInterpretResults.toISOString(), + completed_at: endTimeInterpretResults.toISOString(), + exit_status: "success", + language, + properties: { + alertCounts: perQueryAlertCounts + } + }; + if (statusReport["event_reports"] === void 0) { + statusReport["event_reports"] = []; + } + statusReport["event_reports"].push(perQueryAlertCountEventReport); + } + } catch (e) { + statusReport.analyze_failure_language = language; + throw new CodeQLAnalysisError( + statusReport, + `Error running analysis for ${language}: ${getErrorMessage(e)}`, + wrapError(e) + ); + } } -} -function getJobStatusDisplayName(status) { - switch (status) { - case "JOB_STATUS_SUCCESS" /* SuccessStatus */: - return "success"; - case "JOB_STATUS_FAILURE" /* FailureStatus */: - return "failure"; - case "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */: - return "configuration error"; - case "JOB_STATUS_UNKNOWN" /* UnknownStatus */: - return "unknown"; - default: - assertNever(status); + return statusReport; + async function runInterpretResultsFor(analysis, language, queries, enableDebugLogging) { + logger.info(`Interpreting ${analysis.name} results for ${language}`); + const category = analysis.fixCategory(logger, automationDetailsId); + const sarifFile = path15.join( + sarifFolder, + addSarifExtension(analysis, language) + ); + const summary = await runInterpretResults( + language, + queries, + sarifFile, + enableDebugLogging, + category + ); + return { summary, sarifFile }; } -} -function setJobStatusIfUnsuccessful(actionStatus) { - if (actionStatus === "user-error") { - core12.exportVariable( - "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, - process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */ + async function runInterpretResults(language, queries, sarifFile, enableDebugLogging, category) { + const databasePath = getCodeQLDatabasePath(config, language); + return await codeql.databaseInterpretResults( + databasePath, + queries, + sarifFile, + threadsFlag, + enableDebugLogging ? "-vv" : "-v", + sarifRunPropertyFlag, + category, + config, + features ); - } else if (actionStatus === "failure" || actionStatus === "aborted") { - core12.exportVariable( - "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, - process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_FAILURE" /* FailureStatus */ + } + function getPerQueryAlertCounts(sarifPath) { + const sarifObject = JSON.parse( + fs16.readFileSync(sarifPath, "utf8") ); + const perQueryAlertCounts = {}; + for (const sarifRun of sarifObject.runs) { + if (sarifRun.results) { + for (const result of sarifRun.results) { + const query = result.rule?.id || result.ruleId; + if (query) { + perQueryAlertCounts[query] = (perQueryAlertCounts[query] || 0) + 1; + } + } + } + } + return perQueryAlertCounts; } } -async function createStatusReportBase(actionName, status, actionStartedAt, config, diskInfo, logger, cause, exception) { +async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql, config, logger) { try { - const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || ""; - const ref = await getRef(); - const jobRunUUID = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */] || ""; - const workflowRunID = getWorkflowRunID(); - const workflowRunAttempt = getWorkflowRunAttempt(); - const workflowName = process.env["GITHUB_WORKFLOW"] || ""; - const jobName = process.env["GITHUB_JOB"] || ""; - const analysis_key = await getAnalysisKey(); - let workflowStartedAt = process.env["CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */]; - if (workflowStartedAt === void 0) { - workflowStartedAt = actionStartedAt.toISOString(); - core12.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt); - } - const runnerOs = getRequiredEnvParam("RUNNER_OS"); - const codeQlCliVersion = getCachedCodeQlVersion(); - const actionRef = process.env["GITHUB_ACTION_REF"] || ""; - const testingEnvironment = getTestingEnvironment(); - if (testingEnvironment) { - core12.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment); + await fs16.promises.rm(outputDir, { force: true, recursive: true }); + } catch (error3) { + if (error3?.code !== "ENOENT") { + throw error3; } - const isSteadyStateDefaultSetupRun = process.env["CODE_SCANNING_IS_STEADY_STATE_DEFAULT_SETUP"] === "true"; - 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: getActionVersion(), - analysis_kinds: config?.analysisKinds?.join(","), - 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, - steady_state_default_setup: isSteadyStateDefaultSetupRun, - testing_environment: testingEnvironment || "", - workflow_name: workflowName, - workflow_run_attempt: workflowRunAttempt, - workflow_run_id: workflowRunID - }; - try { - statusReport.actions_event_name = getWorkflowEventName(); - } catch (e) { + } + await fs16.promises.mkdir(outputDir, { recursive: true }); + const timings = await finalizeDatabaseCreation( + codeql, + features, + config, + threadsFlag, + memoryFlag, + logger + ); + if (process.env["CODEQL_ACTION_AUTOBUILD_DID_COMPLETE_SUCCESSFULLY" /* AUTOBUILD_DID_COMPLETE_SUCCESSFULLY */] !== "true") { + await endTracingForCluster(codeql, config, logger); + } + return timings; +} +async function warnIfGoInstalledAfterInit(config, logger) { + const goInitPath = process.env["CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */]; + if (process.env["CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */] !== "true" && goInitPath !== void 0) { + const goBinaryPath = await io5.which("go", true); + if (goInitPath !== goBinaryPath) { logger.warning( - `Could not determine the workflow event name: ${getErrorMessage(e)}.` + `Expected \`which go\` to return ${goInitPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.` + ); + addDiagnostic( + config, + "go" /* go */, + makeDiagnostic( + "go/workflow/go-installed-after-codeql-init", + "Go was installed after the `codeql-action/init` Action was run", + { + markdownMessage: "To avoid interfering with the CodeQL analysis, perform all installation steps before calling the `github/codeql-action/init` Action.", + visibility: { + statusPage: true, + telemetry: true, + cliSummaryTable: true + }, + severity: "warning" + } + ) ); } - 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; - } - if (cause) { - statusReport.cause = cause; - } - if (exception) { - statusReport.exception = exception; - } - if (status === "success" || status === "failure" || status === "aborted" || status === "user-error") { - statusReport.completed_at = (/* @__PURE__ */ new Date()).toISOString(); - } - const matrix = getRequiredInput("matrix"); - if (matrix) { - statusReport.matrix_vars = matrix; - } - if ("RUNNER_ARCH" in process.env) { - statusReport.runner_arch = process.env["RUNNER_ARCH"]; - } - if (!(runnerOs === "Linux" && isSelfHostedRunner())) { - statusReport.runner_os_release = os5.release(); - } - if (codeQlCliVersion !== void 0) { - statusReport.codeql_version = codeQlCliVersion.version; - } - const imageVersion = process.env["ImageVersion"]; - if (imageVersion) { - statusReport.runner_image_version = imageVersion; - } - return statusReport; - } catch (e) { - logger.warning( - `Failed to gather information for telemetry: ${getErrorMessage(e)}. Will skip sending status report.` - ); - if (isInTestMode()) { - throw e; - } - return void 0; } } -var OUT_OF_DATE_MSG = "CodeQL Action is out-of-date. Please upgrade to the latest version of `codeql-action`."; -var INCOMPATIBLE_MSG = "CodeQL Action version is incompatible with the API endpoint. Please update to a compatible version of `codeql-action`."; -async function sendStatusReport(statusReport) { - setJobStatusIfUnsuccessful(statusReport.status); - const statusReportJSON = JSON.stringify(statusReport); - core12.debug(`Sending status report: ${statusReportJSON}`); - if (isInTestMode()) { - core12.debug("In test mode. Status reports are not uploaded."); - return; + +// src/database-upload.ts +var fs17 = __toESM(require("fs")); +async function cleanupAndUploadDatabases(repositoryNwo, codeql, config, apiDetails, features, logger) { + if (getRequiredInput("upload-database") !== "true") { + logger.debug("Database upload disabled in workflow. Skipping upload."); + return []; } - const nwo = getRepositoryNwo(); - const client = getApiClient(); - try { - await client.request( - "PUT /repos/:owner/:repo/code-scanning/analysis/status", - { - owner: nwo.owner, - repo: nwo.repo, - data: statusReportJSON - } + if (!config.analysisKinds.includes("code-scanning" /* CodeScanning */)) { + logger.debug( + `Not uploading database because 'analysis-kinds: ${"code-scanning" /* CodeScanning */}' is not enabled.` ); - } catch (e) { - const httpError = asHTTPError(e); - if (httpError !== void 0) { - switch (httpError.status) { - case 403: - if (getWorkflowEventName() === "push" && process.env["GITHUB_ACTOR"] === "dependabot[bot]") { - core12.warning( - `Workflows triggered by Dependabot on the "push" event run with read-only access. Uploading CodeQL results requires write access. To use CodeQL 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/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#scanning-on-push" /* SCANNING_ON_PUSH */} for more information on how to configure these events.` - ); - } else { - core12.warning( - `This run of the CodeQL Action does not have permission to access the CodeQL Action API endpoints. This could be because the Action is running on a pull request from a fork. If not, please ensure the workflow has at least the 'security-events: read' permission. Details: ${httpError.message}` + return []; + } + if (isInTestMode()) { + logger.debug("In test mode. Skipping database upload."); + return []; + } + if (config.gitHubVersion.type !== "GitHub.com" /* DOTCOM */ && config.gitHubVersion.type !== "GitHub Enterprise Cloud with data residency" /* GHEC_DR */) { + logger.debug("Not running against github.com or GHEC-DR. Skipping upload."); + return []; + } + if (!await isAnalyzingDefaultBranch()) { + logger.debug("Not analyzing default branch. Skipping upload."); + return []; + } + const shouldUploadOverlayBase = config.overlayDatabaseMode === "overlay-base" /* OverlayBase */ && await features.getValue("upload_overlay_db_to_api" /* UploadOverlayDbToApi */, codeql); + const cleanupLevel = shouldUploadOverlayBase ? "overlay" /* Overlay */ : "clear" /* Clear */; + await withGroupAsync("Cleaning up databases", async () => { + await codeql.databaseCleanupCluster(config, cleanupLevel); + }); + const reports = []; + for (const language of config.languages) { + let bundledDbSize = void 0; + try { + const bundledDb = await bundleDb(config, language, codeql, language, { + includeDiagnostics: false + }); + bundledDbSize = fs17.statSync(bundledDb).size; + const commitOid = await getCommitOid( + getRequiredInput("checkout_path") + ); + const maxAttempts = 4; + let uploadDurationMs; + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + try { + uploadDurationMs = await uploadBundledDatabase( + repositoryNwo, + language, + commitOid, + bundledDb, + bundledDbSize, + apiDetails + ); + break; + } catch (e) { + const httpError = asHTTPError(e); + const isRetryable = !httpError || !DO_NOT_RETRY_STATUSES.includes(httpError.status); + if (!isRetryable) { + throw e; + } else if (attempt === maxAttempts) { + logger.error( + `Maximum retry attempts exhausted (${attempt}), aborting database upload` ); + throw e; } - return; - case 404: - core12.warning(httpError.message); - return; - case 422: - if (getRequiredEnvParam("GITHUB_SERVER_URL") !== GITHUB_DOTCOM_URL) { - core12.debug(INCOMPATIBLE_MSG); - } else { - core12.debug(OUT_OF_DATE_MSG); - } - return; + const backoffMs = 15e3 * Math.pow(2, attempt - 1); + logger.debug( + `Database upload attempt ${attempt} of ${maxAttempts} failed for ${language}: ${getErrorMessage(e)}. Retrying in ${backoffMs / 1e3}s...` + ); + await new Promise((resolve14) => setTimeout(resolve14, backoffMs)); + } } + reports.push({ + language, + zipped_upload_size_bytes: bundledDbSize, + is_overlay_base: shouldUploadOverlayBase, + upload_duration_ms: uploadDurationMs + }); + logger.debug(`Successfully uploaded database for ${language}`); + } catch (e) { + logger.warning( + `Failed to upload database for ${language}: ${getErrorMessage(e)}` + ); + reports.push({ + language, + error: getErrorMessage(e), + ...bundledDbSize !== void 0 ? { zipped_upload_size_bytes: bundledDbSize } : {} + }); } - core12.warning( - `An unexpected error occurred when sending a status report: ${getErrorMessage( - e - )}` + } + if (shouldUploadOverlayBase && !config.debugMode) { + await withGroupAsync( + "Measuring database size at the clear cleanup level", + () => recordClearCleanupSizes(codeql, config, reports, logger) ); } + return reports; } -async function createInitWithConfigStatusReport(config, initStatusReport, configFile, totalCacheSize, overlayBaseDatabaseStats, dependencyCachingResults) { - const languages = config.languages.join(","); - const paths = (config.originalUserInput.paths || []).join(","); - const pathsIgnore = (config.originalUserInput["paths-ignore"] || []).join( - "," - ); - const disableDefaultQueries = config.originalUserInput["disable-default-queries"] ? languages : ""; - const queries = []; - let queriesInput = getOptionalInput("queries")?.trim(); - if (queriesInput === void 0 || queriesInput.startsWith("+")) { - queries.push( - ...(config.originalUserInput.queries || []).map((q) => q.uses) +async function recordClearCleanupSizes(codeql, config, reports, logger) { + const startTime = performance.now(); + try { + await codeql.databaseCleanupCluster(config, "clear" /* Clear */); + } catch (e) { + logger.warning( + `Failed to clean up databases at the '${"clear" /* Clear */}' level for size measurement: ${getErrorMessage(e)}` ); + return; } - if (queriesInput !== void 0) { - queriesInput = queriesInput.startsWith("+") ? queriesInput.slice(1) : queriesInput; - queries.push(...queriesInput.split(",")); + for (const language of config.languages) { + const report = reports.find((r) => r.language === language); + if (report === void 0) { + continue; + } + try { + const bundledDb = await bundleDb(config, language, codeql, language, { + includeDiagnostics: false + }); + report.clear_cleanup_zipped_size_bytes = fs17.statSync(bundledDb).size; + logger.debug( + `Database for ${language} is ${report.clear_cleanup_zipped_size_bytes} bytes zipped at the '${"clear" /* Clear */}' cleanup level (vs. ${report.zipped_upload_size_bytes ?? "unknown"} bytes at the '${"overlay" /* Overlay */}' level).` + ); + } catch (e) { + logger.warning( + `Failed to measure the '${"clear" /* Clear */}' cleanup database size for ${language}: ${getErrorMessage(e)}` + ); + } } - let packs = {}; - if (Array.isArray(config.computedConfig.packs)) { - packs[config.languages[0]] = config.computedConfig.packs; - } else if (config.computedConfig.packs !== void 0) { - packs = config.computedConfig.packs; + const durationMs = performance.now() - startTime; + for (const report of reports) { + report.clear_cleanup_measurement_duration_ms = durationMs; } - return { - ...initStatusReport, - config_file: configFile ?? "", - disable_default_queries: disableDefaultQueries, - paths, - paths_ignore: pathsIgnore, - queries: queries.join(","), - packs: JSON.stringify(packs), - trap_cache_languages: Object.keys(config.trapCaches).join(","), - trap_cache_download_size_bytes: totalCacheSize, - trap_cache_download_duration_ms: Math.round(config.trapCacheDownloadTime), - overlay_base_database_download_size_bytes: overlayBaseDatabaseStats?.databaseSizeBytes, - overlay_base_database_download_duration_ms: overlayBaseDatabaseStats?.databaseDownloadDurationMs, - dependency_caching_restore_results: dependencyCachingResults, - query_filters: JSON.stringify( - config.originalUserInput["query-filters"] ?? [] - ), - registries: JSON.stringify( - parseRegistriesWithoutCredentials(getOptionalInput("registries")) ?? [] - ) - }; } -async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error3, logger) { +async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails) { + const client = getApiClient(); + const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url)); + uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`; + let uploadsBaseUrl = uploadsUrl.toString(); + if (uploadsBaseUrl.endsWith("/")) { + uploadsBaseUrl = uploadsBaseUrl.slice(0, -1); + } + const bundledDbReadStream = fs17.createReadStream(bundledDb); try { - const statusReport = await createStatusReportBase( - actionName, - "failure", - actionStartedAt, - void 0, - void 0, - logger, - `Unhandled CodeQL Action error: ${getErrorMessage(error3)}`, - error3 instanceof Error ? error3.stack : void 0 - ); - if (statusReport !== void 0) { - await sendStatusReport(statusReport); - } - } catch (e) { - logger.warning( - `Failed to send the unhandled error status report: ${getErrorMessage(e)}.` + const startTime = performance.now(); + await client.request( + `POST /repos/:owner/:repo/code-scanning/codeql/databases/:language?name=:name&commit_oid=:commit_oid`, + { + baseUrl: uploadsBaseUrl, + owner: repositoryNwo.owner, + repo: repositoryNwo.repo, + language, + name: `${language}-database`, + commit_oid: commitOid, + data: bundledDbReadStream, + headers: { + authorization: `token ${apiDetails.auth}`, + "Content-Type": "application/zip", + "Content-Length": bundledDbSize + }, + // Disable `octokit/plugin-retry.js`, since the request body is a ReadStream which can only be consumed once. + request: { + retries: 0 + } + } ); - if (isInTestMode()) { - throw e; - } + return performance.now() - startTime; + } finally { + bundledDbReadStream.close(); } } @@ -152230,7 +152253,7 @@ var fs21 = __toESM(require("fs")); var path18 = __toESM(require("path")); var url = __toESM(require("url")); var import_zlib = __toESM(require("zlib")); -var core14 = __toESM(require_core()); +var core15 = __toESM(require_core()); var jsonschema2 = __toESM(require_lib2()); // src/fingerprints.ts @@ -153358,7 +153381,7 @@ async function addFingerprints(sarifLog, sourceRoot, logger) { // src/init.ts var fs19 = __toESM(require("fs")); var path17 = __toESM(require("path")); -var core13 = __toESM(require_core()); +var core14 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io6 = __toESM(require_io()); @@ -153588,7 +153611,7 @@ To opt out of this change, switch to an advanced setup workflow and ${envVarOptO To opt out of this change, ${envVarOptOut}`; } logger.warning(message); - core13.exportVariable("CODEQL_ACTION_DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION" /* DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION */, "true"); + core14.exportVariable("CODEQL_ACTION_DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION" /* DID_LOG_FILE_COVERAGE_ON_PRS_DEPRECATION */, "true"); } // src/sarif/index.ts @@ -153702,7 +153725,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo logger.warning( `Uploading multiple SARIF runs with the same category is deprecated ${deprecationWarningMessage}. Please update your workflow to upload a single run per category. ${deprecationMoreInformationMessage}` ); - core14.exportVariable("CODEQL_MERGE_SARIF_DEPRECATION_WARNING", "true"); + core15.exportVariable("CODEQL_MERGE_SARIF_DEPRECATION_WARNING", "true"); } return combineSarifFiles(sarifFiles, logger); } @@ -153803,13 +153826,13 @@ async function uploadPayload(payload, repositoryNwo, logger, analysis) { if (httpError !== void 0) { switch (httpError.status) { case 403: - core14.warning(httpError.message || GENERIC_403_MSG); + core15.warning(httpError.message || GENERIC_403_MSG); break; case 404: - core14.warning(httpError.message || GENERIC_404_MSG); + core15.warning(httpError.message || GENERIC_404_MSG); break; default: - core14.warning(httpError.message); + core15.warning(httpError.message); break; } } @@ -154247,7 +154270,7 @@ function validateUniqueCategory(sarifLog, sentinelPrefix) { `Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per tool/category. The easiest fix is to specify a unique value for the \`category\` input. If .runs[].automationDetails.id is specified in the sarif file, that will take precedence over your configured \`category\`. Category: (${id ? id : "none"}) Tool: (${tool ? tool : "none"})` ); } - core14.exportVariable(sentinelEnvVar, sentinelEnvVar); + core15.exportVariable(sentinelEnvVar, sentinelEnvVar); } } function sanitize(str) { @@ -154417,7 +154440,7 @@ async function runAutobuildIfLegacyGoWorkflow(config, logger) { ); await runAutobuild(config, "go" /* go */, logger); } -async function run(startedAt) { +async function run({ startedAt, logger }) { let uploadResults = void 0; let runStats = void 0; let config = void 0; @@ -154427,7 +154450,6 @@ async function run(startedAt) { let didUploadTrapCaches = false; let dependencyCacheResults; let databaseUploadResults = []; - const logger = getActionsLogger(); try { initializeEnvironment(getActionVersion()); persistInputs(); @@ -154466,7 +154488,7 @@ async function run(startedAt) { } const apiDetails = getApiDetails(); const outputDir = getRequiredInput("output"); - core15.exportVariable("CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */, outputDir); + core16.exportVariable("CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */, outputDir); const threads = getThreadsFlag( getOptionalInput("threads") || process.env["CODEQL_THREADS"], logger @@ -154518,8 +154540,8 @@ async function run(startedAt) { for (const language of config.languages) { dbLocations[language] = getCodeQLDatabasePath(config, language); } - core15.setOutput("db-locations", dbLocations); - core15.setOutput("sarif-output", import_path4.default.resolve(outputDir)); + core16.setOutput("db-locations", dbLocations); + core16.setOutput("sarif-output", import_path4.default.resolve(outputDir)); const uploadKind = getUploadValue( getOptionalInput("upload") ); @@ -154536,13 +154558,13 @@ async function run(startedAt) { getOptionalInput("post-processed-sarif-path") ); if (uploadResults["code-scanning" /* CodeScanning */] !== void 0) { - core15.setOutput( + core16.setOutput( "sarif-id", uploadResults["code-scanning" /* CodeScanning */].sarifID ); } if (uploadResults["code-quality" /* CodeQuality */] !== void 0) { - core15.setOutput( + core16.setOutput( "quality-sarif-id", uploadResults["code-quality" /* CodeQuality */].sarifID ); @@ -154585,15 +154607,15 @@ async function run(startedAt) { ); } if (getOptionalInput("expect-error") === "true") { - core15.setFailed( + core16.setFailed( `expect-error input was set to true but no error was thrown.` ); } - core15.exportVariable("CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */, "true"); + core16.exportVariable("CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY" /* ANALYZE_DID_COMPLETE_SUCCESSFULLY */, "true"); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); if (getOptionalInput("expect-error") !== "true" || hasBadExpectErrorInput()) { - core15.setFailed(error3.message); + core16.setFailed(error3.message); } await sendStatusReport2( startedAt, @@ -154657,33 +154679,25 @@ async function run(startedAt) { ); } } +var analyze = { + name: "finish" /* Analyze */, + run +}; async function runWrapper() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error3) { - core15.setFailed(`analyze action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport( - "finish" /* Analyze */, - startedAt, - error3, - logger - ); - } + await runInActions(analyze); await checkForTimeout(); } // src/analyze-action-post.ts var fs26 = __toESM(require("fs")); -var core17 = __toESM(require_core()); +var core18 = __toESM(require_core()); // src/debug-artifacts.ts var fs25 = __toESM(require("fs")); var path22 = __toESM(require("path")); var artifact = __toESM(require_artifact2()); var artifactLegacy = __toESM(require_artifact_client2()); -var core16 = __toESM(require_core()); +var core17 = __toESM(require_core()); // node_modules/archiver/lib/core.js var import_fs2 = require("fs"); @@ -156696,7 +156710,7 @@ var import_async = __toESM(require_async(), 1); var import_path6 = require("path"); // node_modules/archiver/lib/error.js -var import_util28 = __toESM(require("util"), 1); +var import_util29 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -156721,7 +156735,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util28.default.inherits(ArchiverError, Error); +import_util29.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); @@ -159416,10 +159430,10 @@ function getArtifactSuffix(matrix) { for (const matrixKey of Object.keys(matrixObject).sort()) suffix += `-${matrixObject[matrixKey]}`; } else { - core16.warning("User-specified `matrix` input is not an object."); + core17.warning("User-specified `matrix` input is not an object."); } } catch { - core16.warning( + core17.warning( "Could not parse user-specified `matrix` input into JSON. The debug artifact will not be named with the user's `matrix` input." ); } @@ -159429,7 +159443,7 @@ function getArtifactSuffix(matrix) { async function uploadDebugArtifacts(logger, toUpload, rootDir, artifactName, ghVariant, codeQlVersion) { const uploadSupported = isSafeArtifactUpload(codeQlVersion); if (!uploadSupported) { - core16.info( + core17.info( `Skipping debug artifact upload because the current CLI does not support safe upload. Please upgrade to CLI v${SafeArtifactUploadVersion} or later.` ); return "upload-not-supported"; @@ -159442,7 +159456,7 @@ async function uploadArtifacts(logger, toUpload, rootDir, artifactName, ghVarian } if (isInTestMode()) { await scanArtifactsForTokens(toUpload, logger); - core16.exportVariable("CODEQL_ACTION_ARTIFACT_SCAN_FINISHED", "true"); + core17.exportVariable("CODEQL_ACTION_ARTIFACT_SCAN_FINISHED", "true"); } const suffix = getArtifactSuffix(getOptionalInput("matrix")); const artifactUploader = await getArtifactUploaderClient(logger, ghVariant); @@ -159458,7 +159472,7 @@ async function uploadArtifacts(logger, toUpload, rootDir, artifactName, ghVarian ); return "upload-successful"; } catch (e) { - core16.warning(`Failed to upload debug artifacts: ${e}`); + core17.warning(`Failed to upload debug artifacts: ${e}`); return "upload-failed"; } } @@ -159481,7 +159495,7 @@ async function createPartialDatabaseBundle(config, language) { config.dbLocation, `${config.debugDatabaseName}-${language}-partial.zip` ); - core16.info( + core17.info( `${config.debugDatabaseName}-${language} is not finalized. Uploading partial database bundle at ${databaseBundlePath}...` ); if (fs25.existsSync(databaseBundlePath)) { @@ -159551,7 +159565,7 @@ async function runWrapper2() { } } } catch (error3) { - core17.setFailed( + core18.setFailed( `analyze post-action step failed: ${getErrorMessage(error3)}` ); } @@ -159559,29 +159573,6 @@ async function runWrapper2() { // src/autobuild-action.ts var core19 = __toESM(require_core()); - -// src/action-common.ts -var core18 = __toESM(require_core()); -async function runInActions(action) { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - const env = getEnv(); - const actionsEnv = getActionsEnv(); - try { - await action.run({ - name: action.name, - startedAt, - logger, - env, - actions: actionsEnv - }); - } catch (error3) { - core18.setFailed(`${action.name} action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); - } -} - -// src/autobuild-action.ts async function sendCompletedStatusReport(config, logger, startedAt, allLanguages, failingLanguage, cause) { initializeEnvironment(getActionVersion()); const status = getActionsStatus(cause, failingLanguage); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index cc2777bc5f..f7cbbaabe3 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -4,6 +4,7 @@ import { performance } from "perf_hooks"; import * as core from "@actions/core"; +import { Action, ActionState, runInActions } from "./action-common"; import * as actionsUtil from "./actions-util"; import * as analyses from "./analyses"; import { @@ -40,7 +41,6 @@ import { createStatusReportBase, DatabaseCreationTimings, getActionsStatus, - sendUnhandledErrorStatusReport, StatusReportBase, } from "./status-report"; import { @@ -212,7 +212,7 @@ async function runAutobuildIfLegacyGoWorkflow(config: Config, logger: Logger) { await runAutobuild(config, BuiltInLanguage.go, logger); } -async function run(startedAt: Date) { +async function run({ startedAt, logger }: ActionState<["Logger"]>) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. @@ -228,7 +228,6 @@ async function run(startedAt: Date) { let didUploadTrapCaches = false; let dependencyCacheResults: DependencyCacheUploadStatusReport | undefined; let databaseUploadResults: DatabaseUploadResult[] = []; - const logger = getActionsLogger(); try { util.initializeEnvironment(actionsUtil.getActionVersion()); @@ -523,19 +522,13 @@ async function run(startedAt: Date) { } } +/** Defines the `analyze` Action. */ +const analyze: Action = { + name: ActionName.Analyze, + run, +}; + export async function runWrapper() { - const startedAt = new Date(); - const logger = getActionsLogger(); - try { - await run(startedAt); - } catch (error) { - core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`); - await sendUnhandledErrorStatusReport( - ActionName.Analyze, - startedAt, - error, - logger, - ); - } + await runInActions(analyze); await util.checkForTimeout(); } From ef29bf2e4320d6273511c93c842e24f5648b8ea6 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 1 Jul 2026 18:55:25 +0100 Subject: [PATCH 14/14] Improve some comments --- src/action-common.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/action-common.ts b/src/action-common.ts index cc9f7d3d7a..69974f0169 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -51,7 +51,10 @@ export type FieldsOf = Fs extends [] /** Describes the state of an Action that has access to the state corresponding to `Fs`. */ export type ActionState = FieldsOf; -/** The type of an Action's main entry point. */ +/** The type of an Action's main entry point. This is a function that is provided + * with a basic `ActionState` object with features that are always available. + * Each Action can then augment the `state` further if additional features are required. + */ export type ActionMain = ( state: ActionState<["Logger", "Env", "Actions"]>, ) => Promise; @@ -64,7 +67,7 @@ export interface Action { run: ActionMain; } -/** A generic entry point that sets up the environment for the `action` and runs it. */ +/** A generic entry point that sets up the basic environment for the `action` and runs it. */ export async function runInActions(action: Action) { const startedAt = new Date(); const logger = getActionsLogger();