From 738bd621865ef8a960c3af80dff9ddb000ff9ebc Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Fri, 18 Sep 2026 12:50:23 -0500 Subject: [PATCH 01/36] Refactor `changenotes validate` to use helper `getChangenotes` This reduces duplicate code between `assemble` and `validate`. It also has the benefit of fixing a bug in the current implementation of `validate`, where `isValidChangenoteFile` receives a relative file name where it should receive an absolute one. --- pr-checks/changelog/validate.mts | 11 ------- pr-checks/changelog/validate.test.mts | 41 +-------------------------- pr-checks/changenotes.mts | 8 ++++-- 3 files changed, 7 insertions(+), 53 deletions(-) diff --git a/pr-checks/changelog/validate.mts b/pr-checks/changelog/validate.mts index 2e28a4ab1..3c83276f3 100644 --- a/pr-checks/changelog/validate.mts +++ b/pr-checks/changelog/validate.mts @@ -119,14 +119,3 @@ export function isValidChangenoteFile(filename: string): boolean { return isValid; } - -/** - * Validates the change-note files of the given list of file paths, ignoring ".gitkeep". - * @param filepaths A list of filepaths to validate - * @returns True if all the paths are valid, false otherwise. - */ -export function isValidAllChangenoteFiles(filepaths: string[]): boolean { - return filepaths - .filter((f) => f !== ".gitkeep") - .reduce((r, filePath) => r && isValidChangenoteFile(filePath), true); -} diff --git a/pr-checks/changelog/validate.test.mts b/pr-checks/changelog/validate.test.mts index a38339d1c..b8b1e33bb 100644 --- a/pr-checks/changelog/validate.test.mts +++ b/pr-checks/changelog/validate.test.mts @@ -1,13 +1,10 @@ import assert from "node:assert/strict"; -import * as fs from "node:fs"; -import * as path from "node:path"; import { describe, it } from "node:test"; -import { withTmpDir, withTmpFile } from "../../src/util"; +import { withTmpFile } from "../../src/util"; import { hasValidChangenoteCategory, - isValidAllChangenoteFiles, isValidChangenoteContent, isValidChangenoteFile, isValidChangenoteFilename, @@ -187,39 +184,3 @@ await describe("isValidChangenoteFile", async () => { ); }); }); - -await describe("isValidAllChangenoteFiles", async () => { - await it("accepts list of file paths of valid change-notes", async () => { - await withTmpDir(async (tmpDir) => { - const fileName1 = path.join(tmpDir, "2026-01-01-fix-bug.md"); - const fileName2 = path.join(tmpDir, "2026-01-02-add-feature.md"); - fs.writeFileSync(fileName1, "---\ncategory: fix\n---\n- Fixed a bug\n"); - fs.writeFileSync( - fileName2, - "---\ncategory: feature\n---\n- Added a feature\n", - ); - assert.equal(isValidAllChangenoteFiles([fileName1, fileName2]), true); - }); - }); - - await it("accepts the empty list", async () => { - assert.equal(isValidAllChangenoteFiles([]), true); - }); - - await it("accepts list of .gitkeep", async () => { - assert.equal(isValidAllChangenoteFiles([".gitkeep"]), true); - }); - - await it("rejects list containing a file path to an invalid change-note", async () => { - await withTmpDir(async (tmpDir) => { - const fileName1 = path.join(tmpDir, "2026-01-01-fix-bug.md"); - const fileName2 = path.join(tmpDir, "2026-01-02-wrong-category.md"); - fs.writeFileSync(fileName1, "---\ncategory: fix\n---\n- Fixed a bug\n"); - fs.writeFileSync( - fileName2, - "---\ncategory: foobar\n---\n- Added a feature\n", - ); - assert.equal(isValidAllChangenoteFiles([fileName1, fileName2]), false); - }); - }); -}); diff --git a/pr-checks/changenotes.mts b/pr-checks/changenotes.mts index d19d2da83..980d103a2 100755 --- a/pr-checks/changenotes.mts +++ b/pr-checks/changenotes.mts @@ -14,7 +14,7 @@ import { renderChangelog, withChangelog, } from "./changelog"; -import { isValidAllChangenoteFiles } from "./changelog/validate.mjs"; +import { isValidChangenoteFile } from "./changelog/validate.mjs"; import { CHANGENOTES_DIR } from "./config"; /** @@ -116,7 +116,11 @@ function assemble(): ExitCode { function validate(): ExitCode { try { - if (isValidAllChangenoteFiles(fs.readdirSync(CHANGENOTES_DIR))) { + const allChangenotesValid = getChangenotes().reduce( + (r, changenote) => r && isValidChangenoteFile(changenote.absolutePath), + true, + ); + if (allChangenotesValid) { console.log(`All changenotes in '${CHANGENOTES_DIR}' are valid.`); return ExitCode.Success; } From 07dc94940e1af55d7da55811119e389c5acac178 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:07:07 +0100 Subject: [PATCH 02/36] Use default state in per-language bundle tests Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/per-language-bundles.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/per-language-bundles.test.ts b/src/per-language-bundles.test.ts index b8f48512f..0330b51a6 100644 --- a/src/per-language-bundles.test.ts +++ b/src/per-language-bundles.test.ts @@ -38,7 +38,6 @@ async function checkEligibility( [ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted", }), features: createFeatures([Feature.PerLanguageBundles]), - logger: getRecordingLogger([], { logToConsole: false }), ...stateOverrides, }), { ...ELIGIBLE_OPTIONS, ...overrides }, @@ -134,7 +133,6 @@ test("getPerLanguageBundleLanguage explains a disabled feature before checking e const messages: LoggedMessage[] = []; const language = await getPerLanguageBundleLanguage( initAllState({ - env: getTestEnv(), features: createFeatures([]), logger: getRecordingLogger(messages, { logToConsole: false }), }), From 06344e2ba1565124d7acef663be8ff3b6f42643f Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:07:09 +0100 Subject: [PATCH 03/36] Stub nightly release listing directly Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/setup-codeql.test.ts | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index c35bdb840..6ac5bebf1 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -69,25 +69,29 @@ function stubHostedNightly(tagName: string) { available: true, foundZstdBinary: true, }); - const fetchRelease = sinon - .stub, ReturnType>() - .rejects(new Error("Unexpected API request in nightly bundle test")); - fetchRelease - .withArgs( - "https://api.github.com/repos/dsp-testing/codeql-cli-nightlies/releases?per_page=1&page=1&prerelease=true", - sinon.match({ method: "GET" }), - ) - .callsFake( - async () => - new Response(JSON.stringify([{ tag_name: tagName }]), { - headers: { "content-type": "application/json" }, - }), - ); const client = github.getOctokit("123", { - request: { fetch: fetchRelease }, + request: { + fetch: async () => { + throw new Error("Unexpected API request in nightly bundle test"); + }, + }, }); + const listReleases = sinon + .stub(client.rest.repos, "listReleases") + .rejects(new Error("Unexpected release request in nightly bundle test")); + listReleases + .withArgs({ + owner: "dsp-testing", + repo: "codeql-cli-nightlies", + per_page: 1, + page: 1, + prerelease: true, + }) + .resolves({ + data: [{ tag_name: tagName }], + } as Awaited>); sinon.stub(api, "getApiClient").value(() => client); - return fetchRelease; + return listReleases; } test.serial("parse codeql bundle url version", (t) => { From dba87a18dc3eb9d4d09a0585f4148670685519de Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:07:10 +0100 Subject: [PATCH 04/36] Clarify elapsed-time helper documentation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.ts b/src/util.ts index 456cd7c3d..d74e07fa8 100644 --- a/src/util.ts +++ b/src/util.ts @@ -682,7 +682,7 @@ export async function bundleDb( return databaseBundlePath; } -/** Returns the elapsed milliseconds, rounded, since a `performance.now()` timestamp. */ +/** Returns the elapsed milliseconds, rounded, since `startTime` was recorded with `performance.now()`. */ export function durationMsSince(startTime: number): number { return Math.round(performance.now() - startTime); } From a9a8cd1aecbbc419b7b38acc138c3e3cd844b0f9 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:07:10 +0100 Subject: [PATCH 05/36] Explain the nightly bundle version-check exception Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/per-language-bundles.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index f4e46403d..35cfa3e0f 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -102,8 +102,9 @@ export async function getPerLanguageBundleLanguage( return explain("the job is not running on a GitHub-hosted runner"); } - // Check whether per-language bundles are published for the requested CLI version. - // Latest-nightly selection skips this release-version check, but not the other eligibility checks. + // If the user requested the latest nightly, skip the version check, as nightlies have shipped + // per-language bundles since https://github.com/dsp-testing/codeql-cli-nightlies/releases/tag/codeql-bundle-20260909. + // Otherwise, check the requested CLI version to determine whether per-language bundles are published. if (!isLatestNightly) { if (cliVersion === undefined) { return explain("the requested CLI version is unknown"); From f2ec2f6267210c6d22b53d32be7048187043bd34 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:23:55 +0100 Subject: [PATCH 06/36] Tweak comment for latest nightly version check Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/per-language-bundles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index 35cfa3e0f..6f8009683 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -102,7 +102,7 @@ export async function getPerLanguageBundleLanguage( return explain("the job is not running on a GitHub-hosted runner"); } - // If the user requested the latest nightly, skip the version check, as nightlies have shipped + // When selecting the latest nightly, skip the version check, as nightlies have shipped // per-language bundles since https://github.com/dsp-testing/codeql-cli-nightlies/releases/tag/codeql-bundle-20260909. // Otherwise, check the requested CLI version to determine whether per-language bundles are published. if (!isLatestNightly) { From 48321b2d4823e75454e91867ded94e394d33343b Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:49:21 +0100 Subject: [PATCH 07/36] Update src/per-language-bundles.ts Co-authored-by: Michael B. Gale --- src/per-language-bundles.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index 6f8009683..acdff5c74 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -102,9 +102,11 @@ export async function getPerLanguageBundleLanguage( return explain("the job is not running on a GitHub-hosted runner"); } - // When selecting the latest nightly, skip the version check, as nightlies have shipped - // per-language bundles since https://github.com/dsp-testing/codeql-cli-nightlies/releases/tag/codeql-bundle-20260909. - // Otherwise, check the requested CLI version to determine whether per-language bundles are published. + // Nightly releases are identified by dates rather than versions. If + // `isLatestNightly` is `true`, the latest nightly is requested with + // `tools: nightly` and we don't yet have the corresponding tag at this point. + // Therefore, we skip the version check and don't have an equivalent. + // We can safely assume that the latest nightly will have per-language bundles. if (!isLatestNightly) { if (cliVersion === undefined) { return explain("the requested CLI version is unknown"); From 3bacfe2c5b69ecc6f63622003e4ef982bbd5da64 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 22 Sep 2026 16:56:15 +0100 Subject: [PATCH 08/36] Remove trailing whitespace from nightly comment Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/per-language-bundles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index acdff5c74..e4468d2f3 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -102,8 +102,8 @@ export async function getPerLanguageBundleLanguage( return explain("the job is not running on a GitHub-hosted runner"); } - // Nightly releases are identified by dates rather than versions. If - // `isLatestNightly` is `true`, the latest nightly is requested with + // Nightly releases are identified by dates rather than versions. If + // `isLatestNightly` is `true`, the latest nightly is requested with // `tools: nightly` and we don't yet have the corresponding tag at this point. // Therefore, we skip the version check and don't have an equivalent. // We can safely assume that the latest nightly will have per-language bundles. From 53162242d5865c69ec07e928d7348f3fa2841c15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:12:09 +0000 Subject: [PATCH 09/36] Update default bundle to codeql-bundle-v2.27.1 --- lib/defaults.json | 8 ++++---- lib/entry-points.js | 4 ++-- src/defaults.json | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/defaults.json b/lib/defaults.json index e4875a8a3..e201dfd79 100644 --- a/lib/defaults.json +++ b/lib/defaults.json @@ -1,6 +1,6 @@ { - "bundleVersion": "codeql-bundle-v2.27.0", - "cliVersion": "2.27.0", - "priorBundleVersion": "codeql-bundle-v2.26.4", - "priorCliVersion": "2.26.4" + "bundleVersion": "codeql-bundle-v2.27.1", + "cliVersion": "2.27.1", + "priorBundleVersion": "codeql-bundle-v2.27.0", + "priorCliVersion": "2.27.0" } diff --git a/lib/entry-points.js b/lib/entry-points.js index 3fbacc32e..2340dc38e 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -147732,8 +147732,8 @@ var path6 = __toESM(require("path")); var semver4 = __toESM(require_semver2()); // src/defaults.json -var bundleVersion = "codeql-bundle-v2.27.0"; -var cliVersion = "2.27.0"; +var bundleVersion = "codeql-bundle-v2.27.1"; +var cliVersion = "2.27.1"; // src/overlay/index.ts var fs5 = __toESM(require("fs")); diff --git a/src/defaults.json b/src/defaults.json index e4875a8a3..e201dfd79 100644 --- a/src/defaults.json +++ b/src/defaults.json @@ -1,6 +1,6 @@ { - "bundleVersion": "codeql-bundle-v2.27.0", - "cliVersion": "2.27.0", - "priorBundleVersion": "codeql-bundle-v2.26.4", - "priorCliVersion": "2.26.4" + "bundleVersion": "codeql-bundle-v2.27.1", + "cliVersion": "2.27.1", + "priorBundleVersion": "codeql-bundle-v2.27.0", + "priorCliVersion": "2.27.0" } From 81fb67799a74354c9fabb1dbc7ee198832c892db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:12:17 +0000 Subject: [PATCH 10/36] Add changelog note --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 267b4e557..a8880f37a 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. +- Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160) ## 4.38.1 - 18 Sept 2026 From f042742baf35d884f8d502e842ed0f927071edbf Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:38:53 +0100 Subject: [PATCH 11/36] Wrap JSON parse errors in `resolveExtractor` with context --- lib/entry-points.js | 9 ++++++++- src/codeql.ts | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 3fbacc32e..38ca1d699 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -153261,7 +153261,14 @@ async function getCodeQLForCmd(logger, cmd, checkVersion) { } } ).exec(); - return JSON.parse(extractorPath); + try { + return JSON.parse(extractorPath); + } catch (err) { + throw new Error( + `Failed to parse extractor path for '${language}' from CLI: ${getErrorMessage(err)} +Output was: ${extractorPath}` + ); + } }, async resolveQueriesStartingPacks(queries) { const codeqlArgs = [ diff --git a/src/codeql.ts b/src/codeql.ts index 65e73d945..2dfc65996 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -951,7 +951,13 @@ async function getCodeQLForCmd( }, }, ).exec(); - return JSON.parse(extractorPath) as string; + try { + return JSON.parse(extractorPath) as string; + } catch (err) { + throw new Error( + `Failed to parse extractor path for '${language}' from CLI: ${getErrorMessage(err)}\nOutput was: ${extractorPath}`, + ); + } }, async resolveQueriesStartingPacks(queries: string[]): Promise { const codeqlArgs = [ From a5c2338ec0c8df37f677f9e61b6ea99820253bcc Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:41:31 +0100 Subject: [PATCH 12/36] Wrap JSON parse errors in `restoreInputs` with context --- lib/entry-points.js | 13 +++++++++---- src/actions-util.ts | 15 +++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 38ca1d699..677848bf7 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146389,11 +146389,16 @@ var persistInputs = function(env = getEnv()) { core3.saveState(persistedInputsKey, JSON.stringify(inputEnvironmentVariables)); }; var restoreInputs = function() { - const persistedInputs = core3.getState(persistedInputsKey); - if (persistedInputs) { - for (const [name, value] of JSON.parse(persistedInputs)) { - process.env[name] = value; + try { + const persistedInputsValue = core3.getState(persistedInputsKey); + const persistedInputs = JSON.parse(persistedInputsValue); + if (persistedInputs) { + for (const [name, value] of persistedInputs) { + process.env[name] = value; + } } + } catch (err) { + throw new Error(`Unable to restore inputs: ${getErrorMessage(err)}`); } }; function getPullRequestBranches(env = getEnv()) { diff --git a/src/actions-util.ts b/src/actions-util.ts index 677bb04b1..df682d4eb 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -14,6 +14,7 @@ import { getCodeQLDatabasePath, ConfigurationError, getEnv, + getErrorMessage, } from "./util"; /** @@ -413,11 +414,17 @@ export const persistInputs = function (env: Env = getEnv()) { * Restores all inputs to the action from the persisted state. */ export const restoreInputs = function () { - const persistedInputs = core.getState(persistedInputsKey); - if (persistedInputs) { - for (const [name, value] of JSON.parse(persistedInputs)) { - process.env[name] = value; + try { + const persistedInputsValue = core.getState(persistedInputsKey); + const persistedInputs = JSON.parse(persistedInputsValue); + + if (persistedInputs) { + for (const [name, value] of persistedInputs) { + process.env[name] = value; + } } + } catch (err) { + throw new Error(`Unable to restore inputs: ${getErrorMessage(err)}`); } }; From c0369726eea406aff976ade45ef6382836cbbdaa Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:43:26 +0100 Subject: [PATCH 13/36] Wrap JSON parse errors in `getTracerConfigForCluster` with context --- lib/entry-points.js | 24 +++++++++++++----------- src/tracer-config.ts | 26 ++++++++++++++------------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 677848bf7..d1eda854f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -152821,18 +152821,20 @@ async function endTracingForCluster(codeql, config, logger) { } } async function getTracerConfigForCluster(config) { - const tracingEnvVariables = JSON.parse( - fs15.readFileSync( - path14.resolve( - config.dbLocation, - "temp/tracingEnvironment/start-tracing.json" - ), - "utf8" - ) + const filePath = path14.resolve( + config.dbLocation, + "temp/tracingEnvironment/start-tracing.json" ); - return { - env: tracingEnvVariables - }; + try { + const tracingEnvVariables = JSON.parse(fs15.readFileSync(filePath, "utf8")); + return { + env: tracingEnvVariables + }; + } catch (err) { + throw new Error( + `Failed to parse tracing environment from '${filePath}': ${getErrorMessage(err)}` + ); + } } async function getCombinedTracerConfig(codeql, config) { if (!await shouldEnableIndirectTracing(codeql, config)) { diff --git a/src/tracer-config.ts b/src/tracer-config.ts index d786d4651..fb3a0a05b 100644 --- a/src/tracer-config.ts +++ b/src/tracer-config.ts @@ -4,7 +4,7 @@ import * as path from "path"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; import { Logger } from "./logging"; -import { asyncSome, BuildMode } from "./util"; +import { asyncSome, BuildMode, getErrorMessage } from "./util"; export type TracerConfig = { env: { [key: string]: string }; @@ -79,18 +79,20 @@ export async function endTracingForCluster( async function getTracerConfigForCluster( config: Config, ): Promise { - const tracingEnvVariables = JSON.parse( - fs.readFileSync( - path.resolve( - config.dbLocation, - "temp/tracingEnvironment/start-tracing.json", - ), - "utf8", - ), + const filePath = path.resolve( + config.dbLocation, + "temp/tracingEnvironment/start-tracing.json", ); - return { - env: tracingEnvVariables, - }; + try { + const tracingEnvVariables = JSON.parse(fs.readFileSync(filePath, "utf8")); + return { + env: tracingEnvVariables, + }; + } catch (err) { + throw new Error( + `Failed to parse tracing environment from '${filePath}': ${getErrorMessage(err)}`, + ); + } } export async function getCombinedTracerConfig( From 2294a7a8b133c56c46ad0e19037584d196c43c16 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:46:55 +0100 Subject: [PATCH 14/36] Wrap JSON parse errors in `parseMatrixInput` with context --- lib/entry-points.js | 8 +++++++- src/util.ts | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index d1eda854f..e37a54a38 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -145995,7 +145995,13 @@ function parseMatrixInput(matrixInput) { if (matrixInput === void 0 || matrixInput === "null") { return void 0; } - return JSON.parse(matrixInput); + try { + return JSON.parse(matrixInput); + } catch (err) { + throw new Error( + `Failed to parse matrix input '${matrixInput}': ${getErrorMessage(err)}` + ); + } } function wrapError(error3) { return error3 instanceof Error ? error3 : new Error(String(error3)); diff --git a/src/util.ts b/src/util.ts index 456cd7c3d..d473dcd4c 100644 --- a/src/util.ts +++ b/src/util.ts @@ -894,7 +894,13 @@ export function parseMatrixInput( if (matrixInput === undefined || matrixInput === "null") { return undefined; } - return JSON.parse(matrixInput) as { [key: string]: string }; + try { + return JSON.parse(matrixInput) as { [key: string]: string }; + } catch (err) { + throw new Error( + `Failed to parse matrix input '${matrixInput}': ${getErrorMessage(err)}`, + ); + } } export function wrapError(error: unknown): Error { From 8e36092a163a5263056b109fa4fc3dd0862c8ac8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:52:03 +0100 Subject: [PATCH 15/36] Wrap JSON parse errors in `cloneObject` with context --- lib/entry-points.js | 6 +++++- src/util.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index e37a54a38..4a0c530cc 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146069,7 +146069,11 @@ var BuildMode = /* @__PURE__ */ ((BuildMode3) => { return BuildMode3; })(BuildMode || {}); function cloneObject(obj) { - return JSON.parse(JSON.stringify(obj)); + try { + return JSON.parse(JSON.stringify(obj)); + } catch (err) { + throw new Error(`Cloning object failed: ${getErrorMessage(err)}`); + } } async function cleanUpPath(file, name, logger) { logger.debug(`Cleaning up ${name}.`); diff --git a/src/util.ts b/src/util.ts index d473dcd4c..be67a111b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1043,7 +1043,11 @@ export enum BuildMode { } export function cloneObject(obj: T): T { - return JSON.parse(JSON.stringify(obj)) as T; + try { + return JSON.parse(JSON.stringify(obj)) as T; + } catch (err) { + throw new Error(`Cloning object failed: ${getErrorMessage(err)}`); + } } export async function cleanUpPath(file: string, name: string, logger: Logger) { From fe0a932a6a287152f436400a01d897aec8210ebe Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:53:03 +0100 Subject: [PATCH 16/36] Wrap JSON parse errors in `readSarifFile` with context --- lib/entry-points.js | 12 +++++++++--- src/sarif/index.ts | 9 ++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 4a0c530cc..123382751 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -155758,7 +155758,13 @@ function getToolNames(sarifFile) { return Object.keys(toolNames); } function readSarifFile(sarifFilePath) { - return JSON.parse(fs21.readFileSync(sarifFilePath, "utf8")); + try { + return JSON.parse(fs21.readFileSync(sarifFilePath, "utf8")); + } catch (err) { + throw new Error( + `Parsing SARIF file at '${sarifFilePath}' failed: ${getErrorMessage(err)}` + ); + } } function combineSarifFiles(sarifFiles, logger) { logger.info(`Loading SARIF file(s)`); @@ -158903,7 +158909,7 @@ var import_async = __toESM(require_async(), 1); var import_path7 = require("path"); // node_modules/archiver/lib/error.js -var import_util35 = __toESM(require("util"), 1); +var import_util36 = __toESM(require("util"), 1); var ERROR_CODES = { ABORTED: "archive was aborted", DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value", @@ -158928,7 +158934,7 @@ function ArchiverError(code, data) { this.code = code; this.data = data; } -import_util35.default.inherits(ArchiverError, Error); +import_util36.default.inherits(ArchiverError, Error); // node_modules/archiver/lib/core.js var import_readable_stream2 = __toESM(require_ours(), 1); diff --git a/src/sarif/index.ts b/src/sarif/index.ts index 3cd537daf..c288ec6a9 100644 --- a/src/sarif/index.ts +++ b/src/sarif/index.ts @@ -3,6 +3,7 @@ import * as fs from "fs"; import { Logger } from "../logging"; import * as sarif from "sarif"; +import { getErrorMessage } from "../util"; export type * from "sarif"; @@ -48,7 +49,13 @@ export function getToolNames(sarifFile: Partial): string[] { * @returns The resulting JSON value, cast to a SARIF `Log`. */ export function readSarifFile(sarifFilePath: string): Partial { - return JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as sarif.Log; + try { + return JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as sarif.Log; + } catch (err) { + throw new Error( + `Parsing SARIF file at '${sarifFilePath}' failed: ${getErrorMessage(err)}`, + ); + } } // Takes a list of paths to sarif files and combines them together, From 660f7c5f24a5addd7edc96c50399529d4800ef5d Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 18:58:17 +0100 Subject: [PATCH 17/36] Fix formatting --- src/sarif/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sarif/index.ts b/src/sarif/index.ts index c288ec6a9..ecb603a27 100644 --- a/src/sarif/index.ts +++ b/src/sarif/index.ts @@ -1,9 +1,9 @@ import * as fs from "fs"; import { Logger } from "../logging"; +import { getErrorMessage } from "../util"; import * as sarif from "sarif"; -import { getErrorMessage } from "../util"; export type * from "sarif"; From fa4712895bf510badfee5b98edde9378f80e6dde Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 22 Sep 2026 19:09:07 +0100 Subject: [PATCH 18/36] Restore previous `restoreInputs` behaviour --- lib/entry-points.js | 4 ++-- src/actions-util.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 123382751..ed83519d0 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146401,8 +146401,8 @@ var persistInputs = function(env = getEnv()) { var restoreInputs = function() { try { const persistedInputsValue = core3.getState(persistedInputsKey); - const persistedInputs = JSON.parse(persistedInputsValue); - if (persistedInputs) { + if (persistedInputsValue) { + const persistedInputs = JSON.parse(persistedInputsValue); for (const [name, value] of persistedInputs) { process.env[name] = value; } diff --git a/src/actions-util.ts b/src/actions-util.ts index df682d4eb..dd11f7aa0 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -416,9 +416,9 @@ export const persistInputs = function (env: Env = getEnv()) { export const restoreInputs = function () { try { const persistedInputsValue = core.getState(persistedInputsKey); - const persistedInputs = JSON.parse(persistedInputsValue); + if (persistedInputsValue) { + const persistedInputs = JSON.parse(persistedInputsValue); - if (persistedInputs) { for (const [name, value] of persistedInputs) { process.env[name] = value; } From 9691115b1ca24ee0f0939d6680facb305b90635f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 23 Sep 2026 11:09:52 +0100 Subject: [PATCH 19/36] Disable `UsePerfData` for `resolveExtractor` --- lib/entry-points.js | 1 + src/codeql.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/entry-points.js b/lib/entry-points.js index 2340dc38e..bb408af31 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -153247,6 +153247,7 @@ async function getCodeQLForCmd(logger, cmd, checkVersion) { "--format=json", `--language=${language}`, "--extractor-include-aliases", + "-J-XX:-UsePerfData", ...getExtraOptionsFromEnv(["resolve", "extractor"]) ], { diff --git a/src/codeql.ts b/src/codeql.ts index 65e73d945..fbc119a34 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -937,6 +937,7 @@ async function getCodeQLForCmd( "--format=json", `--language=${language}`, "--extractor-include-aliases", + "-J-XX:-UsePerfData", ...getExtraOptionsFromEnv(["resolve", "extractor"]), ], { From 9c9e4b034d1b1fe599ec257ad3287e537edaead8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 23 Sep 2026 13:29:25 +0100 Subject: [PATCH 20/36] Fix `getCommitOid` stubs --- src/git-utils.test.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/git-utils.test.ts b/src/git-utils.test.ts index b77d40a7e..f6a25778a 100644 --- a/src/git-utils.test.ts +++ b/src/git-utils.test.ts @@ -29,10 +29,12 @@ test.serial( process.env["GITHUB_SHA"] = currentSha; const callback = sinon.stub(gitUtils, "getCommitOid"); - callback.withArgs("HEAD").resolves(currentSha); + callback.withArgs(sinon.match.string, "HEAD").resolves(currentSha); const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, expectedRef); + + t.true(callback.calledOnceWith(tmpDir, "HEAD")); }); }, ); @@ -48,11 +50,15 @@ test.serial( const sha = "a".repeat(40); const callback = sinon.stub(gitUtils, "getCommitOid"); - callback.withArgs("refs/remotes/pull/1/merge").resolves(sha); - callback.withArgs("HEAD").resolves(sha); + callback + .withArgs(sinon.match.string, "refs/remotes/pull/1/merge") + .resolves(sha); + callback.withArgs(sinon.match.any, "HEAD").resolves(sha); const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, expectedRef); + + t.true(callback.calledWith(tmpDir, "refs/remotes/pull/1/merge")); }); }, ); @@ -71,6 +77,9 @@ test.serial( const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, "refs/pull/1/head"); + + t.true(callback.calledOnceWith(tmpDir, "refs/pull/1/merge")); + t.true(callback.calledOnceWith(tmpDir, "HEAD")); }); }, ); @@ -92,11 +101,14 @@ test.serial( process.env["GITHUB_SHA"] = "a".repeat(40); const callback = sinon.stub(gitUtils, "getCommitOid"); - callback.withArgs("refs/pull/1/merge").resolves("b".repeat(40)); - callback.withArgs("HEAD").resolves("b".repeat(40)); + callback.withArgs(tmpDir, "refs/pull/1/merge").resolves("b".repeat(40)); + callback.withArgs(sinon.match.any, "HEAD").resolves("b".repeat(40)); const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, "refs/pull/2/merge"); + + t.true(callback.calledOnceWith(tmpDir, "refs/pull/1/merge")); + t.true(callback.calledOnceWith(tmpDir, "HEAD")); }); }, ); From 42277414c74077324e1a1eb1f3cfd58f64fbabc5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 23 Sep 2026 13:38:53 +0100 Subject: [PATCH 21/36] Stub `getCommitOid` correctly and check calls --- src/git-utils.test.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/git-utils.test.ts b/src/git-utils.test.ts index f6a25778a..64b76590a 100644 --- a/src/git-utils.test.ts +++ b/src/git-utils.test.ts @@ -34,6 +34,7 @@ test.serial( const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, expectedRef); + t.is(callback.callCount, 1); t.true(callback.calledOnceWith(tmpDir, "HEAD")); }); }, @@ -58,6 +59,8 @@ test.serial( const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, expectedRef); + t.is(callback.callCount, 2); + t.true(callback.calledWith(tmpDir, "HEAD")); t.true(callback.calledWith(tmpDir, "refs/remotes/pull/1/merge")); }); }, @@ -72,14 +75,18 @@ test.serial( process.env["GITHUB_SHA"] = "a".repeat(40); const callback = sinon.stub(gitUtils, "getCommitOid"); - callback.withArgs(tmpDir, "refs/pull/1/merge").resolves("a".repeat(40)); + callback + .withArgs(tmpDir, "refs/remotes/pull/1/merge") + .resolves("a".repeat(40)); callback.withArgs(tmpDir, "HEAD").resolves("b".repeat(40)); + callback.throws(new Error("Unexpected getCommitOid call in test.")); const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, "refs/pull/1/head"); - t.true(callback.calledOnceWith(tmpDir, "refs/pull/1/merge")); - t.true(callback.calledOnceWith(tmpDir, "HEAD")); + t.is(callback.callCount, 2); + t.true(callback.calledWith(tmpDir, "refs/remotes/pull/1/merge")); + t.true(callback.calledWith(tmpDir, "HEAD")); }); }, ); @@ -107,8 +114,8 @@ test.serial( const actualRef = await gitUtils.getRef(); t.deepEqual(actualRef, "refs/pull/2/merge"); - t.true(callback.calledOnceWith(tmpDir, "refs/pull/1/merge")); - t.true(callback.calledOnceWith(tmpDir, "HEAD")); + // getCommitOid shouldn't be called, because the ref should be taken from the input + t.is(callback.callCount, 0); }); }, ); From becb485c9fe880e7048de096129c6cd1a0dfb379 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:54:02 +0000 Subject: [PATCH 22/36] Bump the npm-minor group across 1 directory with 3 updates Bumps the npm-minor group with 3 updates in the / directory: [js-yaml](https://github.com/nodeca/js-yaml), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) and [yaml](https://github.com/eemeli/yaml). Updates `js-yaml` from 5.4.1 to 5.4.2 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/5.4.1...5.4.2) Updates `eslint-plugin-jsdoc` from 64.3.8 to 64.5.2 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v64.3.8...v64.5.2) Updates `yaml` from 2.9.0 to 2.9.1 - [Release notes](https://github.com/eemeli/yaml/releases) - [Commits](https://github.com/eemeli/yaml/compare/v2.9.0...v2.9.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 5.4.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor - dependency-name: eslint-plugin-jsdoc dependency-version: 64.5.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor - dependency-name: yaml dependency-version: 2.9.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 32 +++++++++++++++++++------------- package.json | 4 ++-- pr-checks/package.json | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index d4f189db2..955fcf6d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "follow-redirects": "^1.16.0", "get-folder-size": "^5.0.0", "https-proxy-agent": "^7.0.6", - "js-yaml": "^5.4.1", + "js-yaml": "^5.4.2", "jsonschema": "1.5.0", "long": "^5.3.2", "node-forge": "^1.4.0", @@ -58,7 +58,7 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^64.3.8", + "eslint-plugin-jsdoc": "^64.5.2", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.12.0", @@ -5348,9 +5348,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "64.3.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-64.3.8.tgz", - "integrity": "sha512-JXLYE2BVfmbqLrrslb9/vg3URg8okW5pMnppM+3EYwvPCbuOiSXGOJWaNK208wDx6xXawkIFGtRYgFgrW23dsg==", + "version": "64.5.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-64.5.2.tgz", + "integrity": "sha512-GirLf/jpVQ/HSLVT98ztIrJ8GUlWWrrwExkofqzeIjjOxlqFtyqnpkRs30FLwEKh0xHEpgy35CU0qFn0I/Mh9w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5374,7 +5374,13 @@ "node": "^22.22.2 || >=24.15.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/eslint-plugin-jsdoc/node_modules/debug": { @@ -7091,9 +7097,9 @@ } }, "node_modules/js-yaml": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.1.tgz", - "integrity": "sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.2.tgz", + "integrity": "sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==", "funding": [ { "type": "github", @@ -10367,9 +10373,9 @@ } }, "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10460,7 +10466,7 @@ "lite-matter": "^0.1.2", "mdast-util-from-markdown": "^2.0.3", "semver": "^7.8.5", - "yaml": "^2.9.0" + "yaml": "^2.9.1" }, "devDependencies": { "@types/node": "^20.19.43", diff --git a/package.json b/package.json index 7f31e80e9..315603825 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "follow-redirects": "^1.16.0", "get-folder-size": "^5.0.0", "https-proxy-agent": "^7.0.6", - "js-yaml": "^5.4.1", + "js-yaml": "^5.4.2", "jsonschema": "1.5.0", "long": "^5.3.2", "node-forge": "^1.4.0", @@ -66,7 +66,7 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^64.3.8", + "eslint-plugin-jsdoc": "^64.5.2", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.12.0", diff --git a/pr-checks/package.json b/pr-checks/package.json index 0c5091a79..58722bd0e 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -10,7 +10,7 @@ "lite-matter": "^0.1.2", "mdast-util-from-markdown": "^2.0.3", "semver": "^7.8.5", - "yaml": "^2.9.0" + "yaml": "^2.9.1" }, "devDependencies": { "@types/node": "^20.19.43", From c87fe5756c0c0bcd5e0005d2169945cfee9a232f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:55:50 +0000 Subject: [PATCH 23/36] Rebuild --- lib/entry-points.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index bb408af31..e89c2ab07 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -144779,6 +144779,7 @@ function doubleQuoteWhitespaceOnly(layout) { function applyForceQuotesOption(layout) { if (!layout.presenterOptions.forceQuotes) return; if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); } function tryLongOrMultilineAsBlock(layout) { @@ -164485,7 +164486,7 @@ tmp/lib/tmp.js: *) js-yaml/dist/js-yaml.mjs: - (*! js-yaml 5.4.1 https://github.com/nodeca/js-yaml @license MIT *) + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) long/index.js: (** From b13f5f47d5398d0fb982942ced6fdfc4e3951804 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:56:05 +0000 Subject: [PATCH 24/36] 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.321.0 to 1.323.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/95ef2b042f9d7a56d8268cba8559e2842e2ad01b...984c0c890880bbf811283d6f09c4607c62d210a4) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-version: 1.323.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 c405b44fe..96f2dacca 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@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 + uses: ruby/setup-ruby@984c0c890880bbf811283d6f09c4607c62d210a4 # v1.323.0 with: ruby-version: 2.6 - name: Install Code Scanning integration From 5e4e2550b48d7f3de205c9d752eb5176bf07f6d9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:57:57 +0000 Subject: [PATCH 25/36] 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 37c5d36e9..550bdb6cc 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@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 + uses: ruby/setup-ruby@984c0c890880bbf811283d6f09c4607c62d210a4 # v1.323.0 with: ruby-version: 2.6 - name: Install Code Scanning integration From f42df5b5c1f951934a54e79fb18d88601e9b9f62 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Wed, 23 Sep 2026 19:15:14 +0100 Subject: [PATCH 26/36] Move bundle types and helpers out of setup-codeql.ts Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 51 ++++++++++++++++--------------- src/codeql-bundle.ts | 38 +++++++++++++++++++++++ src/per-language-bundles.ts | 13 ++++++++ src/setup-codeql.ts | 60 +++++++++---------------------------- 4 files changed, 90 insertions(+), 72 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index e89c2ab07..ca89d1581 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -151206,6 +151206,20 @@ var import_fast_deep_equal = __toESM(require_fast_deep_equal()); var semver10 = __toESM(require_semver2()); // src/codeql-bundle.ts +function getCodeQLBundleName(compressionMethod, platform2, language) { + const extensions = { + gzip: ".tar.gz", + zstd: ".tar.zst" + }; + const extension = extensions[compressionMethod]; + if (platform2 === void 0) { + return `codeql-bundle${extension}`; + } + if (language !== void 0) { + return `codeql-bundle-${language}-${platform2}${extension}`; + } + return `codeql-bundle-${platform2}${extension}`; +} var PER_LANGUAGE_BUNDLE_NAME = /^codeql-bundle-(.+)-(?:linux64|osx64|win64)\.tar\.(?:gz|zst)$/; function getCodeQLBundleFromUrl(url2) { let assetName; @@ -151607,6 +151621,11 @@ async function getPerLanguageBundleLanguage({ } return language; } +function logPerLanguageBundleFallback({ logger }, language, location) { + logger.warning( + `No per-language CodeQL bundle for '${language}' was found at ${location}, so falling back to the bundle that contains all languages. This analysis will still produce correct results, but will take longer to set up.` + ); +} // src/tar.ts var import_child_process = require("child_process"); @@ -152005,26 +152024,8 @@ var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension(compressionMethod) { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - assertNever(compressionMethod); - } -} -function getCodeQLBundleName(compressionMethod, language) { - const extension = getCodeQLBundleExtension(compressionMethod); - const platform2 = getBundlePlatform(); - if (platform2 === void 0) { - return `codeql-bundle${extension}`; - } - if (language !== void 0) { - return `codeql-bundle-${language}-${platform2}${extension}`; - } - return `codeql-bundle-${platform2}${extension}`; +function getCodeQLBundleName2(compressionMethod, language) { + return getCodeQLBundleName(compressionMethod, getBundlePlatform(), language); } function getCodeQLActionRepository(logger) { if (isRunningLocalAction()) { @@ -152447,7 +152448,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO const resolveBundleURL = (language) => getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName(compressionMethod, language), + getCodeQLBundleName2(compressionMethod, language), logger ); const combinedBundleURL = await resolveBundleURL(); @@ -152680,9 +152681,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp if (bundle.kind !== "per-language" || bundle.combinedBundleURL === void 0 || asHTTPError(e)?.status !== 404) { throw e; } - logger.warning( - `No per-language CodeQL bundle for '${bundle.language}' was found at ${bundle.url}, so falling back to the bundle that contains all languages. This analysis will still produce correct results, but will take longer to set up.` - ); + logPerLanguageBundleFallback(action, bundle.language, bundle.url); const result = await downloadCodeQL( { ...source, @@ -152740,12 +152739,12 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { throw new Error("Could not find the latest nightly release."); } const assetUrl = (name) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url2 = assetUrl(getCodeQLBundleName(compressionMethod, language)); + const url2 = assetUrl(getCodeQLBundleName2(compressionMethod, language)); return language === void 0 ? { kind: "combined", url: url2 } : { kind: "per-language", url: url2, language, - combinedBundleURL: assetUrl(getCodeQLBundleName(compressionMethod)) + combinedBundleURL: assetUrl(getCodeQLBundleName2(compressionMethod)) }; } catch (e) { throw new Error( diff --git a/src/codeql-bundle.ts b/src/codeql-bundle.ts index 4e9f5d5de..2d262c848 100644 --- a/src/codeql-bundle.ts +++ b/src/codeql-bundle.ts @@ -1,4 +1,6 @@ import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; +import { BundlePlatform } from "./platform"; +import type { CompressionMethod } from "./tar"; /** Describes the contents and location of a downloadable CodeQL bundle. */ export type CodeQLBundle = @@ -11,6 +13,42 @@ export type CodeQLBundle = combinedBundleURL?: string; }; +/** A resolved download, including its bundle identity and version. */ +export interface CodeQLDownloadSource { + /** Distinguishes downloads from local archives and cached installations. */ + sourceType: "download"; + /** The bundle to download. */ + bundle: CodeQLBundle; + /** The compression format of the bundle archive. */ + compressionMethod: CompressionMethod; + /** Bundle version of the tools, if known. */ + bundleVersion?: string; + /** Requested CLI version, if known. */ + cliVersion?: string; + /** Resolved version for telemetry, independent of whether the bundle can be cached. */ + toolsVersion: string; +} + +/** Returns the exact bundle asset name for a platform and optional language. */ +export function getCodeQLBundleName( + compressionMethod: CompressionMethod, + platform: BundlePlatform | undefined, + language?: BuiltInLanguage, +): string { + const extensions: Record = { + gzip: ".tar.gz", + zstd: ".tar.zst", + }; + const extension = extensions[compressionMethod]; + if (platform === undefined) { + return `codeql-bundle${extension}`; + } + if (language !== undefined) { + return `codeql-bundle-${language}-${platform}${extension}`; + } + return `codeql-bundle-${platform}${extension}`; +} + const PER_LANGUAGE_BUNDLE_NAME = /^codeql-bundle-(.+)-(?:linux64|osx64|win64)\.tar\.(?:gz|zst)$/; diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index e4468d2f3..e0db649c7 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -131,3 +131,16 @@ export async function getPerLanguageBundleLanguage( return language; } + +/** Explains why an eligible per-language bundle is being replaced by a combined bundle. */ +export function logPerLanguageBundleFallback( + { logger }: ActionState<["Logger"]>, + language: BuiltInLanguage, + location: string, +): void { + logger.warning( + `No per-language CodeQL bundle for '${language}' was found at ${location}, so ` + + "falling back to the bundle that contains all languages. This analysis will still " + + "produce correct results, but will take longer to set up.", + ); +} diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 648435d80..58f37d638 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -17,7 +17,12 @@ import { isRunningLocalAction, } from "./actions-util"; import * as api from "./api-client"; -import { CodeQLBundle, getCodeQLBundleFromUrl } from "./codeql-bundle"; +import { + CodeQLBundle, + CodeQLDownloadSource, + getCodeQLBundleFromUrl, + getCodeQLBundleName as getBundleName, +} from "./codeql-bundle"; import * as defaults from "./defaults.json"; import { addNoLanguageDiagnostic, @@ -35,7 +40,10 @@ import { import { BuiltInLanguage } from "./languages"; import { Logger } from "./logging"; import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching"; -import { getPerLanguageBundleLanguage } from "./per-language-bundles"; +import { + getPerLanguageBundleLanguage, + logPerLanguageBundleFallback, +} from "./per-language-bundles"; import { getBundlePlatform } from "./platform"; import * as tar from "./tar"; import { @@ -49,6 +57,8 @@ import { import * as util from "./util"; import { isGoodVersion } from "./util"; +export type { CodeQLDownloadSource } from "./codeql-bundle"; + export enum ToolsSource { Unknown = "UNKNOWN", Local = "LOCAL", @@ -64,19 +74,6 @@ const CODEQL_BUNDLE_VERSION_ALIAS: string[] = ["linked", "latest"]; const CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; const CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension( - compressionMethod: tar.CompressionMethod, -): string { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - util.assertNever(compressionMethod); - } -} - /** * Returns the name of the CodeQL bundle asset to download. * @@ -87,16 +84,7 @@ export function getCodeQLBundleName( compressionMethod: tar.CompressionMethod, language?: BuiltInLanguage, ): string { - const extension = getCodeQLBundleExtension(compressionMethod); - const platform = getBundlePlatform(); - - if (platform === undefined) { - return `codeql-bundle${extension}`; - } - if (language !== undefined) { - return `codeql-bundle-${language}-${platform}${extension}`; - } - return `codeql-bundle-${platform}${extension}`; + return getBundleName(compressionMethod, getBundlePlatform(), language); } export function getCodeQLActionRepository(logger: Logger): string { @@ -223,22 +211,6 @@ export function convertToSemVer(version: string, logger: Logger): string { return s; } -/** A resolved download, including its bundle identity and version. */ -export interface CodeQLDownloadSource { - /** Distinguishes downloads from local archives and cached installations. */ - sourceType: "download"; - /** The bundle to download. */ - bundle: CodeQLBundle; - /** The compression format of the bundle archive. */ - compressionMethod: tar.CompressionMethod; - /** Bundle version of the tools, if known. */ - bundleVersion?: string; - /** Requested CLI version, if known. */ - cliVersion?: string; - /** Resolved version for telemetry, independent of whether the bundle can be cached. */ - toolsVersion: string; -} - export type CodeQLToolsSource = | { codeqlTarPath: string; @@ -1153,11 +1125,7 @@ export async function downloadCodeQLBundle( ) { throw e; } - logger.warning( - `No per-language CodeQL bundle for '${bundle.language}' was found at ${bundle.url}, so ` + - "falling back to the bundle that contains all languages. This analysis will still " + - "produce correct results, but will take longer to set up.", - ); + logPerLanguageBundleFallback(action, bundle.language, bundle.url); const result = await downloadCodeQL( { From 6aa6d5553a5bc4773e2cc41709554a6957e20924 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 24 Sep 2026 10:09:24 +0100 Subject: [PATCH 27/36] Remove the getCodeQLBundleName wrapper from setup-codeql.ts Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 19 +++++++++++-------- src/codeql-bundle.test.ts | 21 ++++++++++++++++++++- src/setup-codeql.test.ts | 28 ++-------------------------- src/setup-codeql.ts | 31 ++++++++++++------------------- 4 files changed, 45 insertions(+), 54 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ca89d1581..a6590f0bd 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -152024,9 +152024,6 @@ var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleName2(compressionMethod, language) { - return getCodeQLBundleName(compressionMethod, getBundlePlatform(), language); -} function getCodeQLActionRepository(logger) { if (isRunningLocalAction()) { logger.info( @@ -152435,20 +152432,21 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO ); } compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; + const platform2 = getBundlePlatform(); const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( { env: getEnv(), features, logger }, { rawLanguages, cliVersion: cliVersion2, compressionMethod, - platform: getBundlePlatform(), + platform: platform2, variant } ); const resolveBundleURL = (language) => getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName2(compressionMethod, language), + getCodeQLBundleName(compressionMethod, platform2, language), logger ); const combinedBundleURL = await resolveBundleURL(); @@ -152718,11 +152716,12 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { CODEQL_VERSION_ZSTD_BUNDLE, zstdAvailability.available ) ? "zstd" : "gzip"; + const platform2 = getBundlePlatform(); const language = await getPerLanguageBundleLanguage(action, { rawLanguages, cliVersion: void 0, compressionMethod, - platform: getBundlePlatform(), + platform: platform2, variant, isLatestNightly: true }); @@ -152739,12 +152738,16 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { throw new Error("Could not find the latest nightly release."); } const assetUrl = (name) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url2 = assetUrl(getCodeQLBundleName2(compressionMethod, language)); + const url2 = assetUrl( + getCodeQLBundleName(compressionMethod, platform2, language) + ); return language === void 0 ? { kind: "combined", url: url2 } : { kind: "per-language", url: url2, language, - combinedBundleURL: assetUrl(getCodeQLBundleName2(compressionMethod)) + combinedBundleURL: assetUrl( + getCodeQLBundleName(compressionMethod, platform2) + ) }; } catch (e) { throw new Error( diff --git a/src/codeql-bundle.test.ts b/src/codeql-bundle.test.ts index 1014043ea..e528ee76f 100644 --- a/src/codeql-bundle.test.ts +++ b/src/codeql-bundle.test.ts @@ -1,7 +1,26 @@ import test from "ava"; -import { getCodeQLBundleFromUrl } from "./codeql-bundle"; +import { getCodeQLBundleFromUrl, getCodeQLBundleName } from "./codeql-bundle"; import { BuiltInLanguage } from "./languages"; +import { BundlePlatform } from "./platform"; + +test("getCodeQLBundleName returns a per-language bundle name only when a language is specified", (t) => { + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Linux64, BuiltInLanguage.java), + "codeql-bundle-java-linux64.tar.zst", + ); + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Linux64), + "codeql-bundle-linux64.tar.zst", + ); +}); + +test("getCodeQLBundleName names the Swift bundle for macOS", (t) => { + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Osx64, BuiltInLanguage.swift), + "codeql-bundle-swift-osx64.tar.zst", + ); +}); for (const [assetName, language] of [ ["codeql-bundle-java-linux64.tar.zst", BuiltInLanguage.java], diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 6ac5bebf1..c33ac0700 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -435,7 +435,7 @@ test.serial( // Check that the `CodeQLToolsSource` object matches our expectations. const expectedVersion = `0.0.0-${expectedDate}`; - const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`; + const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`; t.deepEqual(source, { bundle: { kind: "combined", url: expectedURL }, bundleVersion: expectedDate, @@ -505,7 +505,7 @@ test.serial( // Check that the `CodeQLToolsSource` object matches our expectations. const expectedVersion = `0.0.0-${expectedDate}`; - const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`; + const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`; t.deepEqual(source, { bundle: { kind: "combined", url: expectedURL }, bundleVersion: expectedDate, @@ -1143,30 +1143,6 @@ const PER_LANGUAGE_CLI_VERSION = { ], }; -test.serial( - "getCodeQLBundleName returns a per-language bundle name only when a language is specified", - (t) => { - sinon.stub(process, "platform").value("linux"); - sinon.stub(process, "arch").value("x64"); - t.is( - setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.java), - "codeql-bundle-java-linux64.tar.zst", - ); - t.is( - setupCodeql.getCodeQLBundleName("zstd"), - "codeql-bundle-linux64.tar.zst", - ); - }, -); - -test.serial("getCodeQLBundleName names the Swift bundle for macOS", (t) => { - sinon.stub(process, "platform").value("darwin"); - t.is( - setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.swift), - "codeql-bundle-swift-osx64.tar.zst", - ); -}); - test.serial( "getCodeQLSource downloads the per-language bundle for a single explicit language", async (t) => { diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 58f37d638..d306d40d6 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -21,7 +21,7 @@ import { CodeQLBundle, CodeQLDownloadSource, getCodeQLBundleFromUrl, - getCodeQLBundleName as getBundleName, + getCodeQLBundleName, } from "./codeql-bundle"; import * as defaults from "./defaults.json"; import { @@ -74,19 +74,6 @@ const CODEQL_BUNDLE_VERSION_ALIAS: string[] = ["linked", "latest"]; const CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; const CODEQL_TOOLCACHE_INPUT = "toolcache"; -/** - * Returns the name of the CodeQL bundle asset to download. - * - * @param compressionMethod The compression method of the bundle. - * @param language Optional language for a per-language bundle. If omitted, returns a combined bundle name. - */ -export function getCodeQLBundleName( - compressionMethod: tar.CompressionMethod, - language?: BuiltInLanguage, -): string { - return getBundleName(compressionMethod, getBundlePlatform(), language); -} - export function getCodeQLActionRepository(logger: Logger): string { if (isRunningLocalAction()) { // This handles the case where the Action does not come from an Action repository, @@ -729,13 +716,14 @@ export async function getCodeQLSource( ? "zstd" : "gzip"; + const platform = getBundlePlatform(); const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( { env: getEnv(), features, logger }, { rawLanguages, cliVersion, compressionMethod, - platform: getBundlePlatform(), + platform, variant, }, ); @@ -745,7 +733,7 @@ export async function getCodeQLSource( getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName(compressionMethod, language), + getCodeQLBundleName(compressionMethod, platform, language), logger, ); @@ -1183,11 +1171,12 @@ async function getLatestNightlyBundle( ? "zstd" : "gzip"; + const platform = getBundlePlatform(); const language = await getPerLanguageBundleLanguage(action, { rawLanguages, cliVersion: undefined, compressionMethod, - platform: getBundlePlatform(), + platform, variant, isLatestNightly: true, }); @@ -1209,14 +1198,18 @@ async function getLatestNightlyBundle( } const assetUrl = (name: string) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url = assetUrl(getCodeQLBundleName(compressionMethod, language)); + const url = assetUrl( + getCodeQLBundleName(compressionMethod, platform, language), + ); return language === undefined ? { kind: "combined", url } : { kind: "per-language", url, language, - combinedBundleURL: assetUrl(getCodeQLBundleName(compressionMethod)), + combinedBundleURL: assetUrl( + getCodeQLBundleName(compressionMethod, platform), + ), }; } catch (e) { throw new Error( From 98af865db5041cee73c7185896319367f8c0adf2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 10:01:43 +0000 Subject: [PATCH 28/36] Update changelog for v4.38.2 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8880f37a..1561188e7 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.38.2 - 24 Sept 2026 - Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160) From 8ad03a333eb88de8ad6833eda208d0fc51a9c571 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 24 Sep 2026 11:15:21 +0100 Subject: [PATCH 29/36] Trigger workflows From 266e8661004d61bd252e1efa382c5adcb6f91f25 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 10:27:53 +0000 Subject: [PATCH 30/36] Update changelog and version after v4.38.2 --- 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 1561188e7..508ed0ce5 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.38.2 - 24 Sept 2026 - Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160) diff --git a/package-lock.json b/package-lock.json index 955fcf6d9..966f2074b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.38.2", + "version": "4.38.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.38.2", + "version": "4.38.3", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index 315603825..44c423493 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.38.2", + "version": "4.38.3", "private": true, "description": "CodeQL action", "scripts": { From 73dc34459c09a670eca2353df25f3181fc14db13 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 10:28:01 +0000 Subject: [PATCH 31/36] 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 e89c2ab07..0bbe01fe3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146168,7 +146168,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.38.2"; + return "4.38.3"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); From b5f938c947412bd5d6ad60b72c4f25b991740adf Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 24 Sep 2026 11:34:56 +0100 Subject: [PATCH 32/36] Log error in `restoreInputs` instead of re-throwing it --- lib/entry-points.js | 17 ++++++++++------- src/actions-util.ts | 9 ++++++--- src/analyze-action-post.ts | 2 +- src/init-action-post.ts | 2 +- src/start-proxy-action-post.ts | 2 +- src/upload-sarif-action-post.ts | 5 +++-- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ed83519d0..fb6a8b6e2 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146398,7 +146398,7 @@ var persistInputs = function(env = getEnv()) { ); core3.saveState(persistedInputsKey, JSON.stringify(inputEnvironmentVariables)); }; -var restoreInputs = function() { +function restoreInputs(logger) { try { const persistedInputsValue = core3.getState(persistedInputsKey); if (persistedInputsValue) { @@ -146408,9 +146408,12 @@ var restoreInputs = function() { } } } catch (err) { - throw new Error(`Unable to restore inputs: ${getErrorMessage(err)}`); + logger.error(`Unable to restore inputs: ${getErrorMessage(err)}`); + throw new Error( + "Failed to restore inputs from the state set by this action's main execution." + ); } -}; +} function getPullRequestBranches(env = getEnv()) { const pullRequest = github.context.payload.pull_request; if (pullRequest) { @@ -161729,8 +161732,8 @@ async function createDatabaseBundleCli(codeql, config, language) { // src/analyze-action-post.ts async function runWrapper2() { try { - restoreInputs(); const logger = getActionsLogger(); + restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); if (process.env["CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */] === "true") { @@ -163026,7 +163029,7 @@ async function run4(startedAt) { let dependencyCachingUsage; try { const jobStatus2 = getOptionalInput("job-status"); - restoreInputs(); + restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); const repositoryNwo = getRepositoryNwo(); @@ -164177,7 +164180,7 @@ var core29 = __toESM(require_core()); async function runWrapper9() { const logger = getActionsLogger(); try { - restoreInputs(); + restoreInputs(logger); const pid = core29.getState("proxy-process-pid"); if (pid) { process.kill(Number(pid)); @@ -164328,8 +164331,8 @@ async function runWrapper10() { var core31 = __toESM(require_core()); async function runWrapper11() { try { - restoreInputs(); const logger = getActionsLogger(); + restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); if (process.env["CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */] !== "true") { diff --git a/src/actions-util.ts b/src/actions-util.ts index dd11f7aa0..6c7d6a78d 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -413,7 +413,7 @@ export const persistInputs = function (env: Env = getEnv()) { /** * Restores all inputs to the action from the persisted state. */ -export const restoreInputs = function () { +export function restoreInputs(logger: Logger) { try { const persistedInputsValue = core.getState(persistedInputsKey); if (persistedInputsValue) { @@ -424,9 +424,12 @@ export const restoreInputs = function () { } } } catch (err) { - throw new Error(`Unable to restore inputs: ${getErrorMessage(err)}`); + logger.error(`Unable to restore inputs: ${getErrorMessage(err)}`); + throw new Error( + "Failed to restore inputs from the state set by this action's main execution.", + ); } -}; +} export interface PullRequestBranches { base: string; diff --git a/src/analyze-action-post.ts b/src/analyze-action-post.ts index 732b52af1..3f9b2fafb 100644 --- a/src/analyze-action-post.ts +++ b/src/analyze-action-post.ts @@ -25,8 +25,8 @@ export async function runWrapper() { // possible, and only use safe functions outside. try { - actionsUtil.restoreInputs(); const logger = getActionsLogger(); + actionsUtil.restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); diff --git a/src/init-action-post.ts b/src/init-action-post.ts index 749020ac6..e3a68b0e5 100644 --- a/src/init-action-post.ts +++ b/src/init-action-post.ts @@ -62,7 +62,7 @@ async function run(startedAt: Date) { const jobStatus = getOptionalInput("job-status"); // Restore inputs from `init` Action. - restoreInputs(); + restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); diff --git a/src/start-proxy-action-post.ts b/src/start-proxy-action-post.ts index 6b59052c6..d300d528b 100644 --- a/src/start-proxy-action-post.ts +++ b/src/start-proxy-action-post.ts @@ -20,7 +20,7 @@ export async function runWrapper() { try { // Restore inputs from `start-proxy` Action. - actionsUtil.restoreInputs(); + actionsUtil.restoreInputs(logger); // Kill the running proxy const pid = core.getState("proxy-process-pid"); diff --git a/src/upload-sarif-action-post.ts b/src/upload-sarif-action-post.ts index a27fe1667..bc0e1361c 100644 --- a/src/upload-sarif-action-post.ts +++ b/src/upload-sarif-action-post.ts @@ -17,9 +17,10 @@ export async function runWrapper() { // possible, and only use safe functions outside. try { - // Restore inputs from `upload-sarif` Action. - actionsUtil.restoreInputs(); const logger = getActionsLogger(); + + // Restore inputs from `upload-sarif` Action. + actionsUtil.restoreInputs(logger); const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); From 19aa55de51e0d269aac6e00e337be7c5eaa1b575 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 24 Sep 2026 12:06:01 +0100 Subject: [PATCH 33/36] Log error in `getTracerConfigForCluster` instead of re-throwing it --- lib/entry-points.js | 11 ++++++----- src/init-action.ts | 2 +- src/tracer-config.test.ts | 17 ++++++++++++++--- src/tracer-config.ts | 7 +++++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 727360efc..05a4c45fa 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -152834,7 +152834,7 @@ async function endTracingForCluster(codeql, config, logger) { ); } } -async function getTracerConfigForCluster(config) { +async function getTracerConfigForCluster(logger, config) { const filePath = path14.resolve( config.dbLocation, "temp/tracingEnvironment/start-tracing.json" @@ -152845,16 +152845,17 @@ async function getTracerConfigForCluster(config) { env: tracingEnvVariables }; } catch (err) { - throw new Error( + logger.error( `Failed to parse tracing environment from '${filePath}': ${getErrorMessage(err)}` ); + throw new Error(`Failed to parse tracing environment from '${filePath}'.`); } } -async function getCombinedTracerConfig(codeql, config) { +async function getCombinedTracerConfig(logger, codeql, config) { if (!await shouldEnableIndirectTracing(codeql, config)) { return void 0; } - return await getTracerConfigForCluster(config); + return await getTracerConfigForCluster(logger, config); } // src/codeql.ts @@ -162630,7 +162631,7 @@ exec ${goBinaryPath} "$@"` qlconfigFile ); } - const tracerConfig = await getCombinedTracerConfig(codeql, config); + const tracerConfig = await getCombinedTracerConfig(logger, codeql, config); if (tracerConfig !== void 0) { for (const [key, value] of Object.entries(tracerConfig.env)) { core22.exportVariable(key, value); diff --git a/src/init-action.ts b/src/init-action.ts index e770fe978..41e0b8629 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -716,7 +716,7 @@ async function run( ); } - const tracerConfig = await getCombinedTracerConfig(codeql, config); + const tracerConfig = await getCombinedTracerConfig(logger, codeql, config); if (tracerConfig !== undefined) { for (const [key, value] of Object.entries(tracerConfig.env)) { core.exportVariable(key, value); diff --git a/src/tracer-config.test.ts b/src/tracer-config.test.ts index 58f844b8e..a3c42d668 100644 --- a/src/tracer-config.test.ts +++ b/src/tracer-config.test.ts @@ -7,7 +7,12 @@ import * as sinon from "sinon"; import { CodeQL, getCodeQLForTesting } from "./codeql"; import * as configUtils from "./config-utils"; import { BuiltInLanguage } from "./languages"; -import { createTestConfig, makeVersionInfo, setupTests } from "./testing-utils"; +import { + createTestConfig, + makeVersionInfo, + RecordingLogger, + setupTests, +} from "./testing-utils"; import { ToolsFeature } from "./tools-features"; import { getCombinedTracerConfig } from "./tracer-config"; import * as util from "./util"; @@ -42,18 +47,20 @@ async function stubCodeql( } test("getCombinedTracerConfig - return undefined when no languages are traced languages", async (t) => { + const logger = new RecordingLogger(); await util.withTmpDir(async (tmpDir) => { const config = getTestConfig(tmpDir); // No traced languages config.languages = [BuiltInLanguage.javascript, BuiltInLanguage.python]; t.deepEqual( - await getCombinedTracerConfig(await stubCodeql(), config), + await getCombinedTracerConfig(logger, await stubCodeql(), config), undefined, ); }); }); test("getCombinedTracerConfig", async (t) => { + const logger = new RecordingLogger(); await util.withTmpDir(async (tmpDir) => { const config = getTestConfig(tmpDir); @@ -82,7 +89,11 @@ test("getCombinedTracerConfig", async (t) => { ); fs.writeFileSync(startTracingJson, JSON.stringify(startTracingEnv)); - const result = await getCombinedTracerConfig(await stubCodeql(), config); + const result = await getCombinedTracerConfig( + logger, + await stubCodeql(), + config, + ); t.notDeepEqual(result, undefined); t.false(Object.prototype.hasOwnProperty.call(result?.env, "CODEQL_RUNNER")); diff --git a/src/tracer-config.ts b/src/tracer-config.ts index fb3a0a05b..33c5b64fc 100644 --- a/src/tracer-config.ts +++ b/src/tracer-config.ts @@ -77,6 +77,7 @@ export async function endTracingForCluster( } async function getTracerConfigForCluster( + logger: Logger, config: Config, ): Promise { const filePath = path.resolve( @@ -89,13 +90,15 @@ async function getTracerConfigForCluster( env: tracingEnvVariables, }; } catch (err) { - throw new Error( + logger.error( `Failed to parse tracing environment from '${filePath}': ${getErrorMessage(err)}`, ); + throw new Error(`Failed to parse tracing environment from '${filePath}'.`); } } export async function getCombinedTracerConfig( + logger: Logger, codeql: CodeQL, config: Config, ): Promise { @@ -103,5 +106,5 @@ export async function getCombinedTracerConfig( return undefined; } - return await getTracerConfigForCluster(config); + return await getTracerConfigForCluster(logger, config); } From 054b25e1c24721c62e6ff4eaabe96851087a5511 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 25 Sep 2026 14:58:43 +0100 Subject: [PATCH 34/36] Remove unnecessary `config` check --- lib/entry-points.js | 6 ------ src/start-proxy-action-post.ts | 6 ------ 2 files changed, 12 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index cbeec2478..0b9e64fa3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -164199,12 +164199,6 @@ async function runWrapper9() { logger.info( "Debug mode is on. Uploading proxy log as Actions debugging artifact..." ); - if (config?.gitHubVersion.type === void 0) { - logger.warning( - `Did not upload debug artifacts because cannot determine the GitHub variant running.` - ); - return; - } const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); await uploadArtifacts( diff --git a/src/start-proxy-action-post.ts b/src/start-proxy-action-post.ts index d300d528b..c872207ac 100644 --- a/src/start-proxy-action-post.ts +++ b/src/start-proxy-action-post.ts @@ -38,12 +38,6 @@ export async function runWrapper() { logger.info( "Debug mode is on. Uploading proxy log as Actions debugging artifact...", ); - if (config?.gitHubVersion.type === undefined) { - logger.warning( - `Did not upload debug artifacts because cannot determine the GitHub variant running.`, - ); - return; - } const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); From 9fb2fa5f460cbdf6af333c849ec85eb0c87458b9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 25 Sep 2026 15:02:13 +0100 Subject: [PATCH 35/36] Avoid duplicate `getApiDetails` in `getGitHubVersion` --- lib/entry-points.js | 5 +++-- src/api-client.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 0b9e64fa3..a165a9b3b 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -146768,9 +146768,10 @@ async function getGitHubVersionFromApi(apiClient, apiDetails) { } async function getGitHubVersion() { if (cachedGitHubVersion === void 0) { + const apiDetails = getApiDetails(); cachedGitHubVersion = await getGitHubVersionFromApi( - getApiClient(), - getApiDetails() + createApiClientWithDetails(apiDetails), + apiDetails ); } return cachedGitHubVersion; diff --git a/src/api-client.ts b/src/api-client.ts index bc6018877..e509f5eea 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -249,9 +249,10 @@ export async function getGitHubVersionFromApi( */ export async function getGitHubVersion(): Promise { if (cachedGitHubVersion === undefined) { + const apiDetails = getApiDetails(); cachedGitHubVersion = await getGitHubVersionFromApi( - getApiClient(), - getApiDetails(), + createApiClientWithDetails(apiDetails), + apiDetails, ); } return cachedGitHubVersion; From 29b01b679967735ac1689d248d9ae6e665390434 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 25 Sep 2026 15:59:36 +0100 Subject: [PATCH 36/36] Point at Dependabot `groups` docs in version mismatch error --- lib/entry-points.js | 7 ++++++- src/config-utils.ts | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index a165a9b3b..186a09106 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -151074,7 +151074,12 @@ async function getConfig(tempDir, logger) { } if (config.version !== getActionVersion()) { throw new ConfigurationError( - `Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'` + [ + `Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'.`, + "All steps in a workflow that use `github/codeql-action` must use the same version to work correctly.", + "If you are using Dependabot to manage dependency updates, you can configure a dependency group to update all `github/codeql-action` steps at the same time.", + "For more information, see https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference#groups--" + ].join(" ") ); } return config; diff --git a/src/config-utils.ts b/src/config-utils.ts index 288b4f02f..4dd14b290 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -1425,7 +1425,12 @@ export async function getConfig( } if (config.version !== getActionVersion()) { throw new ConfigurationError( - `Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'`, + [ + `Loaded a configuration file for version '${config.version}', but running version '${getActionVersion()}'.`, + "All steps in a workflow that use `github/codeql-action` must use the same version to work correctly.", + "If you are using Dependabot to manage dependency updates, you can configure a dependency group to update all `github/codeql-action` steps at the same time.", + "For more information, see https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference#groups--", + ].join(" "), ); }