From 1f9caf0118e0ac28ca8795236cb9d8db9c5c4658 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 18:37:01 +0100 Subject: [PATCH 01/39] Refactor `jobRunUuid` init into a function Use in `init` and `setup-codeql` actions --- lib/entry-points.js | 102 +++++++++++++++++++------------------ src/init-action.ts | 6 +-- src/setup-codeql-action.ts | 7 ++- src/status-report.ts | 13 +++++ 4 files changed, 70 insertions(+), 58 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 46c44a8183..287d8a127e 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145728,6 +145728,50 @@ function formatDuration(durationMs) { var os3 = __toESM(require("os")); var core7 = __toESM(require_core()); +// 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(); +} + +// node_modules/uuid/dist-node/rng.js +var rnds8 = new Uint8Array(16); +function rng() { + return crypto.getRandomValues(rnds8); +} + +// 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 _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; + } + return unsafeStringify(rnds); +} +var v4_default = v4; + // src/api-client.ts var core5 = __toESM(require_core()); var githubUtils = __toESM(require_utils4()); @@ -146346,6 +146390,12 @@ function getDisplayActionName(actionName) { } return actionName; } +function getJobUUID(logger) { + const jobRunUuid = v4_default(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + core7.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + return jobRunUuid; +} function isFirstPartyAnalysis(actionName) { if (actionName !== "upload-sarif" /* UploadSarif */) { return true; @@ -150068,50 +150118,6 @@ 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(); -} - -// node_modules/uuid/dist-node/rng.js -var rnds8 = new Uint8Array(16); -function rng() { - return crypto.getRandomValues(rnds8); -} - -// 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 _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; - } - return unsafeStringify(rnds); -} -var v4_default = v4; - // src/overlay/caching.ts var fs10 = __toESM(require("fs")); var actionsCache3 = __toESM(require_cache4()); @@ -160751,9 +160757,7 @@ async function run3(actionState) { logger ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - const jobRunUuid = v4_default(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + getJobUUID(logger); core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); sourceRoot = path24.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), @@ -161751,9 +161755,7 @@ async function run6(actionState) { ); const repositoryProperties = repositoryPropertiesResult.orElse({}); const actionStateWithFeatures = { ...actionState, features }; - const jobRunUuid = v4_default(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core24.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + getJobUUID(logger); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", diff --git a/src/init-action.ts b/src/init-action.ts index 4b52ba6ec6..a2ae0918be 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -4,7 +4,6 @@ import * as path from "path"; import * as core from "@actions/core"; 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 { @@ -69,6 +68,7 @@ import { createInitWithConfigStatusReport, createStatusReportBase, getActionsStatus, + getJobUUID, sendStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -256,9 +256,7 @@ async function run( const repositoryProperties = repositoryPropertiesResult.orElse({}); // Create a unique identifier for this run. - const jobRunUuid = uuidV4(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + getJobUUID(logger); core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index b2a9e90f36..810931f672 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -1,5 +1,4 @@ import * as core from "@actions/core"; -import { v4 as uuidV4 } from "uuid"; import { Action, ActionState, runInActions } from "./action-common"; import { @@ -26,6 +25,7 @@ import { InitToolsDownloadFields, createStatusReportBase, getActionsStatus, + getJobUUID, sendStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -140,9 +140,8 @@ async function run( const actionStateWithFeatures = { ...actionState, features }; - const jobRunUuid = uuidV4(); - logger.info(`Job run UUID is ${jobRunUuid}.`); - core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + // Create a unique identifier for this run. + getJobUUID(logger); const statusReportBase = await createStatusReportBase( ActionName.SetupCodeQL, diff --git a/src/status-report.ts b/src/status-report.ts index d9d2a7ba4c..13cfe8ac39 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -1,6 +1,7 @@ import * as os from "os"; import * as core from "@actions/core"; +import { v4 as uuidV4 } from "uuid"; import { getWorkflowEventName, @@ -59,6 +60,18 @@ export function getDisplayActionName(actionName: ActionName): string { return actionName; } +/** + * Creates a UUIDv4 for the analysis and returns it. + * The generated UUID is also exported as an environment variable. + */ +export function getJobUUID(logger: Logger) { + const jobRunUuid = uuidV4(); + logger.info(`Job run UUID is ${jobRunUuid}.`); + + core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + return jobRunUuid; +} + /** * @returns a boolean indicating whether the analysis is considered to be first party. * From c7ae51bb2daea524f6967b00fec6cceaa7b607b5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 18:41:41 +0100 Subject: [PATCH 02/39] Make `ActionState` available and add test --- src/init-action.ts | 2 +- src/setup-codeql-action.ts | 4 ++-- src/status-report.test.ts | 9 +++++++++ src/status-report.ts | 5 +++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/init-action.ts b/src/init-action.ts index a2ae0918be..f1c3916318 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -256,7 +256,7 @@ async function run( const repositoryProperties = repositoryPropertiesResult.orElse({}); // Create a unique identifier for this run. - getJobUUID(logger); + getJobUUID(actionState); core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index 810931f672..d2f8c6104b 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -95,7 +95,7 @@ async function sendCompletedStatusReport( /** The main behaviour of this action. */ async function run( - actionState: ActionState<["Base", "Logger", "Actions"]>, + actionState: ActionState<["Base", "Logger", "Env", "Actions"]>, ): Promise { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. @@ -141,7 +141,7 @@ async function run( const actionStateWithFeatures = { ...actionState, features }; // Create a unique identifier for this run. - getJobUUID(logger); + getJobUUID(actionState); const statusReportBase = await createStatusReportBase( ActionName.SetupCodeQL, diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 9086dd34ef..0d8fe8108e 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -1,5 +1,6 @@ import test from "ava"; import * as sinon from "sinon"; +import * as uuid from "uuid"; import * as actionsUtil from "./actions-util"; import { Config } from "./config-utils"; @@ -12,6 +13,7 @@ import { createInitWithConfigStatusReport, createStatusReportBase, getActionsStatus, + getJobUUID, InitStatusReport, InitWithConfigStatusReport, } from "./status-report"; @@ -20,11 +22,18 @@ import { setupActionsVars, createTestConfig, makeMacro, + callee, } from "./testing-utils"; import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util"; setupTests(test); +test("getJobUUID - generates valid UUIDs", async (t) => { + await callee(getJobUUID) + .withArgs() + .passes((val) => t.true(uuid.validate(val))); +}); + function setupEnvironmentAndStub(tmpDir: string) { setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic", diff --git a/src/status-report.ts b/src/status-report.ts index 13cfe8ac39..08cb05ff93 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -3,6 +3,7 @@ import * as os from "os"; import * as core from "@actions/core"; import { v4 as uuidV4 } from "uuid"; +import type { ActionState } from "./action-common"; import { getWorkflowEventName, getOptionalInput, @@ -64,9 +65,9 @@ export function getDisplayActionName(actionName: ActionName): string { * Creates a UUIDv4 for the analysis and returns it. * The generated UUID is also exported as an environment variable. */ -export function getJobUUID(logger: Logger) { +export function getJobUUID(action: ActionState<["Logger", "ReadOnlyEnv"]>) { const jobRunUuid = uuidV4(); - logger.info(`Job run UUID is ${jobRunUuid}.`); + action.logger.info(`Job run UUID is ${jobRunUuid}.`); core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); return jobRunUuid; From 049af32c592249a000289bd518b3592923901db3 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 18:47:23 +0100 Subject: [PATCH 03/39] Allow `getJobUUID` to retrieve the UUID from the environment --- lib/entry-points.js | 38 ++++++++++++++++++++++++++------------ src/status-report.test.ts | 12 ++++++++++++ src/status-report.ts | 18 ++++++++++++++---- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 287d8a127e..ade2488356 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -30477,7 +30477,7 @@ var require_validator = __commonJS({ Validator3.prototype.getSchema = function getSchema(urn) { return this.schemas[urn]; }; - Validator3.prototype.validate = function validate(instance, schema, options, ctx) { + Validator3.prototype.validate = function validate2(instance, schema, options, ctx) { if (typeof schema !== "boolean" && typeof schema !== "object" || schema === null) { throw new SchemaError("Expected `schema` to be an object or boolean"); } @@ -144595,24 +144595,24 @@ function isNumber(value) { function isStringOrUndefined(value) { return value === void 0 || isString(value); } -function defaultCheck(validate) { - return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate(arg) }); +function defaultCheck(validate2) { + return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate2(arg) }); } -function makeValidator(validate, required = true) { +function makeValidator(validate2, required = true) { return { - validate, - check: defaultCheck(validate), + validate: validate2, + check: defaultCheck(validate2), required }; } var string = makeValidator(isString); var number = makeValidator(isNumber); function array(validator) { - const validate = (val) => { + const validate2 = (val) => { return isArray(val) && val.every((e) => validator.validate(e)); }; return { - validate, + validate: validate2, check: (val, opts, path29) => { const result = successfulCheckSchema(); if (!isArray(val)) { @@ -145728,6 +145728,15 @@ function formatDuration(durationMs) { var os3 = __toESM(require("os")); var core7 = __toESM(require_core()); +// node_modules/uuid/dist-node/regex.js +var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i; + +// node_modules/uuid/dist-node/validate.js +function validate(uuid) { + return typeof uuid === "string" && regex_default.test(uuid); +} +var validate_default = validate; + // node_modules/uuid/dist-node/stringify.js var byteToHex = []; for (let i = 0; i < 256; ++i) { @@ -146390,9 +146399,14 @@ function getDisplayActionName(actionName) { } return actionName; } -function getJobUUID(logger) { +function getJobUUID(action) { + const existingJobRunUuid = action.env.getOptional("JOB_RUN_UUID" /* JOB_RUN_UUID */); + if (existingJobRunUuid !== void 0 && validate_default(existingJobRunUuid)) { + action.logger.info(`Existing job run UUID is ${existingJobRunUuid}.`); + return existingJobRunUuid; + } const jobRunUuid = v4_default(); - logger.info(`Job run UUID is ${jobRunUuid}.`); + action.logger.info(`Job run UUID is ${jobRunUuid}.`); core7.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); return jobRunUuid; } @@ -160757,7 +160771,7 @@ async function run3(actionState) { logger ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - getJobUUID(logger); + getJobUUID(actionState); core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); sourceRoot = path24.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), @@ -161755,7 +161769,7 @@ async function run6(actionState) { ); const repositoryProperties = repositoryPropertiesResult.orElse({}); const actionStateWithFeatures = { ...actionState, features }; - getJobUUID(logger); + getJobUUID(actionState); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 0d8fe8108e..6f2c0164b1 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -31,9 +31,21 @@ setupTests(test); test("getJobUUID - generates valid UUIDs", async (t) => { await callee(getJobUUID) .withArgs() + .logs(t, "Job run UUID is ") .passes((val) => t.true(uuid.validate(val))); }); +test("getJobUUID - retrieves existing job UUIDs", async (t) => { + const existingJobUuid = uuid.v4(); + await callee(getJobUUID) + .withArgs() + .withEnv((env) => { + env.set(EnvVar.JOB_RUN_UUID, existingJobUuid); + }) + .logs(t, `Existing job run UUID is ${existingJobUuid}.`) + .passes(t.deepEqual, existingJobUuid); +}); + function setupEnvironmentAndStub(tmpDir: string) { setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic", diff --git a/src/status-report.ts b/src/status-report.ts index 08cb05ff93..ae1e0172ce 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -1,7 +1,7 @@ import * as os from "os"; import * as core from "@actions/core"; -import { v4 as uuidV4 } from "uuid"; +import * as uuid from "uuid"; import type { ActionState } from "./action-common"; import { @@ -62,11 +62,21 @@ export function getDisplayActionName(actionName: ActionName): string { } /** - * Creates a UUIDv4 for the analysis and returns it. - * The generated UUID is also exported as an environment variable. + * Either creates a UUIDv4 for the analysis or retrieves an existing one from the + * environment and returns it. + * If a new UUID is generated, it is also exported as an environment variable. */ export function getJobUUID(action: ActionState<["Logger", "ReadOnlyEnv"]>) { - const jobRunUuid = uuidV4(); + // Check if we already have a UUID for the analysis and return it if so. + const existingJobRunUuid = action.env.getOptional(EnvVar.JOB_RUN_UUID); + + if (existingJobRunUuid !== undefined && uuid.validate(existingJobRunUuid)) { + action.logger.info(`Existing job run UUID is ${existingJobRunUuid}.`); + return existingJobRunUuid; + } + + // Otherwise generate a new UUID. + const jobRunUuid = uuid.v4(); action.logger.info(`Job run UUID is ${jobRunUuid}.`); core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); From 766928d055114dfca04d7ad722bbc9fe4b928c3e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 18:50:56 +0100 Subject: [PATCH 04/39] Call `getJobUUID` in `start-proxy` The `start-proxy` step precedes `init` in Default Setup --- lib/entry-points.js | 5 +++++ src/start-proxy-action.ts | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ade2488356..6eee65e05d 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -162645,6 +162645,11 @@ async function run7(startedAt) { let features; let language; try { + const action = { + logger, + env: new Env(process.env) + }; + getJobUUID(action); persistInputs(); const tempDir = getTemporaryDirectory(); const proxyLogFilePath = path28.resolve(tempDir, "proxy.log"); diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 3e376ec64f..9da2069df9 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -3,8 +3,10 @@ import * as path from "path"; import * as core from "@actions/core"; +import { ActionState } from "./action-common"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; +import { Env } from "./environment"; import { FeatureEnablement, initFeatures } from "./feature-flags"; import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; import { getActionsLogger, Logger } from "./logging"; @@ -23,7 +25,11 @@ import { import { generateCertificateAuthority } from "./start-proxy/ca"; import { checkProxyEnvironment } from "./start-proxy/environment"; import { checkConnections } from "./start-proxy/reachability"; -import { ActionName, sendUnhandledErrorStatusReport } from "./status-report"; +import { + ActionName, + getJobUUID, + sendUnhandledErrorStatusReport, +} from "./status-report"; import * as util from "./util"; async function run(startedAt: Date) { @@ -35,6 +41,14 @@ async function run(startedAt: Date) { let language: BuiltInLanguage | undefined; try { + const action: ActionState<["Logger", "Env"]> = { + logger, + env: new Env(process.env), + }; + + // Create a unique identifier for this run. + getJobUUID(action); + // Make inputs accessible in the `post` step. actionsUtil.persistInputs(); From e9831f72a27e863fb32ccac5d65261114809b6fd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 24 Jul 2026 17:40:26 +0100 Subject: [PATCH 05/39] Add `getRequiredInput` to `ActionsEnv` --- lib/entry-points.js | 2 +- src/actions-util.ts | 3 ++- src/testing-utils.ts | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 6eee65e05d..35a0b20922 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145383,7 +145383,7 @@ var Failure = class { // src/actions-util.ts function getActionsEnv() { - return { getOptionalInput }; + return { getRequiredInput, getOptionalInput }; } var getRequiredInput = function(name) { const value = core3.getInput(name); diff --git a/src/actions-util.ts b/src/actions-util.ts index 5fd1ebc4fe..6731f8ef4e 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -27,6 +27,7 @@ declare const __CODEQL_ACTION_VERSION__: string; * global functions in tests. */ export interface ActionsEnv { + getRequiredInput: (name: string) => string; getOptionalInput: (name: string) => string | undefined; } @@ -34,7 +35,7 @@ export interface ActionsEnv { * Gets the real `ActionsEnv` used by production code. */ export function getActionsEnv(): ActionsEnv { - return { getOptionalInput }; + return { getRequiredInput, getOptionalInput }; } /** diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 03354653ac..e4fb9adf6f 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -187,6 +187,9 @@ export function getTestEnv(testEnv: NodeJS.ProcessEnv = {}): Env { */ export function getTestActionsEnv(): ActionsEnv { return { + getRequiredInput: (name) => { + throw new Error(`Input required and not supplied: ${name}`); + }, getOptionalInput: () => undefined, }; } From 60834a0cd9645a12daf4e2e76f667afb0f4cbed2 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 24 Jul 2026 22:02:49 +0100 Subject: [PATCH 06/39] Add `exportVariable` to `ActionsEnv` --- lib/entry-points.js | 14 +++++++++----- src/actions-util.ts | 7 ++++++- src/testing-utils.ts | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 35a0b20922..7ad13ddc55 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -21559,7 +21559,7 @@ var require_core = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.platform = exports2.toPlatformPath = exports2.toWin32Path = exports2.toPosixPath = exports2.markdownSummary = exports2.summary = exports2.ExitCode = void 0; - exports2.exportVariable = exportVariable15; + exports2.exportVariable = exportVariable16; exports2.setSecret = setSecret2; exports2.addPath = addPath2; exports2.getInput = getInput2; @@ -21591,7 +21591,7 @@ var require_core = __commonJS({ ExitCode2[ExitCode2["Success"] = 0] = "Success"; ExitCode2[ExitCode2["Failure"] = 1] = "Failure"; })(ExitCode || (exports2.ExitCode = ExitCode = {})); - function exportVariable15(name, val) { + function exportVariable16(name, val) { const convertedVal = (0, utils_1.toCommandValue)(val); process.env[name] = convertedVal; const filePath = process.env["GITHUB_ENV"] || ""; @@ -121026,7 +121026,7 @@ var require_core3 = __commonJS({ ExitCode2[ExitCode2["Success"] = 0] = "Success"; ExitCode2[ExitCode2["Failure"] = 1] = "Failure"; })(ExitCode || (exports2.ExitCode = ExitCode = {})); - function exportVariable15(name, val) { + function exportVariable16(name, val) { const convertedVal = (0, utils_1.toCommandValue)(val); process.env[name] = convertedVal; const filePath = process.env["GITHUB_ENV"] || ""; @@ -121035,7 +121035,7 @@ var require_core3 = __commonJS({ } (0, command_1.issueCommand)("set-env", { name }, convertedVal); } - exports2.exportVariable = exportVariable15; + exports2.exportVariable = exportVariable16; function setSecret2(secret) { (0, command_1.issueCommand)("add-mask", {}, secret); } @@ -145383,7 +145383,11 @@ var Failure = class { // src/actions-util.ts function getActionsEnv() { - return { getRequiredInput, getOptionalInput }; + return { + getRequiredInput, + getOptionalInput, + exportVariable: core3.exportVariable + }; } var getRequiredInput = function(name) { const value = core3.getInput(name); diff --git a/src/actions-util.ts b/src/actions-util.ts index 6731f8ef4e..dd5124620d 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -29,13 +29,18 @@ declare const __CODEQL_ACTION_VERSION__: string; export interface ActionsEnv { getRequiredInput: (name: string) => string; getOptionalInput: (name: string) => string | undefined; + exportVariable: (name: string, value: string) => void; } /** * Gets the real `ActionsEnv` used by production code. */ export function getActionsEnv(): ActionsEnv { - return { getRequiredInput, getOptionalInput }; + return { + getRequiredInput, + getOptionalInput, + exportVariable: core.exportVariable, + }; } /** diff --git a/src/testing-utils.ts b/src/testing-utils.ts index e4fb9adf6f..4402458d82 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -191,6 +191,7 @@ export function getTestActionsEnv(): ActionsEnv { throw new Error(`Input required and not supplied: ${name}`); }, getOptionalInput: () => undefined, + exportVariable: () => {}, }; } From e28cbacfa115612a23d42a9425bfa0aa072443df Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 19:13:35 +0100 Subject: [PATCH 07/39] Test that `getJobUUID` calls `exportVariable` --- lib/entry-points.js | 5 +++-- src/start-proxy-action.ts | 3 ++- src/status-report.test.ts | 14 +++++++++++++- src/status-report.ts | 6 ++++-- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7ad13ddc55..0bc32b8bfa 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146411,7 +146411,7 @@ function getJobUUID(action) { } const jobRunUuid = v4_default(); action.logger.info(`Job run UUID is ${jobRunUuid}.`); - core7.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + action.actions.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); return jobRunUuid; } function isFirstPartyAnalysis(actionName) { @@ -162651,7 +162651,8 @@ async function run7(startedAt) { try { const action = { logger, - env: new Env(process.env) + env: new Env(process.env), + actions: getActionsEnv() }; getJobUUID(action); persistInputs(); diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 9da2069df9..ee587c04df 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -41,9 +41,10 @@ async function run(startedAt: Date) { let language: BuiltInLanguage | undefined; try { - const action: ActionState<["Logger", "Env"]> = { + const action: ActionState<["Logger", "Env", "Actions"]> = { logger, env: new Env(process.env), + actions: actionsUtil.getActionsEnv(), }; // Create a unique identifier for this run. diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 6f2c0164b1..efe272faeb 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -29,10 +29,22 @@ import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util"; setupTests(test); test("getJobUUID - generates valid UUIDs", async (t) => { + const exportVariableStub: sinon.SinonStub<[string, string], void> = + sinon.stub(); + await callee(getJobUUID) .withArgs() + .withActions((env) => { + env.exportVariable = exportVariableStub; + }) .logs(t, "Job run UUID is ") - .passes((val) => t.true(uuid.validate(val))); + .passes((val) => { + t.true(uuid.validate(val)); + + const calls = exportVariableStub.getCalls(); + t.is(calls.length, 1); + t.deepEqual(calls[0].args, [EnvVar.JOB_RUN_UUID, val]); + }); }); test("getJobUUID - retrieves existing job UUIDs", async (t) => { diff --git a/src/status-report.ts b/src/status-report.ts index ae1e0172ce..69cac8a05d 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -66,7 +66,9 @@ export function getDisplayActionName(actionName: ActionName): string { * environment and returns it. * If a new UUID is generated, it is also exported as an environment variable. */ -export function getJobUUID(action: ActionState<["Logger", "ReadOnlyEnv"]>) { +export function getJobUUID( + action: ActionState<["Logger", "ReadOnlyEnv", "Actions"]>, +) { // Check if we already have a UUID for the analysis and return it if so. const existingJobRunUuid = action.env.getOptional(EnvVar.JOB_RUN_UUID); @@ -79,7 +81,7 @@ export function getJobUUID(action: ActionState<["Logger", "ReadOnlyEnv"]>) { const jobRunUuid = uuid.v4(); action.logger.info(`Job run UUID is ${jobRunUuid}.`); - core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); + action.actions.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid); return jobRunUuid; } From 94a12eb6f6fa716ef39d1cd9c61231f08577b870 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Jul 2026 19:14:57 +0100 Subject: [PATCH 08/39] Add a test for invalid values --- src/status-report.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/status-report.test.ts b/src/status-report.test.ts index efe272faeb..9d0c62efb1 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -58,6 +58,18 @@ test("getJobUUID - retrieves existing job UUIDs", async (t) => { .passes(t.deepEqual, existingJobUuid); }); +test("getJobUUID - doesn't retrieve invalid UUIDs", async (t) => { + const existingJobUuid = "not-a-uuid"; + await callee(getJobUUID) + .withArgs() + .withEnv((env) => { + env.set(EnvVar.JOB_RUN_UUID, existingJobUuid); + }) + .logs(t, `Job run UUID is `) + .notLogs(t, `Existing job run UUID is ${existingJobUuid}.`) + .passes(t.notDeepEqual, existingJobUuid); +}); + function setupEnvironmentAndStub(tmpDir: string) { setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic", From 2e251072b0a905f36699df95f6deabbff6a6ec5a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 10:19:14 +0100 Subject: [PATCH 09/39] Use `getEnv()` --- lib/entry-points.js | 2 +- src/start-proxy-action.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 0bc32b8bfa..0f35b11dfd 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -162651,7 +162651,7 @@ async function run7(startedAt) { try { const action = { logger, - env: new Env(process.env), + env: getEnv(), actions: getActionsEnv() }; getJobUUID(action); diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index ee587c04df..67f6d50177 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -6,7 +6,6 @@ import * as core from "@actions/core"; import { ActionState } from "./action-common"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; -import { Env } from "./environment"; import { FeatureEnablement, initFeatures } from "./feature-flags"; import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; import { getActionsLogger, Logger } from "./logging"; @@ -43,7 +42,7 @@ async function run(startedAt: Date) { try { const action: ActionState<["Logger", "Env", "Actions"]> = { logger, - env: new Env(process.env), + env: util.getEnv(), actions: actionsUtil.getActionsEnv(), }; From de57c4a441d83a777b077184c67bfa79f5bd4457 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 10:38:08 +0100 Subject: [PATCH 10/39] Move `registry_types` to `StatusReportBase` --- src/start-proxy.ts | 8 +------- src/status-report.ts | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/start-proxy.ts b/src/start-proxy.ts index 74e0b498c4..caa1b3054a 100644 --- a/src/start-proxy.ts +++ b/src/start-proxy.ts @@ -83,12 +83,6 @@ export class StartProxyError extends Error { } } -interface StartProxyStatus extends StatusReportBase { - // A comma-separated list of registry types which are configured for CodeQL. - // This only includes registry types we support, not all that are configured. - registry_types: string; -} - /** * Sends a status report for the `start-proxy` action indicating a successful outcome. * @@ -112,7 +106,7 @@ export async function sendSuccessStatusReport( logger, ); if (statusReportBase !== undefined) { - const statusReport: StartProxyStatus = { + const statusReport: StatusReportBase = { ...statusReportBase, registry_types: registry_types.join(","), }; diff --git a/src/status-report.ts b/src/status-report.ts index d9d2a7ba4c..c61bbb828b 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -159,6 +159,12 @@ export interface StatusReportBase { ml_powered_javascript_queries?: string; /** Ref that the workflow was triggered on. */ ref: string; + /** + * A comma-separated list of private registry types which are configured for CodeQL. + * This only includes registry types we support (as determined by the `start-proxy` action), + * not all that are configured. + */ + registry_types?: string; /** Action runner hardware architecture (context runner.arch). */ runner_arch?: string; /** Available disk space on the runner, in bytes. */ From aac07d2a4154cf30c74193cd5c01955a5a0d817e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 10:55:46 +0100 Subject: [PATCH 11/39] Include `registry_types` whenever `CODEQL_PROXY_URLS` is set --- lib/entry-points.js | 17 ++++++++++++++ src/status-report.test.ts | 47 ++++++++++++++++++++++++++++++++++++++- src/status-report.ts | 33 ++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 46c44a8183..24a7eb5c70 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146396,6 +146396,22 @@ function setJobStatusIfUnsuccessful(actionStatus) { ); } } +function getRegistryTypesFromEnv(logger, env = getEnv()) { + const value = env.getOptional("CODEQL_PROXY_URLS" /* PROXY_URLS */); + if (value === void 0) { + return void 0; + } + try { + const data = JSON.parse(value); + const types2 = new Set(data.map((r) => r.type)); + return Array.from(types2).sort().join(","); + } catch (err) { + logger.debug( + `Failed to parse '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' containing '${value}': ${getErrorMessage(err)}.` + ); + return void 0; + } +} async function createStatusReportBase(actionName, status, actionStartedAt, config, diskInfo, logger, cause, exception) { try { const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || ""; @@ -146435,6 +146451,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi job_name: jobName, job_run_uuid: jobRunUUID, ref, + registry_types: getRegistryTypesFromEnv(logger), runner_os: runnerOs, started_at: workflowStartedAt, status, diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 9086dd34ef..d8ce1b40b4 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -3,15 +3,17 @@ import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; import { Config } from "./config-utils"; -import { EnvVar } from "./environment"; +import { EnvVar, RegistryProxyVars } from "./environment"; import { BuiltInLanguage } from "./languages"; import { getRunnerLogger } from "./logging"; import { ToolsSource } from "./setup-codeql"; +import type { Registry } from "./start-proxy"; import { ActionName, createInitWithConfigStatusReport, createStatusReportBase, getActionsStatus, + getRegistryTypesFromEnv, InitStatusReport, InitWithConfigStatusReport, } from "./status-report"; @@ -20,11 +22,54 @@ import { setupActionsVars, createTestConfig, makeMacro, + getTestEnv, + RecordingLogger, } from "./testing-utils"; import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util"; setupTests(test); +test("getRegistryTypesFromEnv - gets unique registry types from environment", async (t) => { + const logger = new RecordingLogger(true); + const env = getTestEnv({ + [RegistryProxyVars.PROXY_URLS]: JSON.stringify([ + { type: "git_source", url: "https://example.com" }, + { type: "git_source", url: "https://github.com" }, + { type: "docker_registry", url: "https://registry.example.com" }, + ] satisfies Array>), + }); + + const result = getRegistryTypesFromEnv(logger, env); + t.deepEqual(result, ["git_source", "docker_registry"].sort().join(",")); +}); + +test("getRegistryTypesFromEnv - returns undefined if the env var is not set", async (t) => { + const logger = new RecordingLogger(true); + const env = getTestEnv({}); + + const result = getRegistryTypesFromEnv(logger, env); + t.is(result, undefined); +}); + +test("getRegistryTypesFromEnv - returns undefined if the env var is not valid JSON", async (t) => { + const logger = new RecordingLogger(true); + const env = getTestEnv({ [RegistryProxyVars.PROXY_URLS]: "[" }); + + const result = getRegistryTypesFromEnv(logger, env); + t.is(result, undefined); +}); + +test("getRegistryTypesFromEnv - returns undefined if the env var is unexpected JSON", async (t) => { + const logger = new RecordingLogger(true); + const env = getTestEnv({ + // Top-level object rather than an array of objects. + [RegistryProxyVars.PROXY_URLS]: JSON.stringify({ type: "git_source" }), + }); + + const result = getRegistryTypesFromEnv(logger, env); + t.is(result, undefined); +}); + function setupEnvironmentAndStub(tmpDir: string) { setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic", diff --git a/src/status-report.ts b/src/status-report.ts index c61bbb828b..5778081153 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -17,12 +17,13 @@ import type { ComputedInput, InputName } from "./config/inputs"; import { parseRegistriesWithoutCredentials } from "./config/pack-registries"; import type { DependencyCacheRestoreStatusReport } from "./dependency-caching"; import { DocUrl } from "./doc-url"; -import { EnvVar } from "./environment"; +import { EnvVar, getEnv, ReadOnlyEnv, RegistryProxyVars } from "./environment"; import { getRef } from "./git-utils"; import type { Logger } from "./logging"; import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching"; import { getRepositoryNwo } from "./repository"; import type { ToolsSource } from "./setup-codeql"; +import type { Registry } from "./start-proxy"; import { ConfigurationError, getRequiredEnvParam, @@ -268,6 +269,35 @@ export interface EventReport { started_at: string; } +/** + * Attempts to retrieve a list of private registry types from the `CODEQL_PROXY_URLS` environment + * variable and returns it as a comma-separated string if successful. Returns `undefined` otherwise. + */ +export function getRegistryTypesFromEnv( + logger: Logger, + env: ReadOnlyEnv = getEnv(), +): string | undefined { + // Try to get the value of the environment variable. + const value = env.getOptional(RegistryProxyVars.PROXY_URLS); + + if (value === undefined) { + return undefined; + } + + // Try to parse the JSON we expect to find in it and return the comma-separated list of + // (unique) registry types. + try { + const data = JSON.parse(value) as Registry[]; + const types = new Set(data.map((r) => r.type)); + return Array.from(types).sort().join(","); + } catch (err) { + logger.debug( + `Failed to parse '${RegistryProxyVars.PROXY_URLS}' containing '${value}': ${getErrorMessage(err)}.`, + ); + return undefined; + } +} + /** * Compose a StatusReport. * @@ -330,6 +360,7 @@ export async function createStatusReportBase( job_name: jobName, job_run_uuid: jobRunUUID, ref, + registry_types: getRegistryTypesFromEnv(logger), runner_os: runnerOs, started_at: workflowStartedAt, status, From eb692f8b49def92b0d25277bd2be0639251c8a81 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 10:57:52 +0100 Subject: [PATCH 12/39] Add check to `createStatusReportBase` test --- src/status-report.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/status-report.test.ts b/src/status-report.test.ts index d8ce1b40b4..9d3ce0f555 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -79,6 +79,9 @@ function setupEnvironmentAndStub(tmpDir: string) { process.env[EnvVar.ANALYSIS_KEY] = "analysis-key"; process.env["ImageVersion"] = "2023.05.19.1"; + process.env[RegistryProxyVars.PROXY_URLS] = JSON.stringify([ + { type: "maven_repository" }, + ] satisfies Array>); const getRequiredInput = sinon.stub(actionsUtil, "getRequiredInput"); getRequiredInput.withArgs("matrix").resolves("input/matrix"); @@ -122,6 +125,7 @@ test.serial("createStatusReportBase", async (t) => { t.is(typeof statusReport.job_run_uuid, "string"); t.is(statusReport.languages, "java,swift"); t.is(statusReport.ref, process.env["GITHUB_REF"]!); + t.is(statusReport.registry_types, "maven_repository"); t.is(statusReport.runner_available_disk_space_bytes, 100); t.is(statusReport.runner_image_version, process.env["ImageVersion"]); t.is(statusReport.runner_os, process.env["RUNNER_OS"]!); From e893985e8b57c9f9c845bc3320a4fb540653da70 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 11:19:21 +0100 Subject: [PATCH 13/39] Fix `makeValidator` returning `required: boolean` --- lib/entry-points.js | 4 ++-- src/json/index.ts | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 24a7eb5c70..a69c9c02fd 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -144598,11 +144598,11 @@ function isStringOrUndefined(value) { function defaultCheck(validate) { return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate(arg) }); } -function makeValidator(validate, required = true) { +function makeValidator(validate) { return { validate, check: defaultCheck(validate), - required + required: true }; } var string = makeValidator(isString); diff --git a/src/json/index.ts b/src/json/index.ts index 78923f8bac..f040acc932 100644 --- a/src/json/index.ts +++ b/src/json/index.ts @@ -62,14 +62,11 @@ function defaultCheck( return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate(arg) }); } -function makeValidator( - validate: (arg: unknown) => arg is T, - required: boolean = true, -) { +function makeValidator(validate: (arg: unknown) => arg is T) { return { validate, check: defaultCheck(validate), - required, + required: true, } as const satisfies Validator; } From 51d51e81216d2a2764c063e5c4ca37c12aa92eb9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 11:19:57 +0100 Subject: [PATCH 14/39] Add `boolean` `Validator` to `json` module --- lib/entry-points.js | 8 ++++++-- src/json/index.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index a69c9c02fd..302bff49af 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -92812,10 +92812,10 @@ var require_util12 = __commonJS({ return objectToString(arg) === "[object Array]"; } exports2.isArray = isArray2; - function isBoolean(arg) { + function isBoolean2(arg) { return typeof arg === "boolean"; } - exports2.isBoolean = isBoolean; + exports2.isBoolean = isBoolean2; function isNull(arg) { return arg === null; } @@ -144592,6 +144592,9 @@ function isString(value) { function isNumber(value) { return typeof value === "number"; } +function isBoolean(value) { + return typeof value === "boolean"; +} function isStringOrUndefined(value) { return value === void 0 || isString(value); } @@ -144607,6 +144610,7 @@ function makeValidator(validate) { } var string = makeValidator(isString); var number = makeValidator(isNumber); +var boolean = makeValidator(isBoolean); function array(validator) { const validate = (val) => { return isArray(val) && val.every((e) => validator.validate(e)); diff --git a/src/json/index.ts b/src/json/index.ts index f040acc932..d3d3abac0c 100644 --- a/src/json/index.ts +++ b/src/json/index.ts @@ -35,6 +35,11 @@ export function isNumber(value: unknown): value is number { return typeof value === "number"; } +/** Asserts that `value` is a boolean. */ +export function isBoolean(value: unknown): value is boolean { + return typeof value === "boolean"; +} + /** Asserts that `value` is either a string or undefined. */ export function isStringOrUndefined( value: unknown, @@ -79,6 +84,9 @@ export const string = makeValidator(isString); /** A validator for number fields in schemas. */ export const number = makeValidator(isNumber); +/** A validator for boolean fields in schemas. */ +export const boolean = makeValidator(isBoolean); + /** A validator for arrays. */ export function array(validator: Validator) { const validate = (val: unknown) => { From e55a57b808525a6830cbf9c336f7ae221169a3a3 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 11:21:19 +0100 Subject: [PATCH 15/39] Add `RegistryBase` schema and type --- lib/entry-points.js | 6 ++++++ src/start-proxy/types.ts | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 302bff49af..d52d8169cd 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -161989,6 +161989,12 @@ function credentialToStr(credential) { } return result; } +var registryBaseSchema = { + /** The type of the package registry. */ + type: string, + /** Whether the registry replaces the base registry for the ecosystem. */ + "replaces-base": optional(boolean) +}; function getAddressString(address) { if (address.url === void 0) { return address.host; diff --git a/src/start-proxy/types.ts b/src/start-proxy/types.ts index 13369edbfa..17803e9126 100644 --- a/src/start-proxy/types.ts +++ b/src/start-proxy/types.ts @@ -254,13 +254,19 @@ export function credentialToStr(credential: Credential): string { return result; } -/** A package registry is identified by its type and address. */ -export type Registry = { +/** The schema for `RegistryBase` objects. */ +export const registryBaseSchema = { /** The type of the package registry. */ - type: string; + type: json.string, /** Whether the registry replaces the base registry for the ecosystem. */ - "replaces-base"?: boolean; -} & Address; + "replaces-base": json.optional(json.boolean), +} as const satisfies json.Schema; + +/** Information about a registry, other than its address. */ +export type RegistryBase = json.FromSchema; + +/** A package registry is identified by its type and address. */ +export type Registry = RegistryBase & Address; // If a registry has an `url`, then that takes precedence over the `host` which may or may // not be defined. From 13d4882649ba1a2a6abb6c2303df10658daa41f7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 11:35:46 +0100 Subject: [PATCH 16/39] Validate JSON more --- lib/entry-points.js | 316 ++++++++++++++++++++------------------ src/json/index.ts | 17 ++ src/status-report.test.ts | 26 +++- src/status-report.ts | 22 ++- 4 files changed, 222 insertions(+), 159 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d52d8169cd..53b7f491af 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -96885,7 +96885,7 @@ var require_validators = __commonJS({ throw new ERR_INVALID_ARG_TYPE(name, "a dictionary", value); } }); - var validateArray = hideStackFrames((value, name, minLength = 0) => { + var validateArray2 = hideStackFrames((value, name, minLength = 0) => { if (!ArrayIsArray(value)) { throw new ERR_INVALID_ARG_TYPE(name, "Array", value); } @@ -96895,19 +96895,19 @@ var require_validators = __commonJS({ } }); function validateStringArray(value, name) { - validateArray(value, name); + validateArray2(value, name); for (let i = 0; i < value.length; i++) { validateString(value[i], `${name}[${i}]`); } } function validateBooleanArray(value, name) { - validateArray(value, name); + validateArray2(value, name); for (let i = 0; i < value.length; i++) { validateBoolean(value[i], `${name}[${i}]`); } } function validateAbortSignalArray(value, name) { - validateArray(value, name); + validateArray2(value, name); for (let i = 0; i < value.length; i++) { const signal = value[i]; const indexedName = `${name}[${i}]`; @@ -97003,7 +97003,7 @@ var require_validators = __commonJS({ isInt32, isUint32, parseFileMode, - validateArray, + validateArray: validateArray2, validateStringArray, validateBooleanArray, validateAbortSignalArray, @@ -144692,6 +144692,10 @@ function validateSchema(schema, obj) { const result = checkSchema(schema, obj, { failFast: true }); return result.valid; } +function validateArray(elementSchema, arr) { + const elementValidator = object(elementSchema); + return array(elementValidator).validate(arr); +} function successfulCheckSchema() { return { valid: true, @@ -146343,6 +146347,148 @@ async function getGeneratedFiles(workingDirectory) { return generatedFiles; } +// src/start-proxy/types.ts +var usernameSchema = { + /** The username needed to authenticate to the package registry, if any. */ + username: optionalOrNull(string) +}; +function hasUsername(config) { + return "username" in config; +} +var usernamePasswordSchema = { + /** The password needed to authenticate to the package registry, if any. */ + password: optionalOrNull(string), + ...usernameSchema +}; +function hasUsernameAndPassword(config) { + return hasUsername(config) && "password" in config; +} +var tokenSchema = { + /** The token needed to authenticate to the package registry, if any. */ + token: optionalOrNull(string), + ...usernameSchema +}; +function hasToken(config) { + return "token" in config; +} +function isToken(config) { + return "token" in config && validateSchema(tokenSchema, config); +} +var azureConfigSchema = { + "tenant-id": string, + "client-id": string +}; +function isAzureConfig(config) { + return validateSchema(azureConfigSchema, config); +} +var awsConfigSchema = { + "aws-region": string, + "account-id": string, + "role-name": string, + domain: string, + "domain-owner": string, + audience: optionalOrNull(string) +}; +function isAWSConfig(config) { + return validateSchema(awsConfigSchema, config); +} +var jfrogConfigSchema = { + "jfrog-oidc-provider-name": string, + audience: optionalOrNull(string), + "identity-mapping-name": optionalOrNull(string) +}; +function isJFrogConfig(config) { + return validateSchema(jfrogConfigSchema, config); +} +var cloudsmithConfigSchema = { + namespace: string, + "service-slug": string, + "api-host": string +}; +function isCloudsmithConfig(config) { + return validateSchema(cloudsmithConfigSchema, config); +} +var gcpConfigSchema = { + "workload-identity-provider": string, + "service-account": optionalOrNull(string), + audience: optionalOrNull(string) +}; +function isGCPConfig(config) { + return validateSchema(gcpConfigSchema, config); +} +var oidcSchemas = [ + { schema: azureConfigSchema, name: "Azure" }, + { schema: awsConfigSchema, name: "AWS" }, + { schema: jfrogConfigSchema, name: "JFrog" }, + { schema: cloudsmithConfigSchema, name: "Cloudsmith" }, + { schema: gcpConfigSchema, name: "GCP" } +]; +function credentialToStr(credential) { + let result = `Type: ${credential.type};`; + const appendIfDefined = (name, val) => { + if (isDefined2(val)) { + result += ` ${name}: ${val};`; + } + }; + appendIfDefined("Url", credential.url); + appendIfDefined("Host", credential.host); + if (hasUsername(credential)) { + appendIfDefined("Username", credential.username); + } + if ("password" in credential) { + appendIfDefined( + "Password", + isDefined2(credential.password) ? "***" : void 0 + ); + } + if (hasToken(credential)) { + appendIfDefined("Token", isDefined2(credential.token) ? "***" : void 0); + } + if (isAzureConfig(credential)) { + appendIfDefined("Tenant", credential["tenant-id"]); + appendIfDefined("Client", credential["client-id"]); + } else if (isAWSConfig(credential)) { + appendIfDefined("AWS Region", credential["aws-region"]); + appendIfDefined("AWS Account", credential["account-id"]); + appendIfDefined("AWS Role", credential["role-name"]); + appendIfDefined("AWS Domain", credential.domain); + appendIfDefined("AWS Domain Owner", credential["domain-owner"]); + appendIfDefined("AWS Audience", credential.audience); + } else if (isJFrogConfig(credential)) { + appendIfDefined("JFrog Provider", credential["jfrog-oidc-provider-name"]); + appendIfDefined( + "JFrog Identity Mapping", + credential["identity-mapping-name"] + ); + appendIfDefined("JFrog Audience", credential.audience); + } else if (isCloudsmithConfig(credential)) { + appendIfDefined("Cloudsmith Namespace", credential.namespace); + appendIfDefined("Cloudsmith Service Slug", credential["service-slug"]); + appendIfDefined("Cloudsmith API Host", credential["api-host"]); + } else if (isGCPConfig(credential)) { + appendIfDefined( + "GCP Workload Identity Provider", + credential["workload-identity-provider"] + ); + appendIfDefined("GCP Service Account", credential["service-account"]); + appendIfDefined("GCP Audience", credential.audience); + } + return result; +} +var registryBaseSchema = { + /** The type of the package registry. */ + type: string, + /** Whether the registry replaces the base registry for the ecosystem. */ + "replaces-base": optional(boolean) +}; +function getAddressString(address) { + if (address.url === void 0) { + return address.host; + } else { + return address.url; + } +} + // src/status-report.ts function getDisplayActionName(actionName) { if (actionName === "finish" /* Analyze */) { @@ -146407,11 +146553,23 @@ function getRegistryTypesFromEnv(logger, env = getEnv()) { } try { const data = JSON.parse(value); + if (!isArray(data)) { + logger.debug( + `Expected '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' to contain a JSON array, but got '${typeof data}'.` + ); + return void 0; + } + if (!validateArray(registryBaseSchema, data)) { + logger.debug( + `Expected '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' to contain a JSON array of registry objects, but got something else.` + ); + return void 0; + } const types2 = new Set(data.map((r) => r.type)); return Array.from(types2).sort().join(","); } catch (err) { logger.debug( - `Failed to parse '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' containing '${value}': ${getErrorMessage(err)}.` + `Failed to parse '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}': ${getErrorMessage(err)}.` ); return void 0; } @@ -157400,7 +157558,7 @@ var import_async = __toESM(require_async(), 1); var import_path6 = require("path"); // node_modules/archiver/lib/error.js -var import_util33 = __toESM(require("util"), 1); +var import_util34 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -157425,7 +157583,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util33.default.inherits(ArchiverError, Error); +import_util34.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); @@ -161861,148 +162019,6 @@ var path26 = __toESM(require("path")); var core26 = __toESM(require_core()); var toolcache4 = __toESM(require_tool_cache()); -// src/start-proxy/types.ts -var usernameSchema = { - /** The username needed to authenticate to the package registry, if any. */ - username: optionalOrNull(string) -}; -function hasUsername(config) { - return "username" in config; -} -var usernamePasswordSchema = { - /** The password needed to authenticate to the package registry, if any. */ - password: optionalOrNull(string), - ...usernameSchema -}; -function hasUsernameAndPassword(config) { - return hasUsername(config) && "password" in config; -} -var tokenSchema = { - /** The token needed to authenticate to the package registry, if any. */ - token: optionalOrNull(string), - ...usernameSchema -}; -function hasToken(config) { - return "token" in config; -} -function isToken(config) { - return "token" in config && validateSchema(tokenSchema, config); -} -var azureConfigSchema = { - "tenant-id": string, - "client-id": string -}; -function isAzureConfig(config) { - return validateSchema(azureConfigSchema, config); -} -var awsConfigSchema = { - "aws-region": string, - "account-id": string, - "role-name": string, - domain: string, - "domain-owner": string, - audience: optionalOrNull(string) -}; -function isAWSConfig(config) { - return validateSchema(awsConfigSchema, config); -} -var jfrogConfigSchema = { - "jfrog-oidc-provider-name": string, - audience: optionalOrNull(string), - "identity-mapping-name": optionalOrNull(string) -}; -function isJFrogConfig(config) { - return validateSchema(jfrogConfigSchema, config); -} -var cloudsmithConfigSchema = { - namespace: string, - "service-slug": string, - "api-host": string -}; -function isCloudsmithConfig(config) { - return validateSchema(cloudsmithConfigSchema, config); -} -var gcpConfigSchema = { - "workload-identity-provider": string, - "service-account": optionalOrNull(string), - audience: optionalOrNull(string) -}; -function isGCPConfig(config) { - return validateSchema(gcpConfigSchema, config); -} -var oidcSchemas = [ - { schema: azureConfigSchema, name: "Azure" }, - { schema: awsConfigSchema, name: "AWS" }, - { schema: jfrogConfigSchema, name: "JFrog" }, - { schema: cloudsmithConfigSchema, name: "Cloudsmith" }, - { schema: gcpConfigSchema, name: "GCP" } -]; -function credentialToStr(credential) { - let result = `Type: ${credential.type};`; - const appendIfDefined = (name, val) => { - if (isDefined2(val)) { - result += ` ${name}: ${val};`; - } - }; - appendIfDefined("Url", credential.url); - appendIfDefined("Host", credential.host); - if (hasUsername(credential)) { - appendIfDefined("Username", credential.username); - } - if ("password" in credential) { - appendIfDefined( - "Password", - isDefined2(credential.password) ? "***" : void 0 - ); - } - if (hasToken(credential)) { - appendIfDefined("Token", isDefined2(credential.token) ? "***" : void 0); - } - if (isAzureConfig(credential)) { - appendIfDefined("Tenant", credential["tenant-id"]); - appendIfDefined("Client", credential["client-id"]); - } else if (isAWSConfig(credential)) { - appendIfDefined("AWS Region", credential["aws-region"]); - appendIfDefined("AWS Account", credential["account-id"]); - appendIfDefined("AWS Role", credential["role-name"]); - appendIfDefined("AWS Domain", credential.domain); - appendIfDefined("AWS Domain Owner", credential["domain-owner"]); - appendIfDefined("AWS Audience", credential.audience); - } else if (isJFrogConfig(credential)) { - appendIfDefined("JFrog Provider", credential["jfrog-oidc-provider-name"]); - appendIfDefined( - "JFrog Identity Mapping", - credential["identity-mapping-name"] - ); - appendIfDefined("JFrog Audience", credential.audience); - } else if (isCloudsmithConfig(credential)) { - appendIfDefined("Cloudsmith Namespace", credential.namespace); - appendIfDefined("Cloudsmith Service Slug", credential["service-slug"]); - appendIfDefined("Cloudsmith API Host", credential["api-host"]); - } else if (isGCPConfig(credential)) { - appendIfDefined( - "GCP Workload Identity Provider", - credential["workload-identity-provider"] - ); - appendIfDefined("GCP Service Account", credential["service-account"]); - appendIfDefined("GCP Audience", credential.audience); - } - return result; -} -var registryBaseSchema = { - /** The type of the package registry. */ - type: string, - /** Whether the registry replaces the base registry for the ecosystem. */ - "replaces-base": optional(boolean) -}; -function getAddressString(address) { - if (address.url === void 0) { - return address.host; - } else { - return address.url; - } -} - // src/start-proxy/validation.ts var core25 = __toESM(require_core()); function cloneCredential(schema, obj) { diff --git a/src/json/index.ts b/src/json/index.ts index d3d3abac0c..d8764ec478 100644 --- a/src/json/index.ts +++ b/src/json/index.ts @@ -226,6 +226,23 @@ export function validateSchema< return result.valid; } +/** + * Validates that `arr` is an array whose elements satisfy at least `elementSchema`. + * Additional keys are accepted in each element. + * + * @param elementSchema The schema to validate the elements against. + * @param arr The array to validate. + * @returns Asserts that `arr` has elements of `schema`'s type if validation is successful. + */ +export function validateArray< + S extends Schema, + T extends UnvalidatedArray = Array>, +>(elementSchema: S, arr: UnvalidatedArray): arr is T { + const elementValidator = object(elementSchema); + + return array(elementValidator).validate(arr); +} + export interface CheckSchemaOptions { /** Whether to stop validation after the first error. */ failFast?: boolean; diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 9d3ce0f555..917a2e4d8e 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -61,13 +61,27 @@ test("getRegistryTypesFromEnv - returns undefined if the env var is not valid JS test("getRegistryTypesFromEnv - returns undefined if the env var is unexpected JSON", async (t) => { const logger = new RecordingLogger(true); - const env = getTestEnv({ - // Top-level object rather than an array of objects. - [RegistryProxyVars.PROXY_URLS]: JSON.stringify({ type: "git_source" }), - }); - const result = getRegistryTypesFromEnv(logger, env); - t.is(result, undefined); + t.is( + getRegistryTypesFromEnv( + logger, + getTestEnv({ + // Top-level object rather than an array of objects. + [RegistryProxyVars.PROXY_URLS]: JSON.stringify({ type: "git_source" }), + }), + ), + undefined, + ); + t.is( + getRegistryTypesFromEnv( + logger, + getTestEnv({ + // Object has no "type" key. + [RegistryProxyVars.PROXY_URLS]: JSON.stringify([{}]), + }), + ), + undefined, + ); }); function setupEnvironmentAndStub(tmpDir: string) { diff --git a/src/status-report.ts b/src/status-report.ts index 5778081153..a6b263ee08 100644 --- a/src/status-report.ts +++ b/src/status-report.ts @@ -19,11 +19,12 @@ import type { DependencyCacheRestoreStatusReport } from "./dependency-caching"; import { DocUrl } from "./doc-url"; import { EnvVar, getEnv, ReadOnlyEnv, RegistryProxyVars } from "./environment"; import { getRef } from "./git-utils"; +import * as json from "./json"; import type { Logger } from "./logging"; import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching"; import { getRepositoryNwo } from "./repository"; import type { ToolsSource } from "./setup-codeql"; -import type { Registry } from "./start-proxy"; +import { registryBaseSchema } from "./start-proxy/types"; import { ConfigurationError, getRequiredEnvParam, @@ -287,12 +288,27 @@ export function getRegistryTypesFromEnv( // Try to parse the JSON we expect to find in it and return the comma-separated list of // (unique) registry types. try { - const data = JSON.parse(value) as Registry[]; + const data = JSON.parse(value) as unknown; + + // Check that the parsed JSON meets our expectations. + if (!json.isArray(data)) { + logger.debug( + `Expected '${RegistryProxyVars.PROXY_URLS}' to contain a JSON array, but got '${typeof data}'.`, + ); + return undefined; + } + if (!json.validateArray(registryBaseSchema, data)) { + logger.debug( + `Expected '${RegistryProxyVars.PROXY_URLS}' to contain a JSON array of registry objects, but got something else.`, + ); + return undefined; + } + const types = new Set(data.map((r) => r.type)); return Array.from(types).sort().join(","); } catch (err) { logger.debug( - `Failed to parse '${RegistryProxyVars.PROXY_URLS}' containing '${value}': ${getErrorMessage(err)}.`, + `Failed to parse '${RegistryProxyVars.PROXY_URLS}': ${getErrorMessage(err)}.`, ); return undefined; } From 42a3b947902ef5aef0cda3594c9e0cb60f8f4820 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 11:58:44 +0100 Subject: [PATCH 17/39] Add `CODEQL_ACTION_` prefix to `JOB_RUN_UUID` --- .github/workflows/__job-run-uuid-sarif.yml | 4 ++-- lib/entry-points.js | 8 ++++---- pr-checks/checks/job-run-uuid-sarif.yml | 4 ++-- src/environment.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/__job-run-uuid-sarif.yml b/.github/workflows/__job-run-uuid-sarif.yml index cd47fb577e..429a694947 100644 --- a/.github/workflows/__job-run-uuid-sarif.yml +++ b/.github/workflows/__job-run-uuid-sarif.yml @@ -71,8 +71,8 @@ jobs: run: | cd "$RUNNER_TEMP/results" actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif) - if [[ "$actual" != "$JOB_RUN_UUID" ]]; then - echo "Expected SARIF output to contain job run UUID '$JOB_RUN_UUID', but found '$actual'." + if [[ "$actual" != "$CODEQL_ACTION_JOB_RUN_UUID" ]]; then + echo "Expected SARIF output to contain job run UUID '$CODEQL_ACTION_JOB_RUN_UUID', but found '$actual'." exit 1 else echo "Found job run UUID '$actual'." diff --git a/lib/entry-points.js b/lib/entry-points.js index 0f35b11dfd..a2f6d22c52 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146404,14 +146404,14 @@ function getDisplayActionName(actionName) { return actionName; } function getJobUUID(action) { - const existingJobRunUuid = action.env.getOptional("JOB_RUN_UUID" /* JOB_RUN_UUID */); + const existingJobRunUuid = action.env.getOptional("CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */); if (existingJobRunUuid !== void 0 && validate_default(existingJobRunUuid)) { action.logger.info(`Existing job run UUID is ${existingJobRunUuid}.`); return existingJobRunUuid; } const jobRunUuid = v4_default(); action.logger.info(`Job run UUID is ${jobRunUuid}.`); - action.actions.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); + action.actions.exportVariable("CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); return jobRunUuid; } function isFirstPartyAnalysis(actionName) { @@ -146468,7 +146468,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi try { const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || ""; const ref = await getRef(); - const jobRunUUID = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */] || ""; + const jobRunUUID = process.env["CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */] || ""; const workflowRunID = getWorkflowRunID(); const workflowRunAttempt = getWorkflowRunAttempt(); const workflowName = process.env["GITHUB_WORKFLOW"] || ""; @@ -152008,7 +152008,7 @@ function applyAutobuildAzurePipelinesTimeoutFix() { ].join(" "); } async function getJobRunUuidSarifOptions() { - const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */]; + const jobRunUuid = process.env["CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */]; return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; } diff --git a/pr-checks/checks/job-run-uuid-sarif.yml b/pr-checks/checks/job-run-uuid-sarif.yml index dc1dd02d43..b86725d944 100644 --- a/pr-checks/checks/job-run-uuid-sarif.yml +++ b/pr-checks/checks/job-run-uuid-sarif.yml @@ -21,8 +21,8 @@ steps: run: | cd "$RUNNER_TEMP/results" actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif) - if [[ "$actual" != "$JOB_RUN_UUID" ]]; then - echo "Expected SARIF output to contain job run UUID '$JOB_RUN_UUID', but found '$actual'." + if [[ "$actual" != "$CODEQL_ACTION_JOB_RUN_UUID" ]]; then + echo "Expected SARIF output to contain job run UUID '$CODEQL_ACTION_JOB_RUN_UUID', but found '$actual'." exit 1 else echo "Found job run UUID '$actual'." diff --git a/src/environment.ts b/src/environment.ts index 1b00ab7cfb..fea553d602 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -88,7 +88,7 @@ export enum EnvVar { LOG_VERSION_DEPRECATION = "CODEQL_ACTION_DID_LOG_VERSION_DEPRECATION", /** UUID representing the current job run. */ - JOB_RUN_UUID = "JOB_RUN_UUID", + JOB_RUN_UUID = "CODEQL_ACTION_JOB_RUN_UUID", /** Status for the entire job, submitted to the status report in `init-post` */ JOB_STATUS = "CODEQL_ACTION_JOB_STATUS", From 3ca82bb259b52fe4d0f27055fa58f0fb99694b80 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 12:55:16 +0100 Subject: [PATCH 18/39] Change `withActions` to only allow mutations --- src/config/inputs.test.ts | 18 +++++------------- src/testing-utils.ts | 12 +++++------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/config/inputs.test.ts b/src/config/inputs.test.ts index a91dc258ea..851dd72e2f 100644 --- a/src/config/inputs.test.ts +++ b/src/config/inputs.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import sinon from "sinon"; -import { getActionsEnv } from "../actions-util"; +import { ActionsEnv } from "../actions-util"; import { Feature } from "../feature-flags"; import { RepositoryPropertyName } from "../feature-flags/properties"; import { callee } from "../testing-utils"; @@ -22,32 +22,26 @@ const expectedRepositoryPropertyResult: ComputedInput = { value: "repo-property-input-value", }; -function stubGetToolsInput() { - const actions = getActionsEnv(); +function stubGetToolsInput(actions: ActionsEnv) { sinon .stub(actions, "getOptionalInput") .withArgs(InputName.Tools) .returns(expectedWorkflowResult.value); - return actions; } const workflowLogMessage = `Using ${InputName.Tools} input from workflow:`; test("getToolsInput - returns workflow input if available", async (t) => { - const actions = stubGetToolsInput(); - await callee(getToolsInput) - .withActions(actions) + .withActions(stubGetToolsInput) .withArgs({}) .logs(t, workflowLogMessage) .passes(t.deepEqual, expectedWorkflowResult); }); test("getToolsInput - returns repository property value if enforced", async (t) => { - const actions = stubGetToolsInput(); - const target = callee(getToolsInput) - .withActions(actions) + .withActions(stubGetToolsInput) .withArgs({ [RepositoryPropertyName.TOOLS]: `!${expectedRepositoryPropertyResult.value}`, }); @@ -65,10 +59,8 @@ test("getToolsInput - returns repository property value if enforced", async (t) }); test("getToolsInput - prefers workflow input", async (t) => { - const actions = stubGetToolsInput(); - const target = callee(getToolsInput) - .withActions(actions) + .withActions(stubGetToolsInput) .withArgs({ [RepositoryPropertyName.TOOLS]: expectedRepositoryPropertyResult.value, }); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 4402458d82..553a775e93 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -228,7 +228,8 @@ type DelayedCheck< Fs extends ReadonlyArray, > = (env: Readonly>) => Promise; -export type ValueOrMutation = T | ((val: T) => void); +export type Mutation = (val: T) => void; +export type ValueOrMutation = T | Mutation; /** * Wraps a function that accepts an `ActionState` for testing in different environments. @@ -324,13 +325,10 @@ abstract class BaseEnvBuilder< return result; } - public withActions(arg: ValueOrMutation): this { + /** Applies `fn` to the `ActionsEnv`. */ + public withActions(fn: Mutation): this { const result = this.clone(); - if (typeof arg === "function") { - arg(result.state.actions); - } else { - result.state.actions = arg; - } + fn(result.state.actions); return result; } From 30c33c9286fa4a7c5325301b5a2aa0c5b67a51ec Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 12:56:51 +0100 Subject: [PATCH 19/39] Make results of function call available to delayed checks --- src/testing-utils.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 553a775e93..d6fffb69b1 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -34,11 +34,14 @@ import { ActionName } from "./status-report"; import { DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, + Failure, getEnv, GitHubVariant, GitHubVersion, HTTPError, resetCachedCodeQlVersion, + Result, + Success, } from "./util"; export const SAMPLE_DOTCOM_API_DETAILS = { @@ -226,7 +229,10 @@ type DelayedCheck< Args extends readonly any[], R, Fs extends ReadonlyArray, -> = (env: Readonly>) => Promise; +> = ( + env: Readonly>, + result: Result, ThrownError>, +) => Promise; export type Mutation = (val: T) => void; export type ValueOrMutation = T | Mutation; @@ -441,7 +447,7 @@ class CallableEnvBuilder< // Run other delayed checks. for (const delayedCheck of this.checks) { - await delayedCheck(this); + await delayedCheck(this, new Success(result)); } // Return the results of the function call and the main assertion. @@ -467,7 +473,7 @@ class CallableEnvBuilder< // Run other delayed checks. for (const delayedCheck of this.checks) { - await delayedCheck(this); + await delayedCheck(this, new Failure(error)); } // Return the error. From 36737508ece41f7da5ed9862108928b78f5c24ff Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 13:00:31 +0100 Subject: [PATCH 20/39] Add `Env`-backed `ActionsEnv` implementation for tests --- src/testing-utils.ts | 66 +++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index d6fffb69b1..94c8435218 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -185,17 +185,32 @@ export function getTestEnv(testEnv: NodeJS.ProcessEnv = {}): Env { return getEnv(testEnv); } +/** An implementation of `ActionsEnv` for use in tests. */ +class TestActionsEnv implements ActionsEnv { + constructor(private readonly env: Env) {} + + public clone(env: Env): this { + return Object.create(this, { env: { value: env } }) as this; + } + + public getRequiredInput(name: string): string { + throw new Error(`Input required and not supplied: ${name}`); + } + + public getOptionalInput(_name: string): string | undefined { + return undefined; + } + + public exportVariable(name: string, value: string): void { + this.env.set(name, value); + } +} + /** * Gets an `ActionsEnv` instance for use in tests. */ -export function getTestActionsEnv(): ActionsEnv { - return { - getRequiredInput: (name) => { - throw new Error(`Input required and not supplied: ${name}`); - }, - getOptionalInput: () => undefined, - exportVariable: () => {}, - }; +export function getTestActionsEnv(env: Env): TestActionsEnv { + return new TestActionsEnv(env); } /** For testing purposes, we make all available state features accessible in `TestEnv`. */ @@ -213,12 +228,13 @@ type AllState = [ export function initAllState( overrides?: Partial>, ): ActionState { + const env = getTestEnv(); return { name: ActionName.Init, startedAt: new Date(), logger: new RecordingLogger(), - env: getTestEnv(), - actions: getTestActionsEnv(), + env, + actions: getTestActionsEnv(env), apiClient: github.getOctokit("123"), features: createFeatures([]), ...overrides, @@ -247,6 +263,7 @@ abstract class BaseEnvBuilder< > { protected readonly fn: (state: ActionState, ...args: Args) => R; private logger: RecordingLogger; + private actions: TestActionsEnv; protected state: ActionState; protected checks: Array>; @@ -256,15 +273,26 @@ abstract class BaseEnvBuilder< ) { this.fn = fn; this.logger = new RecordingLogger(); - this.state = - cloneFrom !== undefined - ? ({ - ...cloneFrom.state, - env: cloneFrom.state.env.clone(), - actions: Object.create(cloneFrom.state.actions), - logger: this.logger, - } satisfies ActionState) - : initAllState({ logger: this.logger }); + + if (cloneFrom !== undefined) { + const env = cloneFrom.state.env.clone(); + this.actions = cloneFrom.actions.clone(env); + this.state = { + ...cloneFrom.state, + env, + actions: this.actions, + logger: this.logger, + } satisfies ActionState; + } else { + const env = getTestEnv(); + this.actions = getTestActionsEnv(env); + this.state = initAllState({ + logger: this.logger, + env, + actions: this.actions, + }); + } + this.checks = [...(cloneFrom?.checks ?? [])]; } From d2f5cbbe919141b077e54396de7bb0c31da73912 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 13:22:46 +0100 Subject: [PATCH 21/39] Add `get` method to `ReadOnlyEnv` --- lib/entry-points.js | 4 ++++ src/environment.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index a2f6d22c52..9a7fbaa8e2 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -141565,6 +141565,10 @@ var ReadOnlyEnv = class { clone() { return Object.create(this, { vars: { value: { ...this.vars } } }); } + /** Gets a copy of the underlying environment. */ + get() { + return { ...this.vars }; + } /** Tries to get the value for `name` and throws if there isn't one. */ getRequired(name) { return getRequiredEnvVar(this.vars, name); diff --git a/src/environment.ts b/src/environment.ts index fea553d602..d6ff20391a 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -270,6 +270,11 @@ export class ReadOnlyEnv { return Object.create(this, { vars: { value: { ...this.vars } } }) as this; } + /** Gets a copy of the underlying environment. */ + public get(): Record { + return { ...this.vars }; + } + /** Tries to get the value for `name` and throws if there isn't one. */ public getRequired(name: string): string { return getRequiredEnvVar(this.vars, name); From 0cebd1d28d761cf2fceb2a3a9ed79dff79ea5a8c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 13:24:33 +0100 Subject: [PATCH 22/39] Add `hasEnv` delayed assertion and use for `getJobUUID` test --- src/status-report.test.ts | 15 +++++---------- src/testing-utils.ts | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 9d0c62efb1..17490a60cb 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -29,21 +29,16 @@ import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util"; setupTests(test); test("getJobUUID - generates valid UUIDs", async (t) => { - const exportVariableStub: sinon.SinonStub<[string, string], void> = - sinon.stub(); - await callee(getJobUUID) .withArgs() - .withActions((env) => { - env.exportVariable = exportVariableStub; - }) .logs(t, "Job run UUID is ") + .hasEnv(t, (val) => { + return { + [EnvVar.JOB_RUN_UUID]: val, + }; + }) .passes((val) => { t.true(uuid.validate(val)); - - const calls = exportVariableStub.getCalls(); - t.is(calls.length, 1); - t.deepEqual(calls[0].args, [EnvVar.JOB_RUN_UUID, val]); }); }); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 94c8435218..279459275d 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -378,6 +378,28 @@ abstract class BaseEnvBuilder< return result; } + /** + * Adds a delayed check that the environment variables returned by `fn` + * are present in the environment after the main assertion passes. + */ + public hasEnv( + t: ExecutionContext, + fn: ( + value: Awaited | undefined, + error: ThrownError | undefined, + ) => Record, + ): this { + const result = this.clone(); + result.checks.push(async (env, r) => { + const value = r.orElse(undefined); + const error = r.isFailure() ? r.value : undefined; + const expected = fn(value, error); + + t.like(env.getState().env.get(), expected); + }); + return result; + } + /** * Adds a delayed check that `messages` are not logged. The check will be * performed after the main assertion passes. From b411bbcd4ad96437e66f359abc5b628477549c83 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 14:27:24 +0100 Subject: [PATCH 23/39] Move `getJobUUID` call into `runInActions` for `init` and `setup-codeql` --- lib/entry-points.js | 8 ++++---- src/action-common.ts | 10 ++++++++-- src/init-action.ts | 4 ---- src/setup-codeql-action.ts | 4 ---- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 9a7fbaa8e2..c56f671098 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146700,13 +146700,15 @@ async function runInActions(action) { const env = getEnv(); const actionsEnv = getActionsEnv(); try { - await action.run({ + const actionState = { name: action.name, startedAt, logger, env, actions: actionsEnv - }); + }; + getJobUUID(actionState); + await action.run(actionState); } catch (error3) { core8.setFailed( `${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error3)}` @@ -160779,7 +160781,6 @@ async function run3(actionState) { logger ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - getJobUUID(actionState); core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); sourceRoot = path24.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), @@ -161777,7 +161778,6 @@ async function run6(actionState) { ); const repositoryProperties = repositoryPropertiesResult.orElse({}); const actionStateWithFeatures = { ...actionState, features }; - getJobUUID(actionState); const statusReportBase = await createStatusReportBase( "setup-codeql" /* SetupCodeQL */, "starting", diff --git a/src/action-common.ts b/src/action-common.ts index cbb1cd3422..be8629addf 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -8,6 +8,7 @@ import { getActionsLogger, Logger } from "./logging"; import { ActionName, getDisplayActionName, + getJobUUID, sendUnhandledErrorStatusReport, } from "./status-report"; import { getEnv, getErrorMessage } from "./util"; @@ -88,13 +89,18 @@ export async function runInActions(action: Action) { const actionsEnv = getActionsEnv(); try { - await action.run({ + const actionState = { name: action.name, startedAt, logger, env, actions: actionsEnv, - }); + }; + + // Create a unique identifier for this run. + getJobUUID(actionState); + + await action.run(actionState); } catch (error) { core.setFailed( `${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error)}`, diff --git a/src/init-action.ts b/src/init-action.ts index f1c3916318..00143df427 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -68,7 +68,6 @@ import { createInitWithConfigStatusReport, createStatusReportBase, getActionsStatus, - getJobUUID, sendStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -255,9 +254,6 @@ async function run( ); const repositoryProperties = repositoryPropertiesResult.orElse({}); - // Create a unique identifier for this run. - getJobUUID(actionState); - core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); // path.resolve() respects the intended semantics of source-root. If diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index d2f8c6104b..7873449f9c 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -25,7 +25,6 @@ import { InitToolsDownloadFields, createStatusReportBase, getActionsStatus, - getJobUUID, sendStatusReport, } from "./status-report"; import { ToolsDownloadStatusReport } from "./tools-download"; @@ -140,9 +139,6 @@ async function run( const actionStateWithFeatures = { ...actionState, features }; - // Create a unique identifier for this run. - getJobUUID(actionState); - const statusReportBase = await createStatusReportBase( ActionName.SetupCodeQL, "starting", From ba46ff760e2acb42dc881f443ad2bb3cd9de9d28 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 14:39:30 +0100 Subject: [PATCH 24/39] Add `transformTelemetryError` option to `Action` --- lib/entry-points.js | 8 +++++++- src/action-common.ts | 20 ++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index c56f671098..456ce1be7f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146713,7 +146713,13 @@ async function runInActions(action) { core8.setFailed( `${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error3)}` ); - await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger); + const statusReportError = action.transformTelemetryError !== void 0 ? action.transformTelemetryError(wrapError(error3)) : error3; + await sendUnhandledErrorStatusReport( + action.name, + startedAt, + statusReportError, + logger + ); } } diff --git a/src/action-common.ts b/src/action-common.ts index be8629addf..95323e7f2a 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -11,7 +11,7 @@ import { getJobUUID, sendUnhandledErrorStatusReport, } from "./status-report"; -import { getEnv, getErrorMessage } from "./util"; +import { getEnv, getErrorMessage, wrapError } from "./util"; /** Base state that is available to an Action on startup. */ export interface BaseState { @@ -79,6 +79,12 @@ export interface Action { name: ActionName; /** The entry point for the Action. */ run: ActionMain; + /** + * An optional function that transforms a caught error into a message suitable for + * inclusion in a status report. This is primarily intended for the `start-proxy` + * action to replace the thrown `Error`'s message with a safe one. + */ + transformTelemetryError?: (error: Error) => string; } /** A generic entry point that sets up the basic environment for the `action` and runs it. */ @@ -105,6 +111,16 @@ export async function runInActions(action: Action) { core.setFailed( `${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error)}`, ); - await sendUnhandledErrorStatusReport(action.name, startedAt, error, logger); + + const statusReportError = + action.transformTelemetryError !== undefined + ? action.transformTelemetryError(wrapError(error)) + : error; + await sendUnhandledErrorStatusReport( + action.name, + startedAt, + statusReportError, + logger, + ); } } From 8e6fdffc3205654e6d9f7e9a5976eaf55dee895b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 14:44:24 +0100 Subject: [PATCH 25/39] Use `runInActions` for `start-proxy` --- lib/entry-points.js | 38 +++++++++++-------------------- src/start-proxy-action.ts | 47 ++++++++++++--------------------------- 2 files changed, 27 insertions(+), 58 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 456ce1be7f..66e153b792 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -21567,7 +21567,7 @@ var require_core = __commonJS({ exports2.getBooleanInput = getBooleanInput; exports2.setOutput = setOutput7; exports2.setCommandEcho = setCommandEcho; - exports2.setFailed = setFailed13; + exports2.setFailed = setFailed12; exports2.isDebug = isDebug5; exports2.debug = debug6; exports2.error = error3; @@ -21651,7 +21651,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); function setCommandEcho(enabled) { (0, command_1.issue)("echo", enabled ? "on" : "off"); } - function setFailed13(message) { + function setFailed12(message) { process.exitCode = ExitCode.Failure; error3(message); } @@ -121094,11 +121094,11 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); (0, command_1.issue)("echo", enabled ? "on" : "off"); } exports2.setCommandEcho = setCommandEcho; - function setFailed13(message) { + function setFailed12(message) { process.exitCode = ExitCode.Failure; error3(message); } - exports2.setFailed = setFailed13; + exports2.setFailed = setFailed12; function isDebug5() { return process.env["RUNNER_DEBUG"] === "1"; } @@ -162654,17 +162654,12 @@ async function checkConnections(logger, proxy, backend) { } // src/start-proxy-action.ts -async function run7(startedAt) { - const logger = getActionsLogger(); +async function run7(action) { + const startedAt = action.startedAt; + const logger = action.logger; let features; let language; try { - const action = { - logger, - env: getEnv(), - actions: getActionsEnv() - }; - getJobUUID(action); persistInputs(); const tempDir = getTemporaryDirectory(); const proxyLogFilePath = path28.resolve(tempDir, "proxy.log"); @@ -162727,20 +162722,13 @@ async function run7(startedAt) { await sendFailedStatusReport(logger, startedAt, language, unwrappedError); } } +var startProxyAction = { + name: "start-proxy" /* StartProxy */, + run: run7, + transformTelemetryError: getSafeErrorMessage +}; async function runWrapper8() { - const startedAt = /* @__PURE__ */ new Date(); - const logger = getActionsLogger(); - try { - await run7(startedAt); - } catch (error3) { - core27.setFailed(`start-proxy action failed: ${getErrorMessage(error3)}`); - await sendUnhandledErrorStatusReport( - "start-proxy" /* StartProxy */, - startedAt, - getSafeErrorMessage(wrapError(error3)), - logger - ); - } + await runInActions(startProxyAction); } async function startProxy(binPath, config, logFilePath, logger) { const host = "127.0.0.1"; diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 67f6d50177..e8b89732f7 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -3,12 +3,12 @@ import * as path from "path"; import * as core from "@actions/core"; -import { ActionState } from "./action-common"; +import { Action, ActionState, runInActions } from "./action-common"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; import { FeatureEnablement, initFeatures } from "./feature-flags"; import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; -import { getActionsLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; import { credentialToStr, @@ -24,31 +24,18 @@ import { import { generateCertificateAuthority } from "./start-proxy/ca"; import { checkProxyEnvironment } from "./start-proxy/environment"; import { checkConnections } from "./start-proxy/reachability"; -import { - ActionName, - getJobUUID, - sendUnhandledErrorStatusReport, -} from "./status-report"; +import { ActionName } from "./status-report"; import * as util from "./util"; -async function run(startedAt: Date) { +async function run(action: ActionState<["Base", "Logger", "Env", "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 startedAt = action.startedAt; + const logger = action.logger; let features: FeatureEnablement | undefined; let language: BuiltInLanguage | undefined; try { - const action: ActionState<["Logger", "Env", "Actions"]> = { - logger, - env: util.getEnv(), - actions: actionsUtil.getActionsEnv(), - }; - - // Create a unique identifier for this run. - getJobUUID(action); - // Make inputs accessible in the `post` step. actionsUtil.persistInputs(); @@ -136,21 +123,15 @@ async function run(startedAt: Date) { } } -export async function runWrapper() { - const startedAt = new Date(); - const logger = getActionsLogger(); +/** Defines the `start-proxy` Action. */ +const startProxyAction: Action = { + name: ActionName.StartProxy, + run, + transformTelemetryError: getSafeErrorMessage, +}; - try { - await run(startedAt); - } catch (error) { - core.setFailed(`start-proxy action failed: ${util.getErrorMessage(error)}`); - await sendUnhandledErrorStatusReport( - ActionName.StartProxy, - startedAt, - getSafeErrorMessage(util.wrapError(error)), - logger, - ); - } +export async function runWrapper() { + await runInActions(startProxyAction); } async function startProxy( From d57c3ffcba10414c396e4bc89f526c3875e18a0d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Jul 2026 15:38:27 +0100 Subject: [PATCH 26/39] Add tests for `runInActions` --- src/action-common.test.ts | 123 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/action-common.test.ts diff --git a/src/action-common.test.ts b/src/action-common.test.ts new file mode 100644 index 0000000000..fc2e0a9aaa --- /dev/null +++ b/src/action-common.test.ts @@ -0,0 +1,123 @@ +import * as core from "@actions/core"; +import test from "ava"; +import sinon from "sinon"; + +import * as common from "./action-common"; +import * as actionsUtil from "./actions-util"; +import * as environment from "./environment"; +import * as logging from "./logging"; +import { ActionName } from "./status-report"; +import * as statusReport from "./status-report"; +import { + getTestActionsEnv, + getTestEnv, + makeMacro, + RecordingLogger, + setupTests, +} from "./testing-utils"; +import { getErrorMessage } from "./util"; + +setupTests(test); + +interface RunInActionsTestOpts { + runFn?: () => Promise; + expectedErrorMessage?: string; + expectedTelemetryError?: string; +} + +const runInActionsMacro = makeMacro({ + exec: async (t, opts: RunInActionsTestOpts) => { + const expectFailure = opts?.expectedErrorMessage !== undefined; + + const logger = new RecordingLogger(); + const getActionsLogger = sinon + .stub(logging, "getActionsLogger") + .returns(logger); + + const env = getTestEnv(); + const getEnv = sinon.stub(environment, "getEnv").returns(env); + + const actionsEnv = getTestActionsEnv(env); + const getActionsEnv = sinon + .stub(actionsUtil, "getActionsEnv") + .returns(actionsEnv); + + const getJobUUID = sinon + .stub(statusReport, "getJobUUID") + .returns("test-job-uuid"); + + const setFailed = sinon.stub(core, "setFailed"); + const sendUnhandledErrorStatusReport = sinon.stub( + statusReport, + "sendUnhandledErrorStatusReport", + ); + + const name = ActionName.Init; + const run = sinon.stub(); + + if (opts?.runFn) { + run.callsFake(opts.runFn); + } + + const transformTelemetryError = sinon + .stub() + .callsFake((err) => opts?.expectedTelemetryError ?? getErrorMessage(err)); + const testAction: common.Action = { + name, + run, + transformTelemetryError, + }; + + await common.runInActions(testAction); + + // These always should have been called once. + t.true(getActionsLogger.calledOnce); + t.true(getEnv.calledOnce); + t.true(getActionsEnv.calledOnce); + + const expectedActionState = { + actions: actionsEnv, + env, + logger, + name: ActionName.Init, + }; + + t.true(getJobUUID.calledOnceWithExactly(sinon.match(expectedActionState))); + t.true(run.calledOnceWithExactly(sinon.match(expectedActionState))); + + t.is(setFailed.calledOnce, expectFailure ?? false); + t.is(sendUnhandledErrorStatusReport.calledOnce, expectFailure ?? false); + + if (expectFailure) { + t.true( + setFailed.calledOnceWithExactly( + `${statusReport.getDisplayActionName(name)} action failed: ${opts?.expectedErrorMessage}`, + ), + ); + t.true( + sendUnhandledErrorStatusReport.calledOnceWithExactly( + name, + sinon.match.any, + opts?.expectedTelemetryError ?? opts?.expectedErrorMessage, + logger, + ), + ); + } + }, + title: (providedTitle) => `runInActions - ${providedTitle}`, +}); + +runInActionsMacro.serial("calls run", {}); +runInActionsMacro.serial("handles run exceptions", { + runFn: () => { + throw new Error("Test failure"); + }, + expectedErrorMessage: "Test failure", +}); +runInActionsMacro.serial("transforms run exceptions", { + runFn: () => { + throw new Error("Test failure"); + }, + expectedErrorMessage: "Test failure", + expectedTelemetryError: "Transformed failure message", +}); From 8f0a4f23c4e6fd3bdc74965a57db44f356b5ee32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 17:54:52 +0000 Subject: [PATCH 27/39] Bump the npm-minor group across 1 directory with 2 updates Bumps the npm-minor group with 2 updates in the / directory: [sinon](https://github.com/sinonjs/sinon) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint). Updates `sinon` from 22.0.0 to 22.1.0 - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/CHANGES.md) - [Commits](https://github.com/sinonjs/sinon/compare/v22.0.0...v22.1.0) Updates `typescript-eslint` from 8.64.0 to 8.65.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.65.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: sinon dependency-version: 22.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor - dependency-name: typescript-eslint dependency-version: 8.65.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 148 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 76 insertions(+), 76 deletions(-) diff --git a/package-lock.json b/package-lock.json index a01b4a12e7..1e395f75fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,9 +63,9 @@ "glob": "^13.0.6", "globals": "^17.7.0", "nock": "^14.0.16", - "sinon": "^22.0.0", + "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.64.0" + "typescript-eslint": "^8.65.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2591,17 +2591,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.64.0.tgz", - "integrity": "sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", + "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.64.0", - "@typescript-eslint/type-utils": "8.64.0", - "@typescript-eslint/utils": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/type-utils": "8.65.0", + "@typescript-eslint/utils": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2614,7 +2614,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.64.0", + "@typescript-eslint/parser": "^8.65.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2630,16 +2630,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.64.0.tgz", - "integrity": "sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", + "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.64.0", - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/typescript-estree": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", "debug": "^4.4.3" }, "engines": { @@ -2673,14 +2673,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.64.0.tgz", - "integrity": "sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", + "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.64.0", - "@typescript-eslint/types": "^8.64.0", + "@typescript-eslint/tsconfig-utils": "^8.65.0", + "@typescript-eslint/types": "^8.65.0", "debug": "^4.4.3" }, "engines": { @@ -2713,14 +2713,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.64.0.tgz", - "integrity": "sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz", + "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0" + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2731,9 +2731,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz", - "integrity": "sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", + "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", "dev": true, "license": "MIT", "engines": { @@ -2748,15 +2748,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.64.0.tgz", - "integrity": "sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz", + "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/typescript-estree": "8.64.0", - "@typescript-eslint/utils": "8.64.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2791,9 +2791,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.64.0.tgz", - "integrity": "sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", + "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", "dev": true, "license": "MIT", "engines": { @@ -2805,16 +2805,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.64.0.tgz", - "integrity": "sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", + "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.64.0", - "@typescript-eslint/tsconfig-utils": "8.64.0", - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0", + "@typescript-eslint/project-service": "8.65.0", + "@typescript-eslint/tsconfig-utils": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2843,16 +2843,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", - "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", + "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { @@ -2874,13 +2874,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.5" + "brace-expansion": "^5.0.8" }, "engines": { "node": "18 || 20 || >=22" @@ -2890,16 +2890,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.64.0.tgz", - "integrity": "sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz", + "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.64.0", - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/typescript-estree": "8.64.0" + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2914,13 +2914,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.64.0.tgz", - "integrity": "sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.65.0.tgz", + "integrity": "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/types": "8.65.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -8556,9 +8556,9 @@ } }, "node_modules/sinon": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-22.0.0.tgz", - "integrity": "sha512-sq/6DpdXOrLyfbKlXLg/Usc7xu8YXPeLkOFZRvA3bNUSA2lhbrZ06yuXbH1fkzBPCbz9O10+7hznzUsjaYNm0Q==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-22.1.0.tgz", + "integrity": "sha512-n1ajF2rBWMTtEwbKcw4UdFg4nCnDdq/U6RDoxtOd7oapOlRoJ5ynwFx60owROyhDpA9QhMZi0pCO/xtmwFjG7w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9320,16 +9320,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.64.0.tgz", - "integrity": "sha512-0qg+pDNMnqYzqH9AnNK+39tejHvsShUOUUoRUgtnTGE7QuMZhiFDnozq8nHJVq+Wae6NMLKNWLg5WmkcC/ndyQ==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", + "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.64.0", - "@typescript-eslint/parser": "8.64.0", - "@typescript-eslint/typescript-estree": "8.64.0", - "@typescript-eslint/utils": "8.64.0" + "@typescript-eslint/eslint-plugin": "8.65.0", + "@typescript-eslint/parser": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index cdd58cd167..ad959a5eee 100644 --- a/package.json +++ b/package.json @@ -71,9 +71,9 @@ "glob": "^13.0.6", "globals": "^17.7.0", "nock": "^14.0.16", - "sinon": "^22.0.0", + "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.64.0" + "typescript-eslint": "^8.65.0" }, "overrides": { "@actions/tool-cache": { From 3502f795752239ff535bbb8c75134dce966e6700 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 17:57:26 +0000 Subject: [PATCH 28/39] Bump ruby/setup-ruby Bumps the actions-minor group with 1 update in the /.github/workflows directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby). Updates `ruby/setup-ruby` from 1.319.0 to 1.321.0 - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/003a5c4d8d6321bd302e38f6f0ec593f77f06600...95ef2b042f9d7a56d8268cba8559e2842e2ad01b) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-version: 1.321.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/__rubocop-multi-language.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index 4809b680ab..c405b44fed 100644 --- a/.github/workflows/__rubocop-multi-language.yml +++ b/.github/workflows/__rubocop-multi-language.yml @@ -54,7 +54,7 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Set up Ruby - uses: ruby/setup-ruby@003a5c4d8d6321bd302e38f6f0ec593f77f06600 # v1.319.0 + uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 with: ruby-version: 2.6 - name: Install Code Scanning integration From 60a57910be57f97ad7b63038a43680ac716a4039 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 17:59:24 +0000 Subject: [PATCH 29/39] Rebuild --- pr-checks/checks/rubocop-multi-language.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml index 7879653f38..37c5d36e90 100644 --- a/pr-checks/checks/rubocop-multi-language.yml +++ b/pr-checks/checks/rubocop-multi-language.yml @@ -5,7 +5,7 @@ versions: - default steps: - name: Set up Ruby - uses: ruby/setup-ruby@003a5c4d8d6321bd302e38f6f0ec593f77f06600 # v1.319.0 + uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 with: ruby-version: 2.6 - name: Install Code Scanning integration From 82f035a50156142187b47d8eb748075dbde92426 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:21:21 +0000 Subject: [PATCH 30/39] Update changelog and version after v4.37.4 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51bb95d5c8..65cd1e1fae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. +## [UNRELEASED] + +No user facing changes. + ## 4.37.4 - 29 Jul 2026 - This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037) diff --git a/package-lock.json b/package-lock.json index a01b4a12e7..b72c91e22b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.37.4", + "version": "4.37.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.37.4", + "version": "4.37.5", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index cdd58cd167..8b379f9c9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.37.4", + "version": "4.37.5", "private": true, "description": "CodeQL action", "scripts": { From 06f1d4ffed243918940368743ff3fd9147859de6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:21:35 +0000 Subject: [PATCH 31/39] Rebuild --- lib/entry-points.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index eb81affd67..17f56246ae 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145404,7 +145404,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.37.4"; + return "4.37.5"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); From 2d3b351ea6452a9b21346f8d64567e5b833924de Mon Sep 17 00:00:00 2001 From: sim Date: Thu, 30 Jul 2026 18:47:27 +0100 Subject: [PATCH 32/39] Handle network errors when streaming the CodeQL bundle download A network error such as `ECONNRESET` while streaming the download and extraction of the CodeQL bundle terminated the `init` Action rather than falling back to downloading the bundle before extracting it, since no `error` listener was attached to the request returned by `https.get`. Also pipe the response into `tar` using `stream.pipeline` so that errors on the response itself are surfaced and `tar`'s standard input is closed, and abort the request if it stalls. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 2 +- lib/entry-points.js | 360 +++++++++++++++++++------------------ src/tar.test.ts | 33 ++++ src/tar.ts | 13 +- src/tools-download.test.ts | 37 ++++ src/tools-download.ts | 28 ++- 6 files changed, 290 insertions(+), 183 deletions(-) create mode 100644 src/tar.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 65cd1e1fae..c461878c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th ## [UNRELEASED] -No user facing changes. +- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#3367](https://github.com/github/codeql-action/issues/3367) ## 4.37.4 - 29 Jul 2026 diff --git a/lib/entry-points.js b/lib/entry-points.js index 8bea6abaaf..a03519a725 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -7069,7 +7069,7 @@ var require_client_h2 = __commonJS({ "node_modules/undici/lib/dispatcher/client-h2.js"(exports2, module2) { "use strict"; var assert = require("node:assert"); - var { pipeline } = require("node:stream"); + var { pipeline: pipeline2 } = require("node:stream"); var util3 = require_util(); var { RequestContentLengthMismatchError, @@ -7516,7 +7516,7 @@ var require_client_h2 = __commonJS({ } function writeStream(abort, socket, expectsPayload, h2stream, body, client, request3, contentLength) { assert(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); - const pipe = pipeline( + const pipe = pipeline2( body, h2stream, (err) => { @@ -10506,7 +10506,7 @@ var require_api_pipeline = __commonJS({ util3.destroy(ret, err); } }; - function pipeline(opts, handler2) { + function pipeline2(opts, handler2) { try { const pipelineHandler = new PipelineHandler(opts, handler2); this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler); @@ -10515,7 +10515,7 @@ var require_api_pipeline = __commonJS({ return new PassThrough3().destroy(err); } } - module2.exports = pipeline; + module2.exports = pipeline2; } }); @@ -13680,7 +13680,7 @@ var require_fetch = __commonJS({ subresourceSet } = require_constants3(); var EE = require("node:events"); - var { Readable: Readable3, pipeline, finished } = require("node:stream"); + var { Readable: Readable3, pipeline: pipeline2, finished } = require("node:stream"); var { addAbortListener, isErrored, isReadable, bufferToLowerCasedHeaderName } = require_util(); var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url(); var { getGlobalDispatcher } = require_global2(); @@ -14624,7 +14624,7 @@ var require_fetch = __commonJS({ status, statusText, headersList, - body: decoders.length ? pipeline(this.body, ...decoders, (err) => { + body: decoders.length ? pipeline2(this.body, ...decoders, (err) => { if (err) { this.onError(err); } @@ -18604,7 +18604,7 @@ ${value}`; var require_eventsource = __commonJS({ "node_modules/undici/lib/web/eventsource/eventsource.js"(exports2, module2) { "use strict"; - var { pipeline } = require("node:stream"); + var { pipeline: pipeline2 } = require("node:stream"); var { fetching } = require_fetch(); var { makeRequest } = require_request2(); var { webidl } = require_webidl(); @@ -18762,7 +18762,7 @@ var require_eventsource = __commonJS({ )); } }); - pipeline( + pipeline2( response.body.stream, eventSourceStream, (error3) => { @@ -32788,8 +32788,8 @@ var require_internal_hash_files = __commonJS({ continue; } const hash2 = crypto3.createHash("sha256"); - const pipeline = util3.promisify(stream2.pipeline); - yield pipeline(fs31.createReadStream(file), hash2); + const pipeline2 = util3.promisify(stream2.pipeline); + yield pipeline2(fs31.createReadStream(file), hash2); result.write(hash2.digest()); count++; if (!hasMatch) { @@ -35356,12 +35356,12 @@ var require_pipeline = __commonJS({ } sendRequest(httpClient, request3) { const policies = this.getOrderedPolicies(); - const pipeline = policies.reduceRight((next, policy) => { + const pipeline2 = policies.reduceRight((next, policy) => { return (req) => { return policy.sendRequest(req, next); }; }, (req) => httpClient.sendRequest(req)); - return pipeline(request3); + return pipeline2(request3); } getOrderedPolicies() { if (!this._orderedPolicies) { @@ -38488,26 +38488,26 @@ var require_createPipelineFromOptions = __commonJS({ var tlsPolicy_js_1 = require_tlsPolicy(); var multipartPolicy_js_1 = require_multipartPolicy(); function createPipelineFromOptions(options) { - const pipeline = (0, pipeline_js_1.createEmptyPipeline)(); + const pipeline2 = (0, pipeline_js_1.createEmptyPipeline)(); if (checkEnvironment_js_1.isNodeLike) { if (options.agent) { - pipeline.addPolicy((0, agentPolicy_js_1.agentPolicy)(options.agent)); + pipeline2.addPolicy((0, agentPolicy_js_1.agentPolicy)(options.agent)); } if (options.tlsOptions) { - pipeline.addPolicy((0, tlsPolicy_js_1.tlsPolicy)(options.tlsOptions)); + pipeline2.addPolicy((0, tlsPolicy_js_1.tlsPolicy)(options.tlsOptions)); } - pipeline.addPolicy((0, proxyPolicy_js_1.proxyPolicy)(options.proxyOptions)); - pipeline.addPolicy((0, decompressResponsePolicy_js_1.decompressResponsePolicy)()); + pipeline2.addPolicy((0, proxyPolicy_js_1.proxyPolicy)(options.proxyOptions)); + pipeline2.addPolicy((0, decompressResponsePolicy_js_1.decompressResponsePolicy)()); } - pipeline.addPolicy((0, formDataPolicy_js_1.formDataPolicy)(), { beforePolicies: [multipartPolicy_js_1.multipartPolicyName] }); - pipeline.addPolicy((0, userAgentPolicy_js_1.userAgentPolicy)(options.userAgentOptions)); - pipeline.addPolicy((0, multipartPolicy_js_1.multipartPolicy)(), { afterPhase: "Deserialize" }); - pipeline.addPolicy((0, defaultRetryPolicy_js_1.defaultRetryPolicy)(options.retryOptions), { phase: "Retry" }); + pipeline2.addPolicy((0, formDataPolicy_js_1.formDataPolicy)(), { beforePolicies: [multipartPolicy_js_1.multipartPolicyName] }); + pipeline2.addPolicy((0, userAgentPolicy_js_1.userAgentPolicy)(options.userAgentOptions)); + pipeline2.addPolicy((0, multipartPolicy_js_1.multipartPolicy)(), { afterPhase: "Deserialize" }); + pipeline2.addPolicy((0, defaultRetryPolicy_js_1.defaultRetryPolicy)(options.retryOptions), { phase: "Retry" }); if (checkEnvironment_js_1.isNodeLike) { - pipeline.addPolicy((0, redirectPolicy_js_1.redirectPolicy)(options.redirectOptions), { afterPhase: "Retry" }); + pipeline2.addPolicy((0, redirectPolicy_js_1.redirectPolicy)(options.redirectOptions), { afterPhase: "Retry" }); } - pipeline.addPolicy((0, logPolicy_js_1.logPolicy)(options.loggingOptions), { afterPhase: "Sign" }); - return pipeline; + pipeline2.addPolicy((0, logPolicy_js_1.logPolicy)(options.loggingOptions), { afterPhase: "Sign" }); + return pipeline2; } } }); @@ -38729,21 +38729,21 @@ var require_clientHelpers = __commonJS({ var oauth2AuthenticationPolicy_js_1 = require_oauth2AuthenticationPolicy(); var cachedHttpClient; function createDefaultPipeline(options = {}) { - const pipeline = (0, createPipelineFromOptions_js_1.createPipelineFromOptions)(options); - pipeline.addPolicy((0, apiVersionPolicy_js_1.apiVersionPolicy)(options)); + const pipeline2 = (0, createPipelineFromOptions_js_1.createPipelineFromOptions)(options); + pipeline2.addPolicy((0, apiVersionPolicy_js_1.apiVersionPolicy)(options)); const { credential, authSchemes, allowInsecureConnection } = options; if (credential) { if ((0, credentials_js_1.isApiKeyCredential)(credential)) { - pipeline.addPolicy((0, apiKeyAuthenticationPolicy_js_1.apiKeyAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); + pipeline2.addPolicy((0, apiKeyAuthenticationPolicy_js_1.apiKeyAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); } else if ((0, credentials_js_1.isBasicCredential)(credential)) { - pipeline.addPolicy((0, basicAuthenticationPolicy_js_1.basicAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); + pipeline2.addPolicy((0, basicAuthenticationPolicy_js_1.basicAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); } else if ((0, credentials_js_1.isBearerTokenCredential)(credential)) { - pipeline.addPolicy((0, bearerAuthenticationPolicy_js_1.bearerAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); + pipeline2.addPolicy((0, bearerAuthenticationPolicy_js_1.bearerAuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); } else if ((0, credentials_js_1.isOAuth2TokenCredential)(credential)) { - pipeline.addPolicy((0, oauth2AuthenticationPolicy_js_1.oauth2AuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); + pipeline2.addPolicy((0, oauth2AuthenticationPolicy_js_1.oauth2AuthenticationPolicy)({ authSchemes, credential, allowInsecureConnection })); } } - return pipeline; + return pipeline2; } function getCachedDefaultHttpsClient() { if (!cachedHttpClient) { @@ -38879,11 +38879,11 @@ var require_sendRequest = __commonJS({ var clientHelpers_js_1 = require_clientHelpers(); var typeGuards_js_1 = require_typeGuards(); var multipart_js_1 = require_multipart(); - async function sendRequest(method, url2, pipeline, options = {}, customHttpClient) { + async function sendRequest(method, url2, pipeline2, options = {}, customHttpClient) { const httpClient = customHttpClient ?? (0, clientHelpers_js_1.getCachedDefaultHttpsClient)(); const request3 = buildPipelineRequest(method, url2, options); try { - const response = await pipeline.sendRequest(httpClient, request3); + const response = await pipeline2.sendRequest(httpClient, request3); const headers = response.headers.toJSON(); const stream2 = response.readableStreamBody ?? response.browserStreamBody; const parsedBody = options.responseAsStream || stream2 !== void 0 ? void 0 : getResponseBody(response); @@ -39146,11 +39146,11 @@ var require_getClient = __commonJS({ var urlHelpers_js_1 = require_urlHelpers(); var checkEnvironment_js_1 = require_checkEnvironment(); function getClient(endpoint2, clientOptions = {}) { - const pipeline = clientOptions.pipeline ?? (0, clientHelpers_js_1.createDefaultPipeline)(clientOptions); + const pipeline2 = clientOptions.pipeline ?? (0, clientHelpers_js_1.createDefaultPipeline)(clientOptions); if (clientOptions.additionalPolicies?.length) { for (const { policy, position } of clientOptions.additionalPolicies) { const afterPhase = position === "perRetry" ? "Sign" : void 0; - pipeline.addPolicy(policy, { + pipeline2.addPolicy(policy, { afterPhase }); } @@ -39161,53 +39161,53 @@ var require_getClient = __commonJS({ const getUrl = (requestOptions) => (0, urlHelpers_js_1.buildRequestUrl)(endpointUrl, path29, args, { allowInsecureConnection, ...requestOptions }); return { get: (requestOptions = {}) => { - return buildOperation("GET", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("GET", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, post: (requestOptions = {}) => { - return buildOperation("POST", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("POST", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, put: (requestOptions = {}) => { - return buildOperation("PUT", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("PUT", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, patch: (requestOptions = {}) => { - return buildOperation("PATCH", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("PATCH", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, delete: (requestOptions = {}) => { - return buildOperation("DELETE", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("DELETE", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, head: (requestOptions = {}) => { - return buildOperation("HEAD", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("HEAD", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, options: (requestOptions = {}) => { - return buildOperation("OPTIONS", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("OPTIONS", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); }, trace: (requestOptions = {}) => { - return buildOperation("TRACE", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); + return buildOperation("TRACE", getUrl(requestOptions), pipeline2, requestOptions, allowInsecureConnection, httpClient); } }; }; return { path: client, pathUnchecked: client, - pipeline + pipeline: pipeline2 }; } - function buildOperation(method, url2, pipeline, options, allowInsecureConnection, httpClient) { + function buildOperation(method, url2, pipeline2, options, allowInsecureConnection, httpClient) { allowInsecureConnection = options.allowInsecureConnection ?? allowInsecureConnection; return { then: function(onFulfilled, onrejected) { - return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline, { ...options, allowInsecureConnection }, httpClient).then(onFulfilled, onrejected); + return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline2, { ...options, allowInsecureConnection }, httpClient).then(onFulfilled, onrejected); }, async asBrowserStream() { if (checkEnvironment_js_1.isNodeLike) { throw new Error("`asBrowserStream` is supported only in the browser environment. Use `asNodeStream` instead to obtain the response body stream. If you require a Web stream of the response in Node, consider using `Readable.toWeb` on the result of `asNodeStream`."); } else { - return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline, { ...options, allowInsecureConnection, responseAsStream: true }, httpClient); + return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline2, { ...options, allowInsecureConnection, responseAsStream: true }, httpClient); } }, async asNodeStream() { if (checkEnvironment_js_1.isNodeLike) { - return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline, { ...options, allowInsecureConnection, responseAsStream: true }, httpClient); + return (0, sendRequest_js_1.sendRequest)(method, url2, pipeline2, { ...options, allowInsecureConnection, responseAsStream: true }, httpClient); } else { throw new Error("`isNodeStream` is not supported in the browser environment. Use `asBrowserStream` to obtain the response body stream."); } @@ -40697,31 +40697,31 @@ var require_createPipelineFromOptions2 = __commonJS({ var tracingPolicy_js_1 = require_tracingPolicy(); var wrapAbortSignalLikePolicy_js_1 = require_wrapAbortSignalLikePolicy(); function createPipelineFromOptions(options) { - const pipeline = (0, pipeline_js_1.createEmptyPipeline)(); + const pipeline2 = (0, pipeline_js_1.createEmptyPipeline)(); if (core_util_1.isNodeLike) { if (options.agent) { - pipeline.addPolicy((0, agentPolicy_js_1.agentPolicy)(options.agent)); + pipeline2.addPolicy((0, agentPolicy_js_1.agentPolicy)(options.agent)); } if (options.tlsOptions) { - pipeline.addPolicy((0, tlsPolicy_js_1.tlsPolicy)(options.tlsOptions)); - } - pipeline.addPolicy((0, proxyPolicy_js_1.proxyPolicy)(options.proxyOptions)); - pipeline.addPolicy((0, decompressResponsePolicy_js_1.decompressResponsePolicy)()); - } - pipeline.addPolicy((0, wrapAbortSignalLikePolicy_js_1.wrapAbortSignalLikePolicy)()); - pipeline.addPolicy((0, formDataPolicy_js_1.formDataPolicy)(), { beforePolicies: [multipartPolicy_js_1.multipartPolicyName] }); - pipeline.addPolicy((0, userAgentPolicy_js_1.userAgentPolicy)(options.userAgentOptions)); - pipeline.addPolicy((0, setClientRequestIdPolicy_js_1.setClientRequestIdPolicy)(options.telemetryOptions?.clientRequestIdHeaderName)); - pipeline.addPolicy((0, multipartPolicy_js_1.multipartPolicy)(), { afterPhase: "Deserialize" }); - pipeline.addPolicy((0, defaultRetryPolicy_js_1.defaultRetryPolicy)(options.retryOptions), { phase: "Retry" }); - pipeline.addPolicy((0, tracingPolicy_js_1.tracingPolicy)({ ...options.userAgentOptions, ...options.loggingOptions }), { + pipeline2.addPolicy((0, tlsPolicy_js_1.tlsPolicy)(options.tlsOptions)); + } + pipeline2.addPolicy((0, proxyPolicy_js_1.proxyPolicy)(options.proxyOptions)); + pipeline2.addPolicy((0, decompressResponsePolicy_js_1.decompressResponsePolicy)()); + } + pipeline2.addPolicy((0, wrapAbortSignalLikePolicy_js_1.wrapAbortSignalLikePolicy)()); + pipeline2.addPolicy((0, formDataPolicy_js_1.formDataPolicy)(), { beforePolicies: [multipartPolicy_js_1.multipartPolicyName] }); + pipeline2.addPolicy((0, userAgentPolicy_js_1.userAgentPolicy)(options.userAgentOptions)); + pipeline2.addPolicy((0, setClientRequestIdPolicy_js_1.setClientRequestIdPolicy)(options.telemetryOptions?.clientRequestIdHeaderName)); + pipeline2.addPolicy((0, multipartPolicy_js_1.multipartPolicy)(), { afterPhase: "Deserialize" }); + pipeline2.addPolicy((0, defaultRetryPolicy_js_1.defaultRetryPolicy)(options.retryOptions), { phase: "Retry" }); + pipeline2.addPolicy((0, tracingPolicy_js_1.tracingPolicy)({ ...options.userAgentOptions, ...options.loggingOptions }), { afterPhase: "Retry" }); if (core_util_1.isNodeLike) { - pipeline.addPolicy((0, redirectPolicy_js_1.redirectPolicy)(options.redirectOptions), { afterPhase: "Retry" }); + pipeline2.addPolicy((0, redirectPolicy_js_1.redirectPolicy)(options.redirectOptions), { afterPhase: "Retry" }); } - pipeline.addPolicy((0, logPolicy_js_1.logPolicy)(options.loggingOptions), { afterPhase: "Sign" }); - return pipeline; + pipeline2.addPolicy((0, logPolicy_js_1.logPolicy)(options.loggingOptions), { afterPhase: "Sign" }); + return pipeline2; } } }); @@ -41635,8 +41635,8 @@ var require_disableKeepAlivePolicy = __commonJS({ } }; } - function pipelineContainsDisableKeepAlivePolicy(pipeline) { - return pipeline.getOrderedPolicies().some((policy) => policy.name === exports2.disableKeepAlivePolicyName); + function pipelineContainsDisableKeepAlivePolicy(pipeline2) { + return pipeline2.getOrderedPolicies().some((policy) => policy.name === exports2.disableKeepAlivePolicyName); } } }); @@ -42975,18 +42975,18 @@ var require_pipeline3 = __commonJS({ var core_rest_pipeline_1 = require_commonjs6(); var serializationPolicy_js_1 = require_serializationPolicy(); function createClientPipeline(options = {}) { - const pipeline = (0, core_rest_pipeline_1.createPipelineFromOptions)(options ?? {}); + const pipeline2 = (0, core_rest_pipeline_1.createPipelineFromOptions)(options ?? {}); if (options.credentialOptions) { - pipeline.addPolicy((0, core_rest_pipeline_1.bearerTokenAuthenticationPolicy)({ + pipeline2.addPolicy((0, core_rest_pipeline_1.bearerTokenAuthenticationPolicy)({ credential: options.credentialOptions.credential, scopes: options.credentialOptions.credentialScopes })); } - pipeline.addPolicy((0, serializationPolicy_js_1.serializationPolicy)(options.serializationOptions), { phase: "Serialize" }); - pipeline.addPolicy((0, deserializationPolicy_js_1.deserializationPolicy)(options.deserializationOptions), { + pipeline2.addPolicy((0, serializationPolicy_js_1.serializationPolicy)(options.serializationOptions), { phase: "Serialize" }); + pipeline2.addPolicy((0, deserializationPolicy_js_1.deserializationPolicy)(options.deserializationOptions), { phase: "Deserialize" }); - return pipeline; + return pipeline2; } } }); @@ -50204,11 +50204,11 @@ var require_Pipeline = __commonJS({ var StorageSharedKeyCredentialPolicyV2_js_1 = require_StorageSharedKeyCredentialPolicyV22(); var StorageBrowserPolicyFactory_js_1 = require_StorageBrowserPolicyFactory2(); var StorageCorrectContentLengthPolicy_js_1 = require_StorageCorrectContentLengthPolicy2(); - function isPipelineLike(pipeline) { - if (!pipeline || typeof pipeline !== "object") { + function isPipelineLike(pipeline2) { + if (!pipeline2 || typeof pipeline2 !== "object") { return false; } - const castPipeline = pipeline; + const castPipeline = pipeline2; return Array.isArray(castPipeline.factories) && typeof castPipeline.options === "object" && typeof castPipeline.toServiceClientOptions === "function"; } var Pipeline = class { @@ -50248,11 +50248,11 @@ var require_Pipeline = __commonJS({ if (!credential) { credential = new AnonymousCredential_js_1.AnonymousCredential(); } - const pipeline = new Pipeline([], pipelineOptions); - pipeline._credential = credential; - return pipeline; + const pipeline2 = new Pipeline([], pipelineOptions); + pipeline2._credential = credential; + return pipeline2; } - function processDownlevelPipeline(pipeline) { + function processDownlevelPipeline(pipeline2) { const knownFactoryFunctions = [ isAnonymousCredential, isStorageSharedKeyCredential, @@ -50262,8 +50262,8 @@ var require_Pipeline = __commonJS({ isStorageTelemetryPolicyFactory, isCoreHttpPolicyFactory ]; - if (pipeline.factories.length) { - const novelFactories = pipeline.factories.filter((factory) => { + if (pipeline2.factories.length) { + const novelFactories = pipeline2.factories.filter((factory) => { return !knownFactoryFunctions.some((knownFactory) => knownFactory(factory)); }); if (novelFactories.length) { @@ -50276,14 +50276,14 @@ var require_Pipeline = __commonJS({ } return void 0; } - function getCoreClientOptions(pipeline) { - const { httpClient: v1Client, ...restOptions } = pipeline.options; - let httpClient = pipeline._coreHttpClient; + function getCoreClientOptions(pipeline2) { + const { httpClient: v1Client, ...restOptions } = pipeline2.options; + let httpClient = pipeline2._coreHttpClient; if (!httpClient) { httpClient = v1Client ? (0, core_http_compat_1.convertHttpClient)(v1Client) : (0, storage_common_1.getCachedDefaultHttpClient)(); - pipeline._coreHttpClient = httpClient; + pipeline2._coreHttpClient = httpClient; } - let corePipeline = pipeline._corePipeline; + let corePipeline = pipeline2._corePipeline; if (!corePipeline) { const packageDetails = `azsdk-js-azure-storage-blob/${constants_js_1.SDK_VERSION}`; const userAgentPrefix = restOptions.userAgentOptions && restOptions.userAgentOptions.userAgentPrefix ? `${restOptions.userAgentOptions.userAgentPrefix} ${packageDetails}` : `${packageDetails}`; @@ -50324,11 +50324,11 @@ var require_Pipeline = __commonJS({ corePipeline.addPolicy((0, StorageRetryPolicyV2_js_1.storageRetryPolicy)(restOptions.retryOptions), { phase: "Retry" }); corePipeline.addPolicy((0, storage_common_1.storageRequestFailureDetailsParserPolicy)()); corePipeline.addPolicy((0, StorageBrowserPolicyV2_js_1.storageBrowserPolicy)()); - const downlevelResults = processDownlevelPipeline(pipeline); + const downlevelResults = processDownlevelPipeline(pipeline2); if (downlevelResults) { corePipeline.addPolicy(downlevelResults.wrappedPolicies, downlevelResults.afterRetry ? { afterPhase: "Retry" } : void 0); } - const credential = getCredentialFromPipeline(pipeline); + const credential = getCredentialFromPipeline(pipeline2); if ((0, core_auth_1.isTokenCredential)(credential)) { corePipeline.addPolicy((0, core_rest_pipeline_1.bearerTokenAuthenticationPolicy)({ credential, @@ -50341,7 +50341,7 @@ var require_Pipeline = __commonJS({ accountKey: credential.accountKey }), { phase: "Sign" }); } - pipeline._corePipeline = corePipeline; + pipeline2._corePipeline = corePipeline; } return { ...restOptions, @@ -50350,12 +50350,12 @@ var require_Pipeline = __commonJS({ pipeline: corePipeline }; } - function getCredentialFromPipeline(pipeline) { - if (pipeline._credential) { - return pipeline._credential; + function getCredentialFromPipeline(pipeline2) { + if (pipeline2._credential) { + return pipeline2._credential; } let credential = new AnonymousCredential_js_1.AnonymousCredential(); - for (const factory of pipeline.factories) { + for (const factory of pipeline2.factories) { if ((0, core_auth_1.isTokenCredential)(factory.credential)) { credential = factory.credential; } else if (isStorageSharedKeyCredential(factory)) { @@ -63880,13 +63880,13 @@ var require_StorageClient = __commonJS({ * @param url - url to resource * @param pipeline - request policy pipeline. */ - constructor(url2, pipeline) { + constructor(url2, pipeline2) { this.url = (0, utils_common_js_1.escapeURLPath)(url2); this.accountName = (0, utils_common_js_1.getAccountNameFromUrl)(url2); - this.pipeline = pipeline; - this.storageClientContext = new StorageContextClient_js_1.StorageContextClient(this.url, (0, Pipeline_js_1.getCoreClientOptions)(pipeline)); + this.pipeline = pipeline2; + this.storageClientContext = new StorageContextClient_js_1.StorageContextClient(this.url, (0, Pipeline_js_1.getCoreClientOptions)(pipeline2)); this.isHttps = (0, utils_common_js_1.iEqual)((0, utils_common_js_1.getURLScheme)(this.url) || "", "https"); - this.credential = (0, Pipeline_js_1.getCredentialFromPipeline)(pipeline); + this.credential = (0, Pipeline_js_1.getCredentialFromPipeline)(pipeline2); const storageClientContext = this.storageClientContext; storageClientContext.requestContentType = void 0; } @@ -68669,21 +68669,21 @@ var require_Clients = __commonJS({ } constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, options) { options = options || {}; - let pipeline; + let pipeline2; let url2; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = credentialOrPipelineOrContainerName; + pipeline2 = credentialOrPipelineOrContainerName; } else if (core_util_1.isNodeLike && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; options = blobNameOrOptions; - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url2 = urlOrConnectionString; if (blobNameOrOptions && typeof blobNameOrOptions !== "string") { options = blobNameOrOptions; } - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string" && blobNameOrOptions && typeof blobNameOrOptions === "string") { const containerName = credentialOrPipelineOrContainerName; const blobName = blobNameOrOptions; @@ -68695,20 +68695,20 @@ var require_Clients = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url2 = (0, utils_common_js_1.appendToURLPath)((0, utils_common_js_1.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName)) + "?" + extractedCreds.accountSas; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for containerName and blobName parameters"); } - super(url2, pipeline); + super(url2, pipeline2); ({ blobName: this._name, containerName: this._containerName } = this.getBlobAndContainerNamesFromUrl()); this.blobContext = this.storageClientContext.blob; this._snapshot = (0, utils_common_js_1.getURLParameter)(this.url, constants_js_1.URLConstants.Parameters.SNAPSHOT); @@ -69694,19 +69694,19 @@ var require_Clients = __commonJS({ */ appendBlobContext; constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, options) { - let pipeline; + let pipeline2; let url2; options = options || {}; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = credentialOrPipelineOrContainerName; + pipeline2 = credentialOrPipelineOrContainerName; } else if (core_util_1.isNodeLike && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; options = blobNameOrOptions; - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url2 = urlOrConnectionString; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string" && blobNameOrOptions && typeof blobNameOrOptions === "string") { const containerName = credentialOrPipelineOrContainerName; const blobName = blobNameOrOptions; @@ -69718,20 +69718,20 @@ var require_Clients = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url2 = (0, utils_common_js_1.appendToURLPath)((0, utils_common_js_1.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName)) + "?" + extractedCreds.accountSas; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for containerName and blobName parameters"); } - super(url2, pipeline); + super(url2, pipeline2); this.appendBlobContext = this.storageClientContext.appendBlob; } /** @@ -69967,22 +69967,22 @@ var require_Clients = __commonJS({ */ blockBlobContext; constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, options) { - let pipeline; + let pipeline2; let url2; options = options || {}; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = credentialOrPipelineOrContainerName; + pipeline2 = credentialOrPipelineOrContainerName; } else if (core_util_1.isNodeLike && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; options = blobNameOrOptions; - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url2 = urlOrConnectionString; if (blobNameOrOptions && typeof blobNameOrOptions !== "string") { options = blobNameOrOptions; } - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string" && blobNameOrOptions && typeof blobNameOrOptions === "string") { const containerName = credentialOrPipelineOrContainerName; const blobName = blobNameOrOptions; @@ -69994,20 +69994,20 @@ var require_Clients = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url2 = (0, utils_common_js_1.appendToURLPath)((0, utils_common_js_1.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName)) + "?" + extractedCreds.accountSas; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for containerName and blobName parameters"); } - super(url2, pipeline); + super(url2, pipeline2); this.blockBlobContext = this.storageClientContext.blockBlob; this._blobContext = this.storageClientContext.blob; } @@ -70579,19 +70579,19 @@ var require_Clients = __commonJS({ */ pageBlobContext; constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, options) { - let pipeline; + let pipeline2; let url2; options = options || {}; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = credentialOrPipelineOrContainerName; + pipeline2 = credentialOrPipelineOrContainerName; } else if (core_util_1.isNodeLike && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; options = blobNameOrOptions; - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url2 = urlOrConnectionString; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string" && blobNameOrOptions && typeof blobNameOrOptions === "string") { const containerName = credentialOrPipelineOrContainerName; const blobName = blobNameOrOptions; @@ -70603,20 +70603,20 @@ var require_Clients = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url2 = (0, utils_common_js_1.appendToURLPath)((0, utils_common_js_1.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName)) + "?" + extractedCreds.accountSas; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for containerName and blobName parameters"); } - super(url2, pipeline); + super(url2, pipeline2); this.pageBlobContext = this.storageClientContext.pageBlob; } /** @@ -71681,10 +71681,10 @@ var require_BlobBatch = __commonJS({ accountKey: credential.accountKey }), { phase: "Sign" }); } - const pipeline = new Pipeline_js_1.Pipeline([]); - pipeline._credential = credential; - pipeline._corePipeline = corePipeline; - return pipeline; + const pipeline2 = new Pipeline_js_1.Pipeline([]); + pipeline2._credential = credential; + pipeline2._corePipeline = corePipeline; + return pipeline2; } appendSubRequestToBody(request3) { this.body += [ @@ -71776,15 +71776,15 @@ var require_BlobBatchClient = __commonJS({ var BlobBatchClient = class { serviceOrContainerContext; constructor(url2, credentialOrPipeline, options) { - let pipeline; + let pipeline2; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipeline)) { - pipeline = credentialOrPipeline; + pipeline2 = credentialOrPipeline; } else if (!credentialOrPipeline) { - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipeline, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipeline, options); } - const storageClientContext = new StorageContextClient_js_1.StorageContextClient(url2, (0, Pipeline_js_1.getCoreClientOptions)(pipeline)); + const storageClientContext = new StorageContextClient_js_1.StorageContextClient(url2, (0, Pipeline_js_1.getCoreClientOptions)(pipeline2)); const path29 = (0, utils_common_js_1.getURLPath)(url2); if (path29 && path29 !== "/") { this.serviceOrContainerContext = storageClientContext.container; @@ -71947,18 +71947,18 @@ var require_ContainerClient = __commonJS({ return this._containerName; } constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, options) { - let pipeline; + let pipeline2; let url2; options = options || {}; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = credentialOrPipelineOrContainerName; + pipeline2 = credentialOrPipelineOrContainerName; } else if (core_util_1.isNodeLike && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipelineOrContainerName)) { url2 = urlOrConnectionString; - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url2 = urlOrConnectionString; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string") { const containerName = credentialOrPipelineOrContainerName; const extractedCreds = (0, utils_common_js_1.extractConnectionStringParts)(urlOrConnectionString); @@ -71969,20 +71969,20 @@ var require_ContainerClient = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url2 = (0, utils_common_js_1.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)) + "?" + extractedCreds.accountSas; - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } else { throw new Error("Expecting non-empty strings for containerName parameter"); } - super(url2, pipeline); + super(url2, pipeline2); this._containerName = this.getContainerNameFromUrl(); this.containerContext = this.storageClientContext.container; } @@ -73660,28 +73660,28 @@ var require_BlobServiceClient = __commonJS({ if (!options.proxyOptions) { options.proxyOptions = (0, core_rest_pipeline_1.getDefaultProxySettings)(extractedCreds.proxyUri); } - const pipeline = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); - return new _BlobServiceClient(extractedCreds.url, pipeline); + const pipeline2 = (0, Pipeline_js_1.newPipeline)(sharedKeyCredential, options); + return new _BlobServiceClient(extractedCreds.url, pipeline2); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { - const pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); - return new _BlobServiceClient(extractedCreds.url + "?" + extractedCreds.accountSas, pipeline); + const pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + return new _BlobServiceClient(extractedCreds.url + "?" + extractedCreds.accountSas, pipeline2); } else { throw new Error("Connection string must be either an Account connection string or a SAS connection string"); } } constructor(url2, credentialOrPipeline, options) { - let pipeline; + let pipeline2; if ((0, Pipeline_js_1.isPipelineLike)(credentialOrPipeline)) { - pipeline = credentialOrPipeline; + pipeline2 = credentialOrPipeline; } else if (core_util_1.isNodeLike && credentialOrPipeline instanceof StorageSharedKeyCredential_js_1.StorageSharedKeyCredential || credentialOrPipeline instanceof AnonymousCredential_js_1.AnonymousCredential || (0, core_auth_1.isTokenCredential)(credentialOrPipeline)) { - pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipeline, options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(credentialOrPipeline, options); } else { - pipeline = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); + pipeline2 = (0, Pipeline_js_1.newPipeline)(new AnonymousCredential_js_1.AnonymousCredential(), options); } - super(url2, pipeline); + super(url2, pipeline2); this.serviceContext = this.storageClientContext.service; } /** @@ -75082,8 +75082,8 @@ var require_downloadUtils = __commonJS({ var abort_controller_1 = require_dist4(); function pipeResponseToStream(response, output) { return __awaiter2(this, void 0, void 0, function* () { - const pipeline = util3.promisify(stream2.pipeline); - yield pipeline(response.message, output); + const pipeline2 = util3.promisify(stream2.pipeline); + yield pipeline2(response.message, output); }); } var DownloadProgress = class { @@ -82212,12 +82212,12 @@ var require_tool_cache = __commonJS({ core31.debug(`Failed to download from "${url2}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); throw err; } - const pipeline = util3.promisify(stream2.pipeline); + const pipeline2 = util3.promisify(stream2.pipeline); const responseMessageFactory = _getGlobal("TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY", () => response.message); const readStream = responseMessageFactory(); let succeeded = false; try { - yield pipeline(readStream, fs31.createWriteStream(dest)); + yield pipeline2(readStream, fs31.createWriteStream(dest)); core31.debug("download complete"); succeeded = true; return dest; @@ -100809,7 +100809,7 @@ var require_pipeline4 = __commonJS({ } } } - function pipeline(...streams) { + function pipeline2(...streams) { return pipelineImpl(streams, once(popCallback(streams))); } function pipelineImpl(streams, callback, opts) { @@ -101075,7 +101075,7 @@ var require_pipeline4 = __commonJS({ } module2.exports = { pipelineImpl, - pipeline + pipeline: pipeline2 }; } }); @@ -101084,7 +101084,7 @@ var require_pipeline4 = __commonJS({ var require_compose = __commonJS({ "node_modules/readable-stream/lib/internal/streams/compose.js"(exports2, module2) { "use strict"; - var { pipeline } = require_pipeline4(); + var { pipeline: pipeline2 } = require_pipeline4(); var Duplex = require_duplex(); var { destroyer } = require_destroy2(); var { @@ -101144,7 +101144,7 @@ var require_compose = __commonJS({ } } const head = streams[0]; - const tail = pipeline(streams, onfinished); + const tail = pipeline2(streams, onfinished); const writable = !!(isWritable(head) || isWritableStream(head) || isTransformStream(head)); const readable = !!(isReadable(tail) || isReadableStream(tail) || isTransformStream(tail)); d = new Duplex({ @@ -101687,7 +101687,7 @@ var require_promises = __commonJS({ var { pipelineImpl: pl } = require_pipeline4(); var { finished } = require_end_of_stream(); require_stream2(); - function pipeline(...streams) { + function pipeline2(...streams) { return new Promise2((resolve14, reject) => { let signal; let end; @@ -101715,7 +101715,7 @@ var require_promises = __commonJS({ } module2.exports = { finished, - pipeline + pipeline: pipeline2 }; } }); @@ -101735,7 +101735,7 @@ var require_stream2 = __commonJS({ } = require_errors4(); var compose = require_compose(); var { setDefaultHighWaterMark, getDefaultHighWaterMark } = require_state3(); - var { pipeline } = require_pipeline4(); + var { pipeline: pipeline2 } = require_pipeline4(); var { destroyer } = require_destroy2(); var eos = require_end_of_stream(); var promises6 = require_promises(); @@ -101799,7 +101799,7 @@ var require_stream2 = __commonJS({ Stream.Duplex = require_duplex(); Stream.Transform = require_transform(); Stream.PassThrough = require_passthrough2(); - Stream.pipeline = pipeline; + Stream.pipeline = pipeline2; var { addAbortSignal } = require_add_abort_signal(); Stream.addAbortSignal = addAbortSignal; Stream.finished = eos; @@ -101815,7 +101815,7 @@ var require_stream2 = __commonJS({ return promises6; } }); - ObjectDefineProperty(pipeline, customPromisify, { + ObjectDefineProperty(pipeline2, customPromisify, { __proto__: null, enumerable: true, get() { @@ -109038,13 +109038,13 @@ var require_streamx = __commonJS({ } function pipelinePromise(...streams) { return new Promise((resolve14, reject) => { - return pipeline(...streams, (err) => { + return pipeline2(...streams, (err) => { if (err) return reject(err); resolve14(); }); }); } - function pipeline(stream2, ...streams) { + function pipeline2(stream2, ...streams) { const all = Array.isArray(stream2) ? [...stream2, ...streams] : [stream2, ...streams]; const done = all.length && typeof all[all.length - 1] === "function" ? all.pop() : null; if (all.length < 2) throw new Error("Pipeline requires at least 2 streams"); @@ -109129,7 +109129,7 @@ var require_streamx = __commonJS({ return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev; } module2.exports = { - pipeline, + pipeline: pipeline2, pipelinePromise, isStream: isStream2, isStreamx, @@ -150565,10 +150565,12 @@ async function extractTarZst(tar, dest, tarVersion, logger) { 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}`) - ); + stream.pipeline(tar, tarProcess.stdin, (err) => { + if (err) { + reject( + new Error(`Error while downloading and extracting tar: ${err}`) + ); + } }); } tarProcess.on("exit", (code) => { @@ -150615,6 +150617,7 @@ 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 STREAMING_STALL_TIMEOUT_MS = 5 * 60 * 1e3; var TOOLCACHE_TOOL_NAME = "CodeQL"; async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorization, headers, tarVersion, logger) { logger.info( @@ -150692,8 +150695,8 @@ async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorizatio authorization ? { authorization } : {}, headers ); - const response = await new Promise( - (resolve14) => import_follow_redirects.https.get( + const response = await new Promise((resolve14, reject) => { + const request3 = import_follow_redirects.https.get( codeqlURL, { headers, @@ -150703,9 +150706,18 @@ async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorizatio agent }, (r) => resolve14(r) - ) - ); + ); + request3.on("error", reject); + request3.setTimeout(STREAMING_STALL_TIMEOUT_MS, () => { + request3.destroy( + new Error( + `No data received for ${formatDuration(STREAMING_STALL_TIMEOUT_MS)}.` + ) + ); + }); + }); if (response.statusCode !== 200) { + response.resume(); throw new Error( `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.` ); diff --git a/src/tar.test.ts b/src/tar.test.ts new file mode 100644 index 0000000000..48f4e866d3 --- /dev/null +++ b/src/tar.test.ts @@ -0,0 +1,33 @@ +import * as path from "path"; +import * as stream from "stream"; + +import test from "ava"; + +import { getRunnerLogger } from "./logging"; +import { extractTarZst } from "./tar"; +import { setupTests } from "./testing-utils"; +import { withTmpDir } from "./util"; + +setupTests(test); + +test("extractTarZst rejects if the input stream errors", async (t) => { + await withTmpDir(async (tmpDir) => { + const archive = new stream.PassThrough(); + const promise = extractTarZst( + archive, + path.join(tmpDir, "dest"), + { type: "gnu", version: "1.34" }, + getRunnerLogger(true), + ); + + archive.destroy( + Object.assign(new Error("socket hang up"), { + code: "ECONNRESET", + }), + ); + + await t.throwsAsync(promise, { + message: /Error while downloading and extracting tar/, + }); + }); +}); diff --git a/src/tar.ts b/src/tar.ts index 723716b016..3a0d79cc64 100644 --- a/src/tar.ts +++ b/src/tar.ts @@ -194,10 +194,15 @@ export async function extractTarZst( }); if (tar instanceof stream.Readable) { - tar.pipe(tarProcess.stdin).on("error", (err) => { - reject( - new Error(`Error while downloading and extracting tar: ${err}`), - ); + // Use `pipeline` rather than `pipe` so that an error on either stream is reported here + // rather than being emitted as an unhandled `error` event, and so that `tar`'s standard + // input is closed if the download fails partway through. + stream.pipeline(tar, tarProcess.stdin, (err) => { + if (err) { + reject( + new Error(`Error while downloading and extracting tar: ${err}`), + ); + } }); } diff --git a/src/tools-download.test.ts b/src/tools-download.test.ts index e17d38c5be..66fe0e72e4 100644 --- a/src/tools-download.test.ts +++ b/src/tools-download.test.ts @@ -38,6 +38,43 @@ test.serial( }, ); +test.serial( + "downloadAndExtract falls back to downloading before extracting if streaming fails", + async (t) => { + await withTmpDir(async (tmpDir) => { + sinon.stub(process, "platform").value("linux"); + const archivePath = path.join(tmpDir, "codeql-bundle.tar.zst"); + const destination = path.join(tmpDir, "codeql"); + const downloadTool = sinon + .stub(toolcache, "downloadTool") + .resolves(archivePath); + const extract = sinon.stub(tar, "extract").resolves(destination); + const extractTarZst = sinon.stub(tar, "extractTarZst").resolves(); + const request = nock("https://example.com") + .get("/codeql-bundle.tar.zst") + .replyWithError( + Object.assign(new Error("socket hang up"), { code: "ECONNRESET" }), + ); + + const statusReport = await downloadAndExtract( + "https://example.com/codeql-bundle.tar.zst", + "zstd", + destination, + undefined, + {}, + { type: "gnu", version: "1.34" }, + getRunnerLogger(true), + ); + + t.assert(Number.isInteger(statusReport.downloadDurationMs)); + t.true(request.isDone()); + t.false(extractTarZst.called); + t.true(downloadTool.calledOnce); + t.true(extract.calledOnce); + }); + }, +); + test.serial( "downloadAndExtract omits the download duration when streaming extraction", async (t) => { diff --git a/src/tools-download.ts b/src/tools-download.ts index c19cedb13e..9b2fa8723a 100644 --- a/src/tools-download.ts +++ b/src/tools-download.ts @@ -19,6 +19,12 @@ import { cleanUpPath, getErrorMessage, getRequiredEnvParam } from "./util"; */ const STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; // 4 MiB +/** + * How long the streaming download of the CodeQL tools may stall for before we abort it. This + * applies both to establishing the connection and to gaps between chunks of the response body. + */ +const STREAMING_STALL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes + /** * The name of the tool cache directory for the CodeQL tools. */ @@ -137,8 +143,8 @@ async function downloadAndExtractZstdWithStreaming( authorization ? { authorization } : {}, headers, ); - const response = await new Promise((resolve) => - https.get( + const response = await new Promise((resolve, reject) => { + const request = https.get( codeqlURL, { headers, @@ -148,10 +154,24 @@ async function downloadAndExtractZstdWithStreaming( agent, } as unknown as RequestOptions, (r) => resolve(r), - ), - ); + ); + // Without this listener, connection failures such as `ECONNRESET` are emitted as unhandled + // `error` events, which terminate the process instead of letting us fall back to downloading + // the bundle before extracting it. This listener stays attached after the response arrives, so + // it also handles errors that occur while the response is being streamed. + request.on("error", reject); + request.setTimeout(STREAMING_STALL_TIMEOUT_MS, () => { + request.destroy( + new Error( + `No data received for ${formatDuration(STREAMING_STALL_TIMEOUT_MS)}.`, + ), + ); + }); + }); if (response.statusCode !== 200) { + // Discard the response body so that the connection can be released. + response.resume(); throw new Error( `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.`, ); From 155e5229973b426bd1ae2f83bb1bf42417fa2a8f Mon Sep 17 00:00:00 2001 From: sim Date: Thu, 30 Jul 2026 18:48:10 +0100 Subject: [PATCH 33/39] Link the PR from the changelog entry Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c461878c51..36092606b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th ## [UNRELEASED] -- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#3367](https://github.com/github/codeql-action/issues/3367) +- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061) ## 4.37.4 - 29 Jul 2026 From c29563eeaafbc75499c7bb0d74bf77b3506c1cbd Mon Sep 17 00:00:00 2001 From: Sam Robson Date: Fri, 31 Jul 2026 10:10:39 +0100 Subject: [PATCH 34/39] ci: use federated enterprise release PAT --- .../workflows/update-supported-enterprise-server-versions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-supported-enterprise-server-versions.yml b/.github/workflows/update-supported-enterprise-server-versions.yml index 01cd6ab8fb..ee2649ad0e 100644 --- a/.github/workflows/update-supported-enterprise-server-versions.yml +++ b/.github/workflows/update-supported-enterprise-server-versions.yml @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: github/enterprise-releases - token: ${{ secrets.ENTERPRISE_RELEASE_TOKEN }} + token: ${{ secrets.CODEQL_CI_ENTERPRISE_RELEASE_PAT }} path: ${{ github.workspace }}/enterprise-releases/ sparse-checkout: releases.json From e74600b0d945db9734eb044f95cd43f34b773451 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 09:18:21 +0000 Subject: [PATCH 35/39] Update changelog for v4.37.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36092606b4..0008822f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## [UNRELEASED] +## 4.37.5 - 03 Aug 2026 - Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061) From 2c538e64039da33fbf9c014fd6f75cff3c1011f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:09:40 +0000 Subject: [PATCH 36/39] Revert "Update version and changelog for v3.37.4" This reverts commit 93539ac81b75263db7b19c95c7ec9af06ae0861f. --- CHANGELOG.md | 82 ++++++++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e18fd0e2..51bb95d5c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,62 +2,62 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## 3.37.4 - 29 Jul 2026 +## 4.37.4 - 29 Jul 2026 - This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037) - Update default CodeQL bundle version to [2.26.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2). [#4051](https://github.com/github/codeql-action/pull/4051) -## 3.37.3 - 22 Jul 2026 +## 4.37.3 - 22 Jul 2026 No user facing changes. -## 3.37.2 - 21 Jul 2026 +## 4.37.2 - 21 Jul 2026 - The new address format for the `config-file` input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the `remote=` prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. [#4023](https://github.com/github/codeql-action/pull/4023) - The CodeQL Action can now make use of [configured private registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. [#4007](https://github.com/github/codeql-action/pull/4007) -## 3.37.1 - 16 Jul 2026 +## 4.37.1 - 16 Jul 2026 - _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. [#3956](https://github.com/github/codeql-action/pull/3956) - Update default CodeQL bundle version to [2.26.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1). [#4019](https://github.com/github/codeql-action/pull/4019) -## 3.37.0 - 08 Jul 2026 +## 4.37.0 - 08 Jul 2026 - Update default CodeQL bundle version to [2.26.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0). [#3995](https://github.com/github/codeql-action/pull/3995) - In addition to the existing input format, the `config-file` input for the `codeql-action/init` step will soon support a new `[owner/]repo[@ref][:path]` format. All components except the repository name are optional. If omitted, `owner` defaults to the same owner as the repository the analysis is running for, `ref` to `main`, and `path` to `.github/codeql-action.yaml`. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. [#3973](https://github.com/github/codeql-action/pull/3973) -## 3.36.3 - 01 Jul 2026 +## 4.36.3 - 01 Jul 2026 No user facing changes. -## 3.36.2 - 04 Jun 2026 +## 4.36.2 - 04 Jun 2026 - Cache CodeQL CLI version information across Actions steps. [#3943](https://github.com/github/codeql-action/pull/3943) - Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. [#3937](https://github.com/github/codeql-action/pull/3937) - Update default CodeQL bundle version to [2.25.6](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6). [#3948](https://github.com/github/codeql-action/pull/3948) -## 3.36.1 - 02 Jun 2026 +## 4.36.1 - 02 Jun 2026 No user facing changes. -## 3.36.0 - 22 May 2026 +## 4.36.0 - 22 May 2026 - _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894) - Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893) - Update default CodeQL bundle version to [2.25.5](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5). [#3926](https://github.com/github/codeql-action/pull/3926) -## 3.35.5 - 15 May 2026 +## 4.35.5 - 15 May 2026 - We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899) - For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791) - If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892) - Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880) -## 3.35.4 - 07 May 2026 +## 4.35.4 - 07 May 2026 - Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881) -## 3.35.3 - 01 May 2026 +## 4.35.3 - 01 May 2026 - _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837) - Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. [#3850](https://github.com/github/codeql-action/pull/3850) @@ -65,7 +65,7 @@ No user facing changes. - Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. [#3852](https://github.com/github/codeql-action/pull/3852) - Update default CodeQL bundle version to [2.25.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3). [#3865](https://github.com/github/codeql-action/pull/3865) -## 3.35.2 - 15 Apr 2026 +## 4.35.2 - 15 Apr 2026 - The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#3795](https://github.com/github/codeql-action/pull/3795) - The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. [#3789](https://github.com/github/codeql-action/pull/3789) @@ -73,26 +73,26 @@ No user facing changes. - Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. [#3807](https://github.com/github/codeql-action/pull/3807) - Update default CodeQL bundle version to [2.25.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.2). [#3823](https://github.com/github/codeql-action/pull/3823) -## 3.35.1 - 27 Mar 2026 +## 4.35.1 - 27 Mar 2026 - Fix incorrect minimum required Git version for [improved incremental analysis](https://github.com/github/roadmap/issues/1158): it should have been 2.36.0, not 2.11.0. [#3781](https://github.com/github/codeql-action/pull/3781) -## 3.35.0 - 27 Mar 2026 +## 4.35.0 - 27 Mar 2026 - Reduced the minimum Git version required for [improved incremental analysis](https://github.com/github/roadmap/issues/1158) from 2.38.0 to 2.11.0. [#3767](https://github.com/github/codeql-action/pull/3767) - Update default CodeQL bundle version to [2.25.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.1). [#3773](https://github.com/github/codeql-action/pull/3773) -## 3.34.1 - 20 Mar 2026 +## 4.34.1 - 20 Mar 2026 - Downgrade default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3) due to issues with a small percentage of Actions and JavaScript analyses. [#3762](https://github.com/github/codeql-action/pull/3762) -## 3.34.0 - 20 Mar 2026 +## 4.34.0 - 20 Mar 2026 - Added an experimental change which disables TRAP caching when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. [#3569](https://github.com/github/codeql-action/pull/3569) - We are rolling out improved incremental analysis to C/C++ analyses that use build mode `none`. We expect this rollout to be complete by the end of April 2026. [#3584](https://github.com/github/codeql-action/pull/3584) - Update default CodeQL bundle version to [2.25.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.0). [#3585](https://github.com/github/codeql-action/pull/3585) -## 3.33.0 - 16 Mar 2026 +## 4.33.0 - 16 Mar 2026 - Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. [#3562](https://github.com/github/codeql-action/pull/3562) @@ -106,11 +106,11 @@ No user facing changes. - Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". [#3564](https://github.com/github/codeql-action/pull/3564) - A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. [#3570](https://github.com/github/codeql-action/pull/3570) -## 3.32.6 - 05 Mar 2026 +## 4.32.6 - 05 Mar 2026 - Update default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3). [#3548](https://github.com/github/codeql-action/pull/3548) -## 3.32.5 - 02 Mar 2026 +## 4.32.5 - 02 Mar 2026 - Repositories owned by an organization can now set up the `github-codeql-disable-overlay` custom repository property to disable [improved incremental analysis for CodeQL](https://github.com/github/roadmap/issues/1158). First, create a custom repository property with the name `github-codeql-disable-overlay` and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to `true` to disable improved incremental analysis. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature is not yet available on GitHub Enterprise Server. [#3507](https://github.com/github/codeql-action/pull/3507) - Added an experimental change so that when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. [#3487](https://github.com/github/codeql-action/pull/3487) @@ -120,7 +120,7 @@ No user facing changes. - Added an experimental change which allows the `start-proxy` action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. [#3512](https://github.com/github/codeql-action/pull/3512) - The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. [#3503](https://github.com/github/codeql-action/pull/3503), [#3504](https://github.com/github/codeql-action/pull/3504) -## 3.32.4 - 20 Feb 2026 +## 4.32.4 - 20 Feb 2026 - Update default CodeQL bundle version to [2.24.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.2). [#3493](https://github.com/github/codeql-action/pull/3493) - Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. [#3473](https://github.com/github/codeql-action/pull/3473) @@ -128,89 +128,89 @@ No user facing changes. - Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. [#3485](https://github.com/github/codeql-action/pull/3485) - Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a [nightly CodeQL CLI release](https://github.com/dsp-testing/codeql-cli-nightlies) instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. [#3484](https://github.com/github/codeql-action/pull/3484) -## 3.32.3 - 13 Feb 2026 +## 4.32.3 - 13 Feb 2026 - Added experimental support for testing connections to [private package registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. [#3466](https://github.com/github/codeql-action/pull/3466) -## 3.32.2 - 05 Feb 2026 +## 4.32.2 - 05 Feb 2026 - Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://github.com/github/codeql-action/pull/3460) -## 3.32.1 - 02 Feb 2026 +## 4.32.1 - 02 Feb 2026 - A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://github.com/github/codeql-action/pull/3422) - Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://github.com/github/codeql-action/pull/3421) -## 3.32.0 - 26 Jan 2026 +## 4.32.0 - 26 Jan 2026 - Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://github.com/github/codeql-action/pull/3425) -## 3.31.11 - 23 Jan 2026 +## 4.31.11 - 23 Jan 2026 - When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://github.com/github/codeql-action/pull/3409) - Improved error handling throughout the CodeQL Action. [#3415](https://github.com/github/codeql-action/pull/3415) - Added experimental support for automatically excluding [generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. [#3318](https://github.com/github/codeql-action/pull/3318) - The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. [#3403](https://github.com/github/codeql-action/pull/3403) -## 3.31.10 - 12 Jan 2026 +## 4.31.10 - 12 Jan 2026 - Update default CodeQL bundle version to 2.23.9. [#3393](https://github.com/github/codeql-action/pull/3393) -## 3.31.9 - 16 Dec 2025 +## 4.31.9 - 16 Dec 2025 No user facing changes. -## 3.31.8 - 11 Dec 2025 +## 4.31.8 - 11 Dec 2025 - Update default CodeQL bundle version to 2.23.8. [#3354](https://github.com/github/codeql-action/pull/3354) -## 3.31.7 - 05 Dec 2025 +## 4.31.7 - 05 Dec 2025 - Update default CodeQL bundle version to 2.23.7. [#3343](https://github.com/github/codeql-action/pull/3343) -## 3.31.6 - 01 Dec 2025 +## 4.31.6 - 01 Dec 2025 No user facing changes. -## 3.31.5 - 24 Nov 2025 +## 4.31.5 - 24 Nov 2025 - Update default CodeQL bundle version to 2.23.6. [#3321](https://github.com/github/codeql-action/pull/3321) -## 3.31.4 - 18 Nov 2025 +## 4.31.4 - 18 Nov 2025 No user facing changes. -## 3.31.3 - 13 Nov 2025 +## 4.31.3 - 13 Nov 2025 - CodeQL Action v3 will be deprecated in December 2026. The Action now logs a warning for customers who are running v3 but could be running v4. For more information, see [Upcoming deprecation of CodeQL Action v3](https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/). - Update default CodeQL bundle version to 2.23.5. [#3288](https://github.com/github/codeql-action/pull/3288) -## 3.31.2 - 30 Oct 2025 +## 4.31.2 - 30 Oct 2025 No user facing changes. -## 3.31.1 - 30 Oct 2025 +## 4.31.1 - 30 Oct 2025 - The `add-snippets` input has been removed from the `analyze` action. This input has been deprecated since CodeQL Action 3.26.4 in August 2024 when this removal was announced. -## 3.31.0 - 24 Oct 2025 +## 4.31.0 - 24 Oct 2025 - Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223) - When SARIF files are uploaded by the `analyze` or `upload-sarif` actions, the CodeQL Action automatically performs post-processing steps to prepare the data for the upload. Previously, these post-processing steps were only performed before an upload took place. We are now changing this so that the post-processing steps will always be performed, even when the SARIF files are not uploaded. This does not change anything for the `upload-sarif` action. For `analyze`, this may affect Advanced Setup for CodeQL users who specify a value other than `always` for the `upload` input. [#3222](https://github.com/github/codeql-action/pull/3222) -## 3.30.9 - 17 Oct 2025 +## 4.30.9 - 17 Oct 2025 - Update default CodeQL bundle version to 2.23.3. [#3205](https://github.com/github/codeql-action/pull/3205) - Experimental: A new `setup-codeql` action has been added which is similar to `init`, except it only installs the CodeQL CLI and does not initialize a database. Do not use this in production as it is part of an internal experiment and subject to change at any time. [#3204](https://github.com/github/codeql-action/pull/3204) -## 3.30.8 - 10 Oct 2025 +## 4.30.8 - 10 Oct 2025 No user facing changes. -## 3.30.7 - 06 Oct 2025 +## 4.30.7 - 06 Oct 2025 +- [v4+ only] The CodeQL Action now runs on Node.js v24. [#3169](https://github.com/github/codeql-action/pull/3169) -No user facing changes. ## 3.30.6 - 02 Oct 2025 - Update default CodeQL bundle version to 2.23.2. [#3168](https://github.com/github/codeql-action/pull/3168) diff --git a/package.json b/package.json index 7a844edacf..cdd58cd167 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "3.37.4", + "version": "4.37.4", "private": true, "description": "CodeQL action", "scripts": { From 5667eabe3b41f4b1f77ff962c30b7743885774b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:09:40 +0000 Subject: [PATCH 37/39] Revert "Rebuild" This reverts commit 85722ca3f87110ef5fcc4f079b293ce98a4aff99. --- lib/entry-points.js | 2 +- package-lock.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index bdfda1701c..eb81affd67 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145404,7 +145404,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "3.37.4"; + return "4.37.4"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); diff --git a/package-lock.json b/package-lock.json index 297b558485..a01b4a12e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "3.37.4", + "version": "4.37.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "3.37.4", + "version": "4.37.4", "license": "MIT", "workspaces": [ "pr-checks" From f44d029dbcdca17977d3573981969c200f6ed8c7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:09:41 +0000 Subject: [PATCH 38/39] Update version and changelog for v3.37.5 --- CHANGELOG.md | 84 ++++++++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0008822f0e..b151ff5510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,66 +2,66 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## 4.37.5 - 03 Aug 2026 +## 3.37.5 - 03 Aug 2026 - Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061) -## 4.37.4 - 29 Jul 2026 +## 3.37.4 - 29 Jul 2026 - This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037) - Update default CodeQL bundle version to [2.26.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2). [#4051](https://github.com/github/codeql-action/pull/4051) -## 4.37.3 - 22 Jul 2026 +## 3.37.3 - 22 Jul 2026 No user facing changes. -## 4.37.2 - 21 Jul 2026 +## 3.37.2 - 21 Jul 2026 - The new address format for the `config-file` input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the `remote=` prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. [#4023](https://github.com/github/codeql-action/pull/4023) - The CodeQL Action can now make use of [configured private registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. [#4007](https://github.com/github/codeql-action/pull/4007) -## 4.37.1 - 16 Jul 2026 +## 3.37.1 - 16 Jul 2026 - _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. [#3956](https://github.com/github/codeql-action/pull/3956) - Update default CodeQL bundle version to [2.26.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1). [#4019](https://github.com/github/codeql-action/pull/4019) -## 4.37.0 - 08 Jul 2026 +## 3.37.0 - 08 Jul 2026 - Update default CodeQL bundle version to [2.26.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0). [#3995](https://github.com/github/codeql-action/pull/3995) - In addition to the existing input format, the `config-file` input for the `codeql-action/init` step will soon support a new `[owner/]repo[@ref][:path]` format. All components except the repository name are optional. If omitted, `owner` defaults to the same owner as the repository the analysis is running for, `ref` to `main`, and `path` to `.github/codeql-action.yaml`. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. [#3973](https://github.com/github/codeql-action/pull/3973) -## 4.36.3 - 01 Jul 2026 +## 3.36.3 - 01 Jul 2026 No user facing changes. -## 4.36.2 - 04 Jun 2026 +## 3.36.2 - 04 Jun 2026 - Cache CodeQL CLI version information across Actions steps. [#3943](https://github.com/github/codeql-action/pull/3943) - Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. [#3937](https://github.com/github/codeql-action/pull/3937) - Update default CodeQL bundle version to [2.25.6](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6). [#3948](https://github.com/github/codeql-action/pull/3948) -## 4.36.1 - 02 Jun 2026 +## 3.36.1 - 02 Jun 2026 No user facing changes. -## 4.36.0 - 22 May 2026 +## 3.36.0 - 22 May 2026 - _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894) - Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893) - Update default CodeQL bundle version to [2.25.5](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5). [#3926](https://github.com/github/codeql-action/pull/3926) -## 4.35.5 - 15 May 2026 +## 3.35.5 - 15 May 2026 - We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899) - For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791) - If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892) - Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880) -## 4.35.4 - 07 May 2026 +## 3.35.4 - 07 May 2026 - Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881) -## 4.35.3 - 01 May 2026 +## 3.35.3 - 01 May 2026 - _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837) - Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. [#3850](https://github.com/github/codeql-action/pull/3850) @@ -69,7 +69,7 @@ No user facing changes. - Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. [#3852](https://github.com/github/codeql-action/pull/3852) - Update default CodeQL bundle version to [2.25.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3). [#3865](https://github.com/github/codeql-action/pull/3865) -## 4.35.2 - 15 Apr 2026 +## 3.35.2 - 15 Apr 2026 - The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#3795](https://github.com/github/codeql-action/pull/3795) - The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. [#3789](https://github.com/github/codeql-action/pull/3789) @@ -77,26 +77,26 @@ No user facing changes. - Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. [#3807](https://github.com/github/codeql-action/pull/3807) - Update default CodeQL bundle version to [2.25.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.2). [#3823](https://github.com/github/codeql-action/pull/3823) -## 4.35.1 - 27 Mar 2026 +## 3.35.1 - 27 Mar 2026 - Fix incorrect minimum required Git version for [improved incremental analysis](https://github.com/github/roadmap/issues/1158): it should have been 2.36.0, not 2.11.0. [#3781](https://github.com/github/codeql-action/pull/3781) -## 4.35.0 - 27 Mar 2026 +## 3.35.0 - 27 Mar 2026 - Reduced the minimum Git version required for [improved incremental analysis](https://github.com/github/roadmap/issues/1158) from 2.38.0 to 2.11.0. [#3767](https://github.com/github/codeql-action/pull/3767) - Update default CodeQL bundle version to [2.25.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.1). [#3773](https://github.com/github/codeql-action/pull/3773) -## 4.34.1 - 20 Mar 2026 +## 3.34.1 - 20 Mar 2026 - Downgrade default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3) due to issues with a small percentage of Actions and JavaScript analyses. [#3762](https://github.com/github/codeql-action/pull/3762) -## 4.34.0 - 20 Mar 2026 +## 3.34.0 - 20 Mar 2026 - Added an experimental change which disables TRAP caching when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. [#3569](https://github.com/github/codeql-action/pull/3569) - We are rolling out improved incremental analysis to C/C++ analyses that use build mode `none`. We expect this rollout to be complete by the end of April 2026. [#3584](https://github.com/github/codeql-action/pull/3584) - Update default CodeQL bundle version to [2.25.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.0). [#3585](https://github.com/github/codeql-action/pull/3585) -## 4.33.0 - 16 Mar 2026 +## 3.33.0 - 16 Mar 2026 - Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. [#3562](https://github.com/github/codeql-action/pull/3562) @@ -110,11 +110,11 @@ No user facing changes. - Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". [#3564](https://github.com/github/codeql-action/pull/3564) - A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. [#3570](https://github.com/github/codeql-action/pull/3570) -## 4.32.6 - 05 Mar 2026 +## 3.32.6 - 05 Mar 2026 - Update default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3). [#3548](https://github.com/github/codeql-action/pull/3548) -## 4.32.5 - 02 Mar 2026 +## 3.32.5 - 02 Mar 2026 - Repositories owned by an organization can now set up the `github-codeql-disable-overlay` custom repository property to disable [improved incremental analysis for CodeQL](https://github.com/github/roadmap/issues/1158). First, create a custom repository property with the name `github-codeql-disable-overlay` and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to `true` to disable improved incremental analysis. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature is not yet available on GitHub Enterprise Server. [#3507](https://github.com/github/codeql-action/pull/3507) - Added an experimental change so that when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. [#3487](https://github.com/github/codeql-action/pull/3487) @@ -124,7 +124,7 @@ No user facing changes. - Added an experimental change which allows the `start-proxy` action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. [#3512](https://github.com/github/codeql-action/pull/3512) - The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. [#3503](https://github.com/github/codeql-action/pull/3503), [#3504](https://github.com/github/codeql-action/pull/3504) -## 4.32.4 - 20 Feb 2026 +## 3.32.4 - 20 Feb 2026 - Update default CodeQL bundle version to [2.24.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.2). [#3493](https://github.com/github/codeql-action/pull/3493) - Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. [#3473](https://github.com/github/codeql-action/pull/3473) @@ -132,89 +132,89 @@ No user facing changes. - Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. [#3485](https://github.com/github/codeql-action/pull/3485) - Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a [nightly CodeQL CLI release](https://github.com/dsp-testing/codeql-cli-nightlies) instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. [#3484](https://github.com/github/codeql-action/pull/3484) -## 4.32.3 - 13 Feb 2026 +## 3.32.3 - 13 Feb 2026 - Added experimental support for testing connections to [private package registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. [#3466](https://github.com/github/codeql-action/pull/3466) -## 4.32.2 - 05 Feb 2026 +## 3.32.2 - 05 Feb 2026 - Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://github.com/github/codeql-action/pull/3460) -## 4.32.1 - 02 Feb 2026 +## 3.32.1 - 02 Feb 2026 - A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://github.com/github/codeql-action/pull/3422) - Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://github.com/github/codeql-action/pull/3421) -## 4.32.0 - 26 Jan 2026 +## 3.32.0 - 26 Jan 2026 - Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://github.com/github/codeql-action/pull/3425) -## 4.31.11 - 23 Jan 2026 +## 3.31.11 - 23 Jan 2026 - When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://github.com/github/codeql-action/pull/3409) - Improved error handling throughout the CodeQL Action. [#3415](https://github.com/github/codeql-action/pull/3415) - Added experimental support for automatically excluding [generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. [#3318](https://github.com/github/codeql-action/pull/3318) - The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. [#3403](https://github.com/github/codeql-action/pull/3403) -## 4.31.10 - 12 Jan 2026 +## 3.31.10 - 12 Jan 2026 - Update default CodeQL bundle version to 2.23.9. [#3393](https://github.com/github/codeql-action/pull/3393) -## 4.31.9 - 16 Dec 2025 +## 3.31.9 - 16 Dec 2025 No user facing changes. -## 4.31.8 - 11 Dec 2025 +## 3.31.8 - 11 Dec 2025 - Update default CodeQL bundle version to 2.23.8. [#3354](https://github.com/github/codeql-action/pull/3354) -## 4.31.7 - 05 Dec 2025 +## 3.31.7 - 05 Dec 2025 - Update default CodeQL bundle version to 2.23.7. [#3343](https://github.com/github/codeql-action/pull/3343) -## 4.31.6 - 01 Dec 2025 +## 3.31.6 - 01 Dec 2025 No user facing changes. -## 4.31.5 - 24 Nov 2025 +## 3.31.5 - 24 Nov 2025 - Update default CodeQL bundle version to 2.23.6. [#3321](https://github.com/github/codeql-action/pull/3321) -## 4.31.4 - 18 Nov 2025 +## 3.31.4 - 18 Nov 2025 No user facing changes. -## 4.31.3 - 13 Nov 2025 +## 3.31.3 - 13 Nov 2025 - CodeQL Action v3 will be deprecated in December 2026. The Action now logs a warning for customers who are running v3 but could be running v4. For more information, see [Upcoming deprecation of CodeQL Action v3](https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/). - Update default CodeQL bundle version to 2.23.5. [#3288](https://github.com/github/codeql-action/pull/3288) -## 4.31.2 - 30 Oct 2025 +## 3.31.2 - 30 Oct 2025 No user facing changes. -## 4.31.1 - 30 Oct 2025 +## 3.31.1 - 30 Oct 2025 - The `add-snippets` input has been removed from the `analyze` action. This input has been deprecated since CodeQL Action 3.26.4 in August 2024 when this removal was announced. -## 4.31.0 - 24 Oct 2025 +## 3.31.0 - 24 Oct 2025 - Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223) - When SARIF files are uploaded by the `analyze` or `upload-sarif` actions, the CodeQL Action automatically performs post-processing steps to prepare the data for the upload. Previously, these post-processing steps were only performed before an upload took place. We are now changing this so that the post-processing steps will always be performed, even when the SARIF files are not uploaded. This does not change anything for the `upload-sarif` action. For `analyze`, this may affect Advanced Setup for CodeQL users who specify a value other than `always` for the `upload` input. [#3222](https://github.com/github/codeql-action/pull/3222) -## 4.30.9 - 17 Oct 2025 +## 3.30.9 - 17 Oct 2025 - Update default CodeQL bundle version to 2.23.3. [#3205](https://github.com/github/codeql-action/pull/3205) - Experimental: A new `setup-codeql` action has been added which is similar to `init`, except it only installs the CodeQL CLI and does not initialize a database. Do not use this in production as it is part of an internal experiment and subject to change at any time. [#3204](https://github.com/github/codeql-action/pull/3204) -## 4.30.8 - 10 Oct 2025 +## 3.30.8 - 10 Oct 2025 No user facing changes. -## 4.30.7 - 06 Oct 2025 +## 3.30.7 - 06 Oct 2025 -- [v4+ only] The CodeQL Action now runs on Node.js v24. [#3169](https://github.com/github/codeql-action/pull/3169) +No user facing changes. ## 3.30.6 - 02 Oct 2025 - Update default CodeQL bundle version to 2.23.2. [#3168](https://github.com/github/codeql-action/pull/3168) diff --git a/package.json b/package.json index 0adeb49ccb..7763c22556 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.37.5", + "version": "3.37.5", "private": true, "description": "CodeQL action", "scripts": { From 01b30f9112d928735ea721c8e9c715be5f38d122 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:09:54 +0000 Subject: [PATCH 39/39] Rebuild --- lib/entry-points.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index b7078c8a5d..384b5dd8af 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145420,7 +145420,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.37.5"; + return "3.37.5"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);