From 4a2ca5c068a2462212f2b7488705c0db44fc466f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 6 Oct 2026 13:36:35 +0100 Subject: [PATCH 01/27] Allow logging functions to accept `string[]` directly --- lib/entry-points.js | 20 ++++++++++++++++---- src/logging.test.ts | 17 +++++++++++++++++ src/logging.ts | 43 +++++++++++++++++++++++++++++++++++-------- src/testing-utils.ts | 14 +++++++------- 4 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 src/logging.test.ts diff --git a/lib/entry-points.js b/lib/entry-points.js index 4bda95685..8de2effc4 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170510,12 +170510,24 @@ function fixCodeQualityCategory(logger2, category, env = getEnv()) { // src/logging.ts var core5 = __toESM(require_core()); +var joinMessageStrings = (message) => { + if (Array.isArray(message)) { + return message.join(" "); + } else { + return message; + } +}; +var autoJoinMessageStrings = (fn) => { + return (message) => { + return fn(joinMessageStrings(message)); + }; +}; function getActionsLogger() { return { - debug: core5.debug, - info: core5.info, - warning: core5.warning, - error: core5.error, + debug: autoJoinMessageStrings(core5.debug), + info: autoJoinMessageStrings(core5.info), + warning: autoJoinMessageStrings(core5.warning), + error: autoJoinMessageStrings(core5.error), isDebug: core5.isDebug, startGroup: core5.startGroup, endGroup: core5.endGroup diff --git a/src/logging.test.ts b/src/logging.test.ts new file mode 100644 index 000000000..33f6f8c16 --- /dev/null +++ b/src/logging.test.ts @@ -0,0 +1,17 @@ +import test from "ava"; + +import { joinMessageStrings } from "./logging"; +import { setupTests } from "./testing-utils"; + +setupTests(test); + +test("joinMessageStrings", async (t) => { + // For strings and errors, it is the identity function. + t.deepEqual(joinMessageStrings("Hello"), "Hello"); + + const error = new Error("Some error"); + t.deepEqual(joinMessageStrings(error), error); + + // For arrays of strings, we get a join-ed string. + t.deepEqual(joinMessageStrings(["foo", "bar"]), "foo bar"); +}); diff --git a/src/logging.ts b/src/logging.ts index 2c34cb54d..177aca6c7 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -1,10 +1,16 @@ import * as core from "@actions/core"; +/** Types that all of our logging functions accept. */ +export type Loggable = string | string[]; + +/** Some logging functions also accept errors directly. */ +export type LoggableError = Loggable | Error; + export interface Logger { - debug: (message: string) => void; - info: (message: string) => void; - warning: (message: string | Error) => void; - error: (message: string | Error) => void; + debug: (message: Loggable) => void; + info: (message: Loggable) => void; + warning: (message: LoggableError) => void; + error: (message: LoggableError) => void; isDebug: () => boolean; @@ -12,12 +18,33 @@ export interface Logger { endGroup: () => void; } +/** If `message` is an array of strings, the array is `join`-ed into one string separated by spaces. */ +export const joinMessageStrings = ( + message: string[] | string | T, +): string | T => { + if (Array.isArray(message)) { + return message.join(" "); + } else { + return message; + } +}; + +/** + * Wraps a logging function so that `joinMessageStrings` is applied to the input before + * calling the wrapped logging function. + */ +const autoJoinMessageStrings = (fn: (msg: string | T) => void) => { + return (message: string[] | string | T) => { + return fn(joinMessageStrings(message)); + }; +}; + export function getActionsLogger(): Logger { return { - debug: core.debug, - info: core.info, - warning: core.warning, - error: core.error, + debug: autoJoinMessageStrings(core.debug), + info: autoJoinMessageStrings(core.info), + warning: autoJoinMessageStrings(core.warning), + error: autoJoinMessageStrings(core.error), isDebug: core.isDebug, startGroup: core.startGroup, endGroup: core.endGroup, diff --git a/src/testing-utils.ts b/src/testing-utils.ts index cd6031894..1318415a7 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,7 +30,7 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { Logger } from "./logging"; +import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -618,8 +618,8 @@ export class RecordingLogger implements Logger { constructor(private readonly logToConsole: boolean = true) {} - private addMessage(level: LogLevel, message: string | Error): void { - this.messages.push({ type: level, message }); + private addMessage(level: LogLevel, message: LoggableError): void { + this.messages.push({ type: level, message: joinMessageStrings(message) }); if (this.logToConsole) { // eslint-disable-next-line no-console @@ -644,19 +644,19 @@ export class RecordingLogger implements Logger { return true; } - debug(message: string) { + debug(message: Loggable) { this.addMessage("debug", message); } - info(message: string) { + info(message: Loggable) { this.addMessage("info", message); } - warning(message: string | Error) { + warning(message: LoggableError) { this.addMessage("warning", message); } - error(message: string | Error) { + error(message: LoggableError) { this.addMessage("error", message); } From 924990a9c72b2fe575695534ab9db24dc3bbbc2a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 14:38:12 +0100 Subject: [PATCH 02/27] Move `getCodeQLForTesting` to `testing-utils.ts` --- src/codeql.test.ts | 7 ++++--- src/codeql.ts | 16 ++-------------- src/init-action-post-helper.test.ts | 5 +++-- src/testing-utils.ts | 20 +++++++++++++++++++- src/tracer-config.test.ts | 3 ++- src/workflow.test.ts | 3 ++- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/codeql.test.ts b/src/codeql.test.ts index 3237d5772..643f6d983 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -34,6 +34,7 @@ import { makeVersionInfo, createTestConfig, makeMacro, + getCodeQLForTesting, } from "./testing-utils"; import { ToolsDownloadStatusReport } from "./tools-download"; import * as util from "./util"; @@ -140,7 +141,7 @@ function mockApiDetails(apiDetails: GitHubApiDetails) { } async function stubCodeql(): Promise { - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon .stub(codeqlObject, "isTracedLanguage") @@ -1039,7 +1040,7 @@ test.serial("runTool summarizes autobuilder errors", async (t) => { [2019-09-18 12:00:01] [autobuild] A non-error message `; stubToolRunnerConstructor(1, stderr); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor"); // io throws because of the test CodeQL object. @@ -1095,7 +1096,7 @@ test.serial("runTool recognizes fatal internal errors", async (t) => { com.semmle.util.exception.CatastrophicError: An error occurred while evaluating ControlFlowGraph::ControlFlow::Root.isRootOf/1#dispred#f610e6ed/2@86282cc8 Severe disk cache trouble (corruption or out of space) at /home/runner/work/_temp/codeql_databases/go/db-go/default/cache/pages/28/33.pack: Failed to write item to disk`; stubToolRunnerConstructor(1, stderr); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); sinon.stub(codeqlObject, "resolveExtractor").resolves("/path/to/extractor"); // io throws because of the test CodeQL object. diff --git a/src/codeql.ts b/src/codeql.ts index 68273d27b..fde35b171 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -26,7 +26,7 @@ import { } from "./feature-flags"; import { isAnalyzingDefaultBranch } from "./git-utils"; import { Language } from "./languages"; -import { getRunnerLogger, Logger } from "./logging"; +import type { Logger } from "./logging"; import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "./overlay"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import * as setupCodeql from "./setup-codeql"; @@ -486,18 +486,6 @@ export function createStubCodeQL(partialCodeql: Partial): CodeQL { }; } -/** - * Get a real, newly created CodeQL instance for testing. The instance refers to - * a non-existent placeholder codeql command, so tests that use this function - * should also stub the toolrunner.ToolRunner constructor. - */ -export async function getCodeQLForTesting( - cmd = "codeql-for-testing", - logger: Logger = getRunnerLogger(true), -): Promise { - return getCodeQLForCmd(logger, cmd, false); -} - /** * Return a CodeQL object for CodeQL CLI access. * @@ -506,7 +494,7 @@ export async function getCodeQLForTesting( * version requirement. Must be set to true outside tests. * @returns A new CodeQL object */ -async function getCodeQLForCmd( +export async function getCodeQLForCmd( logger: Logger, cmd: string, checkVersion: boolean, diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index fd1f489f7..26b6ff4ab 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -20,6 +20,7 @@ import { createFeatures, createTestConfig, DEFAULT_ACTIONS_VARS, + getCodeQLForTesting, getTestEnv, makeMacro, makeVersionInfo, @@ -737,7 +738,7 @@ async function testFailedSarifUpload( .withArgs("matrix") .returns(JSON.stringify(matrix)); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); sinon.stub(codeql, "getCodeQL").resolves(codeqlObject); sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6")); const databaseExportDiagnosticsStub = sinon.stub( @@ -832,7 +833,7 @@ async function mockRiskAssessmentEnv(matrix: string) { .stub(apiClient, "getGitHubVersion") .resolves({ type: util.GitHubVariant.GHES, version: "3.0.0" }); - const codeqlObject = await codeql.getCodeQLForTesting(); + const codeqlObject = await getCodeQLForTesting(); const databaseExportDiagnostics = sinon .stub(codeqlObject, "databaseExportDiagnostics") .resolves(); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 1318415a7..dfb08d997 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,7 +30,13 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; +import { + getRunnerLogger, + joinMessageStrings, + Loggable, + LoggableError, + Logger, +} from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -1000,3 +1006,15 @@ export function makeTestToken(length: number = 36) { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return chars.repeat(Math.ceil(length / chars.length)).slice(0, length); } + +/** + * Get a real, newly created CodeQL instance for testing. The instance refers to + * a non-existent placeholder codeql command, so tests that use this function + * should also stub the toolrunner.ToolRunner constructor. + */ +export async function getCodeQLForTesting( + cmd = "codeql-for-testing", + logger: Logger = getRunnerLogger(true), +): Promise { + return codeql.getCodeQLForCmd(logger, cmd, false); +} diff --git a/src/tracer-config.test.ts b/src/tracer-config.test.ts index a3c42d668..f410d47c1 100644 --- a/src/tracer-config.test.ts +++ b/src/tracer-config.test.ts @@ -4,11 +4,12 @@ import * as path from "path"; import test from "ava"; import * as sinon from "sinon"; -import { CodeQL, getCodeQLForTesting } from "./codeql"; +import type { CodeQL } from "./codeql"; import * as configUtils from "./config-utils"; import { BuiltInLanguage } from "./languages"; import { createTestConfig, + getCodeQLForTesting, makeVersionInfo, RecordingLogger, setupTests, diff --git a/src/workflow.test.ts b/src/workflow.test.ts index c7f168a9d..576343078 100644 --- a/src/workflow.test.ts +++ b/src/workflow.test.ts @@ -3,10 +3,11 @@ import * as yaml from "js-yaml"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; -import { createStubCodeQL, getCodeQLForTesting } from "./codeql"; +import { createStubCodeQL } from "./codeql"; import { EnvVar } from "./environment"; import { checkExpectedLogMessages, + getCodeQLForTesting, getRecordingLogger, LoggedMessage, setupTests, From 23d418cf2e0b4e2cfd4b455402bc9db48487e135 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 14:50:54 +0100 Subject: [PATCH 03/27] Remove `getRunnerLogger` --- src/actions-util.test.ts | 3 +- src/analyses.test.ts | 11 ++-- src/analyze.test.ts | 4 +- src/artifact-scanner.test.ts | 4 +- src/cli/output-cache.test.ts | 5 +- src/codeql.test.ts | 24 ++++----- src/config-utils.test.ts | 32 ++++++------ src/config/db-config.test.ts | 7 ++- src/diff-informed-analysis-utils.test.ts | 14 +++--- src/feature-flags/properties.test.ts | 17 +++---- src/feature-flags/testing-util.ts | 5 +- src/fingerprints.test.ts | 9 ++-- src/init-action-post-helper.test.ts | 17 +++---- src/logging.ts | 16 ------ src/overlay/caching.test.ts | 20 ++++---- src/overlay/index.test.ts | 15 +++--- src/setup-codeql.test.ts | 64 ++++++++++++------------ src/start-proxy.test.ts | 40 +++++++-------- src/status-report.test.ts | 21 ++++---- src/tar.test.ts | 5 +- src/testing-utils.ts | 10 +--- src/tools-download.test.ts | 15 +++--- src/trap-caching.test.ts | 4 +- src/upload-lib.test.ts | 22 ++++---- src/upload-sarif.test.ts | 14 ++++-- src/util.test.ts | 17 +++---- 26 files changed, 195 insertions(+), 220 deletions(-) diff --git a/src/actions-util.test.ts b/src/actions-util.test.ts index 17cf96a4a..175fdea96 100644 --- a/src/actions-util.test.ts +++ b/src/actions-util.test.ts @@ -11,7 +11,6 @@ import { } from "./actions-util"; import { computeAutomationID } from "./api-client"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; import { RecordingLogger, setupTests } from "./testing-utils"; import { initializeEnvironment, withTmpDir } from "./util"; @@ -238,7 +237,7 @@ test.serial("fixCodeQualityCategory", (t) => { GITHUB_EVENT_NAME: "dynamic", }, () => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); // Categories that should get adjusted. t.is(fixCodeQualityCategory(logger, "/language:c#"), "/language:csharp"); diff --git a/src/analyses.test.ts b/src/analyses.test.ts index 9d0a9eb3e..b9d182618 100644 --- a/src/analyses.test.ts +++ b/src/analyses.test.ts @@ -15,7 +15,6 @@ import { supportedAnalysisKinds, } from "./analyses"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; import { createFeatures, RecordingLogger, @@ -65,7 +64,7 @@ test.serial( .withArgs("analysis-kinds") .returns("code-scanning,code-quality"); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -139,7 +138,7 @@ test.serial( const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput"); optionalInputStub.withArgs("quality-queries").returns("code-quality"); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -155,7 +154,7 @@ test.serial( const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput"); requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing"); await t.throwsAsync( - getAnalysisKinds(getRunnerLogger(true), features, true), + getAnalysisKinds(new RecordingLogger(), features, true), ); }, ); @@ -181,7 +180,7 @@ for (let i = 0; i < analysisKinds.length; i++) { .withArgs("analysis-kinds") .returns([analysisKind, otherAnalysis].join(",")); const result = await getAnalysisKinds( - getRunnerLogger(true), + new RecordingLogger(), features, true, ); @@ -199,7 +198,7 @@ for (let i = 0; i < analysisKinds.length; i++) { .withArgs("analysis-kinds") .returns([analysisKind, otherAnalysis].join(",")); await t.throwsAsync( - getAnalysisKinds(getRunnerLogger(true), features, true), + getAnalysisKinds(new RecordingLogger(), features, true), { instanceOf: ConfigurationError, message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`, diff --git a/src/analyze.test.ts b/src/analyze.test.ts index 80fc7a547..e60bec719 100644 --- a/src/analyze.test.ts +++ b/src/analyze.test.ts @@ -15,12 +15,12 @@ import { createStubCodeQL } from "./codeql"; import { defaultSuites } from "./config/db-config"; import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { setupTests, setupActionsVars, createFeatures, createTestConfig, + RecordingLogger, } from "./testing-utils"; import * as uploadLib from "./upload-lib"; import * as util from "./util"; @@ -107,7 +107,7 @@ test.serial("status report fields", async (t) => { undefined, codeql, config, - getRunnerLogger(true), + new RecordingLogger(), createFeatures([Feature.QaTelemetryEnabled]), ); t.deepEqual(Object.keys(statusReport).sort(), [ diff --git a/src/artifact-scanner.test.ts b/src/artifact-scanner.test.ts index 56f99e113..50c0d3fd2 100644 --- a/src/artifact-scanner.test.ts +++ b/src/artifact-scanner.test.ts @@ -10,12 +10,12 @@ import { scanArtifactsForTokens, TokenType, } from "./artifact-scanner"; -import { getRunnerLogger } from "./logging"; import { checkExpectedLogMessages, getRecordingLogger, LoggedMessage, makeTestToken, + RecordingLogger, } from "./testing-utils"; test("makeTestToken", (t) => { @@ -121,7 +121,7 @@ for (const { type, value, checkPattern } of testTokens) { } test("scanArtifactsForTokens handles files without tokens", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-")); try { diff --git a/src/cli/output-cache.test.ts b/src/cli/output-cache.test.ts index 656cfd820..ed49dab09 100644 --- a/src/cli/output-cache.test.ts +++ b/src/cli/output-cache.test.ts @@ -3,15 +3,14 @@ import path from "path"; import test from "ava"; -import { getRunnerLogger } from "../logging"; -import { setupTests } from "../testing-utils"; +import { RecordingLogger, setupTests } from "../testing-utils"; import * as util from "../util"; import { getCachedCodeQlVersion } from "./output-cache"; setupTests(test); -const logger = getRunnerLogger(true); +const logger = new RecordingLogger(); test.serial( "getCachedCodeQlVersion reuses a version persisted by an earlier step", diff --git a/src/codeql.test.ts b/src/codeql.test.ts index 643f6d983..4dcc3153e 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -22,7 +22,6 @@ import type { Config } from "./config-utils"; import * as defaults from "./defaults.json"; import { DocUrl } from "./doc-url"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { ToolsSource } from "./setup-codeql"; import { setupTests, @@ -35,6 +34,7 @@ import { createTestConfig, makeMacro, getCodeQLForTesting, + RecordingLogger, } from "./testing-utils"; import { ToolsDownloadStatusReport } from "./tools-download"; import * as util from "./util"; @@ -103,7 +103,7 @@ async function installIntoToolcache({ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), false, ); } @@ -177,7 +177,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -213,7 +213,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -253,7 +253,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.assert(toolcache.find("CodeQL", "0.0.0-20200610")); @@ -363,7 +363,7 @@ for (const { undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.assert(toolcache.find("CodeQL", expectedToolcacheVersion)); @@ -406,7 +406,7 @@ for (const toolcacheVersion of [ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.is( @@ -451,7 +451,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, "0.0.0-20200601"); @@ -498,7 +498,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, defaults.cliVersion); @@ -538,7 +538,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); t.deepEqual(result.toolsVersion, defaults.cliVersion); @@ -580,7 +580,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion features, - getRunnerLogger(true), + new RecordingLogger(), false, ); @@ -665,7 +665,7 @@ const injectedConfigMacro = makeMacro({ tempDir, }; thisStubConfig.computedConfig = generateCodeScanningConfig( - getRunnerLogger(true), + new RecordingLogger(), thisStubConfig.originalUserInput, augmentationProperties, ); diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index b1f5f7134..254e86338 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -21,7 +21,6 @@ import { RepositoryProperties } from "./feature-flags/properties"; import * as gitUtils from "./git-utils"; import { GitVersionInfo } from "./git-utils"; import { BuiltInLanguage, Language } from "./languages"; -import { getRunnerLogger } from "./logging"; import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay"; import * as overlayDiagnostics from "./overlay/diagnostics"; import { OverlayDisabledReason } from "./overlay/diagnostics"; @@ -42,6 +41,7 @@ import { callee, SAMPLE_DOTCOM_API_DETAILS, AssertableTarget, + RecordingLogger, } from "./testing-utils"; import { GitHubVariant, @@ -102,7 +102,7 @@ function createTestInitConfigInputs( features: createFeatures([]), repositoryProperties: {}, enableFileCoverageInformation: true, - logger: getRunnerLogger(true), + logger: new RecordingLogger(), } satisfies configUtils.InitConfigInputs, overrides, ); @@ -150,7 +150,7 @@ function mockListLanguages(languages: string[]) { test.serial("load empty config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "javascript,python"; setupActionsVars(tempDir, tempDir); @@ -194,7 +194,7 @@ test.serial("load empty config", async (t) => { test.serial("load code quality config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "actions"; setupActionsVars(tempDir, tempDir); @@ -249,7 +249,7 @@ test.serial( "initActionState doesn't throw if there are queries configured in the repository properties", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const languages = "javascript"; setupActionsVars(tempDir, tempDir); @@ -311,7 +311,7 @@ test.serial( test.serial("loading a saved config produces the same config", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -359,7 +359,7 @@ test.serial("loading a saved config produces the same config", async (t) => { test.serial("loading config with version mismatch throws", async (t) => { return await withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -782,12 +782,12 @@ test.serial("Unknown languages", async (t) => { }); }); -const mockLogger = getRunnerLogger(true); +const mockLogger = new RecordingLogger(); test.serial("no generateRegistries when registries is undefined", async (t) => { return await withTmpDir(async (tmpDir) => { const registriesInput = undefined; - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, tmpDir, logger); @@ -808,7 +808,7 @@ test.serial( token: "not-a-token", }, ]); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, tmpDir, logger); @@ -2245,7 +2245,7 @@ test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff const config = createTestConfig({}); config.overlayDatabaseMode = OverlayDatabaseMode.None; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2263,7 +2263,7 @@ test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions w overlayDatabaseMode: OverlayDatabaseMode.Overlay, }); const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2286,7 +2286,7 @@ test.serial( }); config.useOverlayDatabaseCaching = true; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const addDiagnosticsStub = sinon .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics") .resolves(); @@ -2318,7 +2318,7 @@ test.serial( config.useOverlayDatabaseCaching = false; config.overlayModeSetExplicitly = true; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const addDiagnosticsStub = sinon .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics") .resolves(); @@ -2341,7 +2341,7 @@ test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only r const config = createTestConfig({}); config.overlayDatabaseMode = OverlayDatabaseMode.None; const codeql = createStubCodeQL({}); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); await configUtils.applyIncrementalAnalysisSettings( config, @@ -2555,7 +2555,7 @@ test("determineUserConfig - merges configs if FF is enabled in Default Setup", a // also check whether loading the configuration from disk that was written // by `determineUserConfig` matches our expectations. const loadedFromDisk = configUtils.getLocalConfig( - getRunnerLogger(true), + new RecordingLogger(), expectedConfigPath, false, ); diff --git a/src/config/db-config.test.ts b/src/config/db-config.test.ts index 76fa91801..4a10a9701 100644 --- a/src/config/db-config.test.ts +++ b/src/config/db-config.test.ts @@ -2,7 +2,6 @@ import test, { ExecutionContext } from "ava"; import { RepositoryProperties } from "../feature-flags/properties"; import { BuiltInLanguage, Language } from "../languages"; -import { getRunnerLogger } from "../logging"; import { checkExpectedLogMessages, getRecordingLogger, @@ -384,7 +383,7 @@ calculateAugmentationErrorMacro( test("parseUserConfig - successfully parses valid YAML", (t) => { const result = dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", ` paths-ignore: @@ -410,7 +409,7 @@ test("parseUserConfig - throws a ConfigurationError if the file is not valid YAM t.throws( () => dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", ` paths-ignore: @@ -629,7 +628,7 @@ test("mergeDefaultSetupAndUserConfigs - warns about invalid keys from Default Se /** Parses `contents` as a configuration without validating it. */ function parseUnvalidatedConfig(contents: string): dbConfig.UserConfig { return dbConfig.parseUserConfig( - getRunnerLogger(true), + new RecordingLogger(), "test", contents, false, diff --git a/src/diff-informed-analysis-utils.test.ts b/src/diff-informed-analysis-utils.test.ts index e07240e32..76e5f33b4 100644 --- a/src/diff-informed-analysis-utils.test.ts +++ b/src/diff-informed-analysis-utils.test.ts @@ -10,7 +10,6 @@ import { exportedForTesting, } from "./diff-informed-analysis-utils"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; -import { getRunnerLogger } from "./logging"; import { parseRepositoryNwo } from "./repository"; import { setupTests, @@ -19,6 +18,7 @@ import { mockFeatureFlagApiEndpoint, setupActionsVars, makeMacro, + RecordingLogger, } from "./testing-utils"; import { GitHubVariant, withTmpDir } from "./util"; import type { GitHubVersion } from "./util"; @@ -55,7 +55,7 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({ setupActionsVars(tmpDir, tmpDir); const testCase = { ...defaultTestCase, ...partialTestCase }; - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion(testCase.codeQLVersion); if (testCase.diffInformedQueriesEnvVar !== undefined) { @@ -182,7 +182,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -207,7 +207,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); // A features implementation whose getValue rejects, simulating an // unexpected failure when determining whether diff-informed analysis @@ -237,7 +237,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -274,7 +274,7 @@ test.serial( async (t) => { await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const codeql = mockCodeQLVersion("2.21.0"); const features = createFeatures([Feature.DiffInformedQueries]); @@ -313,7 +313,7 @@ function runGetDiffRanges(changes: number, patch: string[] | undefined): any { changes, patch: patch?.join("\n"), }, - getRunnerLogger(true), + new RecordingLogger(), ); } diff --git a/src/feature-flags/properties.test.ts b/src/feature-flags/properties.test.ts index d3094a8d1..6544d15d3 100644 --- a/src/feature-flags/properties.test.ts +++ b/src/feature-flags/properties.test.ts @@ -2,7 +2,6 @@ import test from "ava"; import * as sinon from "sinon"; import * as api from "../api-client"; -import { getRunnerLogger } from "../logging"; import { parseRepositoryNwo } from "../repository"; import { RecordingLogger, setupTests } from "../testing-utils"; @@ -19,7 +18,7 @@ test.serial( url: "", data: {}, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -39,7 +38,7 @@ test.serial( url: "", data: [{}], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -63,7 +62,7 @@ test.serial( { property_name: "also-not-used-by-us", value: ["A", "B", "C"] }, ], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.notThrowsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -86,7 +85,7 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => { { property_name: "unknown-property", value: "something" }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( logger, @@ -113,7 +112,7 @@ test.serial("loadPropertiesFromApi parses true boolean property", async (t) => { { property_name: "github-codeql-extra-queries", value: "+queries" }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( @@ -141,7 +140,7 @@ test.serial( }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( @@ -164,7 +163,7 @@ test.serial( url: "", data: [{ property_name: "github-codeql-extra-queries", value: 123 }], }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); await t.throwsAsync( properties.loadPropertiesFromApi(logger, mockRepositoryNwo), @@ -190,7 +189,7 @@ test.serial( }, ] satisfies properties.GitHubPropertiesResponse, }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const warningSpy = sinon.spy(logger, "warning"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const response = await properties.loadPropertiesFromApi( diff --git a/src/feature-flags/testing-util.ts b/src/feature-flags/testing-util.ts index 202f2c97b..46795bdf0 100644 --- a/src/feature-flags/testing-util.ts +++ b/src/feature-flags/testing-util.ts @@ -8,11 +8,12 @@ import { FeatureWithoutCLI, initFeatures, } from "../feature-flags"; -import { getRunnerLogger } from "../logging"; +import type { Logger } from "../logging"; import { parseRepositoryNwo } from "../repository"; import { LoggedMessage, mockCodeQLVersion, + RecordingLogger, setupActionsVars, } from "../testing-utils"; import { ToolsFeature } from "../tools-features"; @@ -51,7 +52,7 @@ export function assertAllFeaturesUndefinedInApi( export function setUpFeatureFlagTests( tmpDir: string, - logger = getRunnerLogger(true), + logger: Logger = new RecordingLogger(), gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion, ): FeatureEnablement { setupActionsVars(tmpDir, tmpDir); diff --git a/src/fingerprints.test.ts b/src/fingerprints.test.ts index 6cb9b6861..6b480a777 100644 --- a/src/fingerprints.test.ts +++ b/src/fingerprints.test.ts @@ -5,9 +5,8 @@ import * as ava from "ava"; import test from "ava"; import * as fingerprints from "./fingerprints"; -import { getRunnerLogger } from "./logging"; import * as sarif from "./sarif"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as util from "./util"; setupTests(test); @@ -131,7 +130,7 @@ function testResolveUriToFile(uri: any, index: any, artifactsURIs: any[]) { location, artifacts, process.cwd(), - getRunnerLogger(true), + new RecordingLogger(), ); } @@ -218,7 +217,7 @@ test("addFingerprints", async (t) => { await fingerprints.addFingerprints( input, sourceRoot, - getRunnerLogger(true), + new RecordingLogger(), ), expected, ); @@ -246,7 +245,7 @@ test("missingRegions", async (t) => { await fingerprints.addFingerprints( input, sourceRoot, - getRunnerLogger(true), + new RecordingLogger(), ), expected, ); diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 26b6ff4ab..5fa691787 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -11,7 +11,6 @@ import * as debugArtifacts from "./debug-artifacts"; import { EnvVar } from "./environment"; import { Feature } from "./feature-flags"; import * as initActionPostHelper from "./init-action-post-helper"; -import { getRunnerLogger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import * as overlayStatus from "./overlay/status"; import { parseRepositoryNwo } from "./repository"; @@ -63,7 +62,7 @@ test.serial("init-post action with debug mode off", async (t) => { createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(uploadAllAvailableDebugArtifactsSpy.notCalled); @@ -87,7 +86,7 @@ test.serial("init-post action with debug mode on", async (t) => { createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(uploadAllAvailableDebugArtifactsSpy.called); @@ -384,7 +383,7 @@ test.serial( createFeatures([Feature.OverlayAnalysisStatusSave]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -454,7 +453,7 @@ test.serial( createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -498,7 +497,7 @@ test.serial("does not save overlay status when build successful", async (t) => { createFeatures([Feature.OverlayAnalysisStatusSave]), "success", env, - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -537,7 +536,7 @@ test.serial( createFeatures([]), "success", getTestEnv(), - getRunnerLogger(true), + new RecordingLogger(), ); t.true( @@ -590,7 +589,7 @@ async function runOverlayPostStep({ createFeatures([Feature.OverlayAnalysisStatusSave]), jobStatus, env, - getRunnerLogger(true), + new RecordingLogger(), ); return { saveOverlayStatusStub }; @@ -765,7 +764,7 @@ async function testFailedSarifUpload( config, parseRepositoryNwo("github/codeql-action"), createFeatures(features), - getRunnerLogger(true), + new RecordingLogger(), ); if (expectUpload) { t.deepEqual(result, { diff --git a/src/logging.ts b/src/logging.ts index 177aca6c7..ffe4e6cce 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -51,22 +51,6 @@ export function getActionsLogger(): Logger { }; } -export function getRunnerLogger(debugMode: boolean): Logger { - return { - // eslint-disable-next-line no-console - debug: debugMode ? console.debug : () => undefined, - // eslint-disable-next-line no-console - info: console.info, - // eslint-disable-next-line no-console - warning: console.warn, - // eslint-disable-next-line no-console - error: console.error, - isDebug: () => debugMode, - startGroup: () => undefined, - endGroup: () => undefined, - }; -} - export function withGroup(groupName: string, f: () => T): T { core.startGroup(groupName); try { diff --git a/src/overlay/caching.test.ts b/src/overlay/caching.test.ts index 364eeff9c..e965b06a7 100644 --- a/src/overlay/caching.test.ts +++ b/src/overlay/caching.test.ts @@ -11,11 +11,11 @@ import type { ResolveDatabaseOutput } from "../codeql"; import * as environment from "../environment"; import * as gitUtils from "../git-utils"; import { BuiltInLanguage } from "../languages"; -import { getRunnerLogger } from "../logging"; import { createTestConfig, makeMacro, mockCodeQLVersion, + RecordingLogger, setupTests, } from "../testing-utils"; import * as utils from "../util"; @@ -63,7 +63,7 @@ const testDownloadOverlayBaseDatabaseFromCache = makeMacro({ const dbLocation = path.join(tmpDir, "db"); await fs.promises.mkdir(dbLocation, { recursive: true }); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const testCase = { ...defaultDownloadTestCase, ...partialTestCase }; const config = createTestConfig({ dbLocation, @@ -214,7 +214,7 @@ testDownloadOverlayBaseDatabaseFromCache.serial( ); test.serial("overlay-base database cache keys remain stable", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ languages: ["python", "javascript"] }); const codeQlVersion = "2.23.0"; const commitOid = "abc123def456"; @@ -261,7 +261,7 @@ test.serial("overlay-base database cache keys remain stable", async (t) => { test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns unique versions sorted latest first", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -287,7 +287,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns empty list when no caches exist", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([]); @@ -303,7 +303,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns empty list when cache keys are unparseable", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -324,7 +324,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases returns the single version when only one cache exists", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ @@ -344,7 +344,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases resolves language aliases", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); // The alias `c++` should be resolved to "cpp" and match cache entries keyed with "cpp" sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); @@ -365,7 +365,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases de-duplicates resolved language aliases", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); const listActionsCachesStub = sinon @@ -391,7 +391,7 @@ test.serial( test.serial( "getCodeQlVersionsForOverlayBaseDatabases ignores nightly versions with build metadata", async (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); sinon.stub(apiClient, "getAutomationID").resolves("test-automation-id/"); sinon.stub(apiClient, "listActionsCaches").resolves([ diff --git a/src/overlay/index.test.ts b/src/overlay/index.test.ts index 967ccf3a7..4534006f8 100644 --- a/src/overlay/index.test.ts +++ b/src/overlay/index.test.ts @@ -6,8 +6,11 @@ import * as sinon from "sinon"; import * as actionsUtil from "../actions-util"; import * as gitUtils from "../git-utils"; -import { getRunnerLogger } from "../logging"; -import { createTestConfig, setupTests } from "../testing-utils"; +import { + createTestConfig, + RecordingLogger, + setupTests, +} from "../testing-utils"; import { withTmpDir } from "../util"; import { writeBaseDatabaseOidsFile, writeOverlayChangesFile } from "."; @@ -27,7 +30,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -91,7 +94,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -169,7 +172,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Mock the getFileOidsUnderPath function to return base OIDs @@ -232,7 +235,7 @@ test.serial( ), ); - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const config = createTestConfig({ dbLocation }); // Base OIDs (sourceRoot-relative paths) diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 3fef11e63..90c3c3309 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -14,7 +14,6 @@ import * as diagnostics from "./diagnostics"; import { ActionsEnvVars, Env, EnvVar, ReadOnlyEnv } from "./environment"; import { Feature } from "./feature-flags"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { getCacheRestoreKeyPrefix } from "./overlay/caching"; import { MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION } from "./per-language-bundles"; import * as setupCodeql from "./setup-codeql"; @@ -22,6 +21,7 @@ import * as tar from "./tar"; import { LINKED_CLI_VERSION, LoggedMessage, + RecordingLogger, SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DOTCOM_API_DETAILS, checkExpectedLogMessages, @@ -117,7 +117,7 @@ test.serial("convert to semver", (t) => { try { const parsedVersion = setupCodeql.convertToSemVer( version, - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(parsedVersion, expectedVersion); } catch (e) { @@ -127,7 +127,7 @@ test.serial("convert to semver", (t) => { }); test.serial("getCodeQLActionRepository", (t) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); initializeEnvironment("1.2.3"); @@ -163,7 +163,7 @@ test.serial( GitHubVariant.DOTCOM, false, features, - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(source, { @@ -249,7 +249,7 @@ for (const { GitHubVariant.DOTCOM, tarSupportsZstd, features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.toolsVersion, LINKED_CLI_VERSION.cliVersion); @@ -615,7 +615,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.CleanupToolcacheBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(result.toolsVersion, "local"); @@ -652,7 +652,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) { GitHubVariant.DOTCOM, true, // tarSupportsZstd createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(source, { @@ -712,7 +712,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -751,7 +751,7 @@ for (const perLanguageBundles of [false, true]) { ? [Feature.ForceNightly, Feature.PerLanguageBundles] : [Feature.ForceNightly], ), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -866,7 +866,7 @@ test.serial( GitHubVariant.DOTCOM, true, createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ), { message: @@ -1038,7 +1038,7 @@ test.serial( t.is( setupCodeql.tryGetTagNameFromUrl( "https://github.com/org/codeql-bundle-testing/releases/download/codeql-bundle-v2.19.0/codeql-bundle-linux64.tar.zst", - getRunnerLogger(true), + new RecordingLogger(), ), "codeql-bundle-v2.19.0", ); @@ -1050,7 +1050,7 @@ test.serial( (t) => { sinon.stub(toolcache, "findAllVersions").returns([]); t.is( - setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), + setupCodeql.getLatestToolcacheVersion(new RecordingLogger()), undefined, ); }, @@ -1062,7 +1062,7 @@ test.serial( const testVersions = ["2.3.1", "3.2.1", "1.2.3"]; sinon.stub(toolcache, "findAllVersions").returns(testVersions); - t.is(setupCodeql.getLatestToolcacheVersion(getRunnerLogger(true)), "3.2.1"); + t.is(setupCodeql.getLatestToolcacheVersion(new RecordingLogger()), "3.2.1"); }, ); @@ -1116,7 +1116,7 @@ test.serial( GitHubVariant.DOTCOM, false, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(listStub.calledOnce); @@ -1155,7 +1155,7 @@ test.serial( GitHubVariant.DOTCOM, false, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(listStub.notCalled); @@ -1193,7 +1193,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -1244,7 +1244,7 @@ test.serial( GitHubVariant.DOTCOM, true, // tarSupportsZstd features, - getRunnerLogger(true), + new RecordingLogger(), ); t.is(source.sourceType, "download"); @@ -1314,7 +1314,7 @@ for (const fallback of [false, true]) { undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ); t.true(fetchRelease.calledTwice); @@ -1582,7 +1582,7 @@ for (const error of [ undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.PerLanguageBundles]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -1618,7 +1618,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -1651,7 +1651,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, @@ -1674,7 +1674,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); }, @@ -1691,7 +1691,7 @@ const noLanguagesMacro = makeMacro({ overlayMatchEnabledVersions, rawLanguages, createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); t.assert( @@ -1716,7 +1716,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); }, @@ -1736,7 +1736,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersion]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.2", tagName: "codeql-bundle-v2.20.2" }, @@ -1753,7 +1753,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, []); t.assert( @@ -1777,7 +1777,7 @@ test.serial( overlayMatchEnabledVersions, ["javascript"], createFeatures([Feature.OverlayAnalysisMatchCodeqlVersionDryRun]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual( result, @@ -1808,7 +1808,7 @@ test.serial( Feature.OverlayAnalysisMatchCodeqlVersion, Feature.OverlayAnalysisMatchCodeqlVersionDryRun, ]), - getRunnerLogger(true), + new RecordingLogger(), ); t.deepEqual(result, [ { cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" }, @@ -2138,7 +2138,7 @@ test.serial( env: new ReadOnlyEnv({ [ActionsEnvVars.RUNNER_TOOL_CACHE]: injectedRoot, }), - logger: getRunnerLogger(true), + logger: new RecordingLogger(), }); t.deepEqual(result, { @@ -2291,7 +2291,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is( @@ -2331,7 +2331,7 @@ test.serial( undefined, // otherLanguagePacksReason false, // useOverlayAwareDefaultCliVersion createFeatures([Feature.CleanupToolcacheBundles]), - getRunnerLogger(true), + new RecordingLogger(), ), { is: error }, ); @@ -2449,7 +2449,7 @@ test.serial( "isToolcacheOnWorkspaceFilesystem assumes a different filesystem when it cannot tell", async (t) => { await withTmpDir(async (tmpDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); setupActionsVars(tmpDir, tmpDir); t.true(toolsDownload.isToolcacheOnWorkspaceFilesystem(logger)); diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index bd2489713..692524e81 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -12,7 +12,7 @@ import { setUpFeatureFlagTests } from "./feature-flags/testing-util"; import { UnvalidatedObject, validateSchema } from "./json"; import { makeFromSchema } from "./json/testing-util"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import { BundlePlatform, getBundlePlatform } from "./platform"; import * as startProxyExports from "./start-proxy"; import * as statusReport from "./status-report"; @@ -148,7 +148,7 @@ test("getCredentials prefers registriesCredentials over registrySecrets", async ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), registrySecrets, registryCredentials, undefined, @@ -165,7 +165,7 @@ test("getCredentials throws an error when configurations are not an array", asyn t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, registryCredentials, undefined, @@ -184,7 +184,7 @@ test("getCredentials throws error when credential is not an object", async (t) = t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -205,7 +205,7 @@ test("getCredentials throws error when credential is missing type", async (t) => t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -228,7 +228,7 @@ test("getCredentials throws error when credential missing host and url", async ( t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, testCredential, undefined, @@ -242,7 +242,7 @@ test("getCredentials throws error when credential missing host and url", async ( test("getCredentials filters by language when specified", async (t) => { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(mixedCredentials), BuiltInLanguage.java, @@ -253,7 +253,7 @@ test("getCredentials filters by language when specified", async (t) => { test("getCredentials returns all for a language when specified", async (t) => { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([...mixedCredentials, gitSourceCredential]), BuiltInLanguage.go, @@ -273,7 +273,7 @@ test("getCredentials returns all goproxy_servers for Go when specified", async ( ]; const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(multipleGoproxyServers), BuiltInLanguage.go, @@ -302,7 +302,7 @@ test("getCredentials returns all maven_repositories for Java when specified", as ]; const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(multipleMavenRepositories), BuiltInLanguage.java, @@ -320,7 +320,7 @@ test("getCredentials returns all credentials when no language specified", async const credentialsInput = toEncodedJSON(mixedCredentials); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -350,7 +350,7 @@ test("getCredentials throws an error when non-printable characters are used", as t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -381,7 +381,7 @@ for (const oidcSchemaInfo of startProxyExports.oidcSchemas) { t.throws( () => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, undefined, @@ -405,7 +405,7 @@ test("getCredentials accepts OIDC configurations", (t) => { ); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON(oidcConfigurations), BuiltInLanguage.csharp, @@ -595,7 +595,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, BuiltInLanguage.java, @@ -614,7 +614,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { }; t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": null }]), BuiltInLanguage.java, @@ -622,7 +622,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ); t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": 123 }]), BuiltInLanguage.java, @@ -630,7 +630,7 @@ test("getCredentials validates 'replaces-base' correctly", async (t) => { ); t.throws(() => startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, toEncodedJSON([{ ...baseInvalid, "replaces-base": "true" }]), BuiltInLanguage.java, @@ -646,7 +646,7 @@ test("getCredentials returns only ALWAYS_ENABLED_REGISTRY_TYPE credentials for A ]); const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, BuiltInLanguage.actions, @@ -678,7 +678,7 @@ test("getCredentials always returns ALWAYS_ENABLED_REGISTRY_TYPE credentials for // Test all languages. for (const language of Object.values(BuiltInLanguage)) { const credentials = startProxyExports.getCredentials( - getRunnerLogger(true), + new RecordingLogger(), undefined, credentialsInput, language, diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 2b763da70..004161efa 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -6,7 +6,6 @@ import * as actionsUtil from "./actions-util"; import { Config } from "./config-utils"; 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 { @@ -154,7 +153,7 @@ test.serial("createStatusReportBase", async (t) => { languages: [BuiltInLanguage.java, BuiltInLanguage.swift], }), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ); @@ -203,7 +202,7 @@ test.serial("createStatusReportBase - empty configuration", async (t) => { new Date("May 19, 2023 05:19:00"), {}, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), ); if (t.truthy(statusReport)) { @@ -225,7 +224,7 @@ test.serial("createStatusReportBase - partial configuration", async (t) => { languages: ["go"], }, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), ); if (t.truthy(statusReport)) { @@ -248,7 +247,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -264,7 +263,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -281,7 +280,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -297,7 +296,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -314,7 +313,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -330,7 +329,7 @@ test.serial("createStatusReportBase_firstParty", async (t) => { new Date("May 19, 2023 05:19:00"), createTestConfig({}), { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ) @@ -411,7 +410,7 @@ const testCreateInitWithConfigStatusReport = makeMacro({ new Date("May 19, 2023 05:19:00"), config, { numAvailableBytes: 100, numTotalBytes: 500 }, - getRunnerLogger(false), + new RecordingLogger(), "failure cause", "exception stack trace", ); diff --git a/src/tar.test.ts b/src/tar.test.ts index 48f4e866d..99d68b531 100644 --- a/src/tar.test.ts +++ b/src/tar.test.ts @@ -3,9 +3,8 @@ import * as stream from "stream"; import test from "ava"; -import { getRunnerLogger } from "./logging"; import { extractTarZst } from "./tar"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import { withTmpDir } from "./util"; setupTests(test); @@ -17,7 +16,7 @@ test("extractTarZst rejects if the input stream errors", async (t) => { archive, path.join(tmpDir, "dest"), { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); archive.destroy( diff --git a/src/testing-utils.ts b/src/testing-utils.ts index dfb08d997..63f9533d2 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -30,13 +30,7 @@ import { featureConfig, FeatureEnablement, } from "./feature-flags"; -import { - getRunnerLogger, - joinMessageStrings, - Loggable, - LoggableError, - Logger, -} from "./logging"; +import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; @@ -1014,7 +1008,7 @@ export function makeTestToken(length: number = 36) { */ export async function getCodeQLForTesting( cmd = "codeql-for-testing", - logger: Logger = getRunnerLogger(true), + logger: Logger = new RecordingLogger(), ): Promise { return codeql.getCodeQLForCmd(logger, cmd, false); } diff --git a/src/tools-download.test.ts b/src/tools-download.test.ts index 407e2ea48..1ba980bbe 100644 --- a/src/tools-download.test.ts +++ b/src/tools-download.test.ts @@ -10,9 +10,8 @@ import { https } from "follow-redirects"; import nock from "nock"; import * as sinon from "sinon"; -import { getRunnerLogger } from "./logging"; import * as tar from "./tar"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import { downloadAndExtract } from "./tools-download"; import * as util from "./util"; @@ -34,7 +33,7 @@ test.serial( undefined, {}, undefined, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -72,7 +71,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -105,7 +104,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ), { instanceOf: util.HTTPError, @@ -149,7 +148,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.downloadDurationMs)); @@ -189,7 +188,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.is( @@ -237,7 +236,7 @@ test.serial( undefined, {}, { type: "gnu", version: "1.34" }, - getRunnerLogger(true), + new RecordingLogger(), ); t.assert(Number.isInteger(statusReport.totalDurationMs)); diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 478305e57..efe93a13f 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -16,12 +16,12 @@ import * as configUtils from "./config-utils"; import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { createFeatures, createTestConfig, getRecordingLogger, makeVersionInfo, + RecordingLogger, setupTests, } from "./testing-utils"; import { @@ -264,7 +264,7 @@ test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => { const statusReport = await cleanupTrapCaches( config, createFeatures([Feature.CleanupTrapCaches]), - getRunnerLogger(true), + new RecordingLogger(), ); t.is(listStub.callCount, 1); diff --git a/src/upload-lib.test.ts b/src/upload-lib.test.ts index 2c27d56c1..ebfc5cd40 100644 --- a/src/upload-lib.test.ts +++ b/src/upload-lib.test.ts @@ -10,9 +10,9 @@ import * as analyses from "./analyses"; import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses"; import * as api from "./api-client"; import * as diffUtils from "./diff-informed-analysis-utils"; -import { getRunnerLogger, Logger } from "./logging"; +import { Logger } from "./logging"; import * as sarif from "./sarif"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as uploadLib from "./upload-lib"; import { UploadPayload } from "./upload-lib/types"; import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; @@ -29,7 +29,7 @@ test.serial("validateSarifFileSchema - valid", (t) => { uploadLib.validateSarifFileSchema( uploadLib.readSarifFileOrThrow(inputFile), inputFile, - getRunnerLogger(true), + new RecordingLogger(), ), ); }); @@ -40,7 +40,7 @@ test.serial("validateSarifFileSchema - invalid", (t) => { uploadLib.validateSarifFileSchema( uploadLib.readSarifFileOrThrow(inputFile), inputFile, - getRunnerLogger(true), + new RecordingLogger(), ), ); }); @@ -179,7 +179,7 @@ test.serial("finding SARIF files", async (t) => { } const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), tmpDir, ); @@ -200,7 +200,7 @@ test.serial("getGroupedSarifFilePaths - Risk Assessment files", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -218,7 +218,7 @@ test.serial("getGroupedSarifFilePaths - Code Quality file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -236,7 +236,7 @@ test.serial("getGroupedSarifFilePaths - Code Scanning file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -254,7 +254,7 @@ test.serial("getGroupedSarifFilePaths - Other file", async (t) => { fs.writeFileSync(sarifPath, ""); const groupedSarifFiles = await uploadLib.getGroupedSarifFilePaths( - getRunnerLogger(true), + new RecordingLogger(), sarifPath, ); @@ -932,7 +932,7 @@ function uploadPayloadFixtures(analysis: analyses.AnalysisConfig) { owner: mockData.owner, repo: mockData.repo, }, - getRunnerLogger(true), + new RecordingLogger(), analysis, ); @@ -1019,7 +1019,7 @@ function runFilterAlertsByDiffRange( diffRanges: diffUtils.DiffThunkRange[], ): Partial { sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges); - return uploadLib.filterAlertsByDiffRange(getRunnerLogger(true), input); + return uploadLib.filterAlertsByDiffRange(new RecordingLogger(), input); } test.serial( diff --git a/src/upload-sarif.test.ts b/src/upload-sarif.test.ts index d310bce92..f9318b196 100644 --- a/src/upload-sarif.test.ts +++ b/src/upload-sarif.test.ts @@ -5,8 +5,12 @@ import test, { ExecutionContext } from "ava"; import * as sinon from "sinon"; import { AnalysisKind, getAnalysisConfig } from "./analyses"; -import { getRunnerLogger } from "./logging"; -import { createFeatures, makeMacro, setupTests } from "./testing-utils"; +import { + createFeatures, + makeMacro, + RecordingLogger, + setupTests, +} from "./testing-utils"; import { UploadResult } from "./upload-lib"; import * as uploadLib from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -51,7 +55,7 @@ const postProcessAndUploadSarifMacro = makeMacro({ expectedResult: Partial>, ) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const testPath = sarifPath(tempDir); const features = createFeatures([]); @@ -206,7 +210,7 @@ test.serial( "postProcessAndUploadSarif doesn't upload if upload is disabled", async (t) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const features = createFeatures([]); const toFullPath = (filename: string) => path.join(tempDir, filename); @@ -239,7 +243,7 @@ test.serial( "postProcessAndUploadSarif writes post-processed SARIF files if output directory is provided", async (t) => { await util.withTmpDir(async (tempDir) => { - const logger = getRunnerLogger(true); + const logger = new RecordingLogger(); const features = createFeatures([]); const toFullPath = (filename: string) => path.join(tempDir, filename); diff --git a/src/util.test.ts b/src/util.test.ts index 074310279..a4b7576b8 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -10,8 +10,7 @@ import * as sinon from "sinon"; import * as api from "./api-client"; import { EnvVar } from "./environment"; -import { getRunnerLogger } from "./logging"; -import { setupTests } from "./testing-utils"; +import { RecordingLogger, setupTests } from "./testing-utils"; import * as util from "./util"; setupTests(test); @@ -92,7 +91,7 @@ for (const { test("getMemoryFlag() throws if the ram input is < 0 or NaN", async (t) => { for (const input of ["-1", "hello!"]) { - t.throws(() => util.getMemoryFlag(input, getRunnerLogger(true))); + t.throws(() => util.getMemoryFlag(input, new RecordingLogger())); } }); @@ -109,13 +108,13 @@ test("getThreadsFlag() should return the correct --threads flag", (t) => { ]; for (const [input, expectedFlag] of tests) { - const flag = util.getThreadsFlag(input, getRunnerLogger(true)); + const flag = util.getThreadsFlag(input, new RecordingLogger()); t.deepEqual(flag, expectedFlag); } }); test("getThreadsFlag() throws if the threads input is not an integer", (t) => { - t.throws(() => util.getThreadsFlag("hello!", getRunnerLogger(true))); + t.throws(() => util.getThreadsFlag("hello!", new RecordingLogger())); }); test.serial( @@ -445,7 +444,7 @@ test("getCgroupCpuCountFromCpus calculates the number of CPUs correctly", async const testCpuFile = `${tmpDir}/cpus-file`; fs.writeFileSync(testCpuFile, "1, 9-10\n", "utf-8"); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), 3, ); }); @@ -456,7 +455,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file doesn't exist" const testCpuFile = `${tmpDir}/cpus-file`; t.false(fs.existsSync(testCpuFile)); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), undefined, ); }); @@ -467,7 +466,7 @@ test("getCgroupCpuCountFromCpus returns undefined if the CPU file exists but is const testCpuFile = `${tmpDir}/cpus-file`; fs.writeFileSync(testCpuFile, "\n", "utf-8"); t.deepEqual( - util.getCgroupCpuCountFromCpus(testCpuFile, getRunnerLogger(true)), + util.getCgroupCpuCountFromCpus(testCpuFile, new RecordingLogger()), undefined, ); }); @@ -477,7 +476,7 @@ test.serial( "checkDiskUsage succeeds and produces positive numbers", async (t) => { process.env["GITHUB_WORKSPACE"] = os.tmpdir(); - const diskUsage = await util.checkDiskUsage(getRunnerLogger(true)); + const diskUsage = await util.checkDiskUsage(new RecordingLogger()); if (t.truthy(diskUsage)) { t.true(diskUsage.numAvailableBytes > 0); t.true(diskUsage.numTotalBytes > 0); From 7d7a550898448d564d08fbc23acaabecc105a70f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 14 Oct 2026 15:11:32 +0100 Subject: [PATCH 04/27] Ensure consistent output formatting in `addMessage` --- src/testing-utils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 63f9533d2..04f0d1701 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -619,11 +619,12 @@ export class RecordingLogger implements Logger { constructor(private readonly logToConsole: boolean = true) {} private addMessage(level: LogLevel, message: LoggableError): void { - this.messages.push({ type: level, message: joinMessageStrings(message) }); + const joinedMessage = joinMessageStrings(message); + this.messages.push({ type: level, message: joinedMessage }); if (this.logToConsole) { // eslint-disable-next-line no-console - console.debug(message); + console.debug(joinedMessage); } } From 1a7b87e3d1ff559edb5823aad696a7b281d15f07 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:45:10 +0100 Subject: [PATCH 05/27] Remove TRAP cache cleanup Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 103 +--------------------------------- src/analyze-action.ts | 21 +------ src/api-client.ts | 15 ----- src/doc-url.ts | 1 - src/feature-flags.ts | 6 -- src/trap-caching.test.ts | 86 ---------------------------- src/trap-caching.ts | 118 +-------------------------------------- 7 files changed, 3 insertions(+), 347 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1a99a4442..fb4ca4736 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170867,14 +170867,6 @@ async function listActionsCaches(keyPrefix, ref) { } ); } -async function deleteActionsCache(id) { - const repositoryNwo = getRepositoryNwo(); - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id - }); -} async function getRepositoryProperties(repositoryNwo) { return getApiClient().request("GET /repos/:owner/:repo/properties/values", { owner: repositoryNwo.owner, @@ -171932,11 +171924,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: void 0 }, - ["cleanup_trap_caches" /* CleanupTrapCaches */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: void 0 - }, ["config_file_repository_property" /* ConfigFileRepositoryProperty */]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", @@ -174250,83 +174237,6 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } -async function cleanupTrapCaches(config, features, logger2) { - const env = getEnv(); - if (!await features.getValue("cleanup_trap_caches" /* CleanupTrapCaches */)) { - return { - trap_cache_cleanup_skipped_because: "feature disabled" - }; - } - logger2.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action." - ); - if (!await isAnalyzingDefaultBranch(env, config.repositoryRoot)) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch" - }; - } - try { - let totalBytesCleanedUp = 0; - const allCaches = await listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await getRef(env, config.repositoryRoot) - ); - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger2 - ); - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - const mostRecentCache = cachesToRemove.pop(); - logger2.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})` - ); - if (cachesToRemove.length === 0) { - logger2.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - for (const cache of cachesToRemove) { - logger2.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0 - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger2.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.` - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger2.warning( - `Could not cleanup TRAP caches as the token did not have the required permissions. To clean up TRAP caches, ensure the token has the "actions:write" permission. See ${"https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs" /* ASSIGNING_PERMISSIONS_TO_JOBS */} for more information.` - ); - } else { - logger2.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} -async function getTrapCachesForLanguage(allCaches, language, logger2) { - logger2.debug(`Listing TRAP caches for ${language}`); - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - `An unexpected cache item was returned from the API that was missing one or more required fields: ${JSON.stringify(cache)}` - ); - } - } - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }); -} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180651,7 +180561,7 @@ async function postProcessAndUploadSarif(logger2, features, uploadKind, checkout } // src/analyze-action.ts -async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, trapCacheCleanup, dependencyCacheResults, databaseUploadResults, logger2) { +async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, dependencyCacheResults, databaseUploadResults, logger2) { const status = getActionsStatus(error3, stats?.analyze_failure_language); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, @@ -180668,7 +180578,6 @@ async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUplo ...statusReportBase, ...stats || {}, ...dbCreationTimings || {}, - ...trapCacheCleanup || {}, dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults }; @@ -180752,7 +180661,6 @@ async function run(action) { let uploadResults = void 0; let runStats = void 0; let config = void 0; - let trapCacheCleanupTelemetry = void 0; let trapCacheUploadTime = void 0; let dbCreationTimings = void 0; let didUploadTrapCaches = false; @@ -180896,11 +180804,6 @@ async function run(action) { const trapCacheUploadStartTime = import_perf_hooks6.performance.now(); didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger2); trapCacheUploadTime = import_perf_hooks6.performance.now() - trapCacheUploadStartTime; - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger2 - ); if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( codeql, @@ -180937,7 +180840,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180956,7 +180858,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180970,7 +180871,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180984,7 +180884,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 9efbb529b..5478d818e 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,11 +49,7 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { - cleanupTrapCaches, - TrapCacheCleanupStatusReport, - uploadTrapCaches, -} from "./trap-caching"; +import { uploadTrapCaches } from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -86,7 +82,6 @@ async function sendStatusReport( trapCacheUploadTime: number | undefined, dbCreationTimings: DatabaseCreationTimings | undefined, didUploadTrapCaches: boolean, - trapCacheCleanup: TrapCacheCleanupStatusReport | undefined, dependencyCacheResults: DependencyCacheUploadStatusReport | undefined, databaseUploadResults: DatabaseUploadResult[], logger: Logger, @@ -107,7 +102,6 @@ async function sendStatusReport( ...statusReportBase, ...(stats || {}), ...(dbCreationTimings || {}), - ...(trapCacheCleanup || {}), dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults, }; @@ -229,8 +223,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { | undefined = undefined; let runStats: QueriesStatusReport | undefined = undefined; let config: Config | undefined = undefined; - let trapCacheCleanupTelemetry: TrapCacheCleanupStatusReport | undefined = - undefined; let trapCacheUploadTime: number | undefined = undefined; let dbCreationTimings: DatabaseCreationTimings | undefined = undefined; let didUploadTrapCaches = false; @@ -415,13 +407,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger); trapCacheUploadTime = performance.now() - trapCacheUploadStartTime; - // Clean up TRAP caches - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger, - ); - // Store dependency cache(s) if dependency caching is enabled. if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( @@ -471,7 +456,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -494,7 +478,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -508,7 +491,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -522,7 +504,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, diff --git a/src/api-client.ts b/src/api-client.ts index 7aa4d61d7..8a456c169 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -401,21 +401,6 @@ export async function listActionsCaches( ); } -/** - * Delete an Actions cache item by its ID. - * - * See https://docs.github.com/en/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id. - */ -export async function deleteActionsCache(id: number) { - const repositoryNwo = getRepositoryNwo(); - - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id, - }); -} - /** * Retrieve all custom repository properties. * diff --git a/src/doc-url.ts b/src/doc-url.ts index c624817e9..97f5451d8 100644 --- a/src/doc-url.ts +++ b/src/doc-url.ts @@ -3,7 +3,6 @@ */ export enum DocUrl { - ASSIGNING_PERMISSIONS_TO_JOBS = "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs", AUTOMATIC_BUILD_FAILED = "https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed", CODEQL_BUILD_MODES = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes", DEFINE_ENV_VARIABLES = "https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 5cf7c7414..8b8e1027a 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -74,7 +74,6 @@ export enum Feature { AllowMergeConfigFiles = "allow_merge_config_files", /** Controls whether we allow multiple values for the `analysis-kinds` input. */ AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds", - CleanupTrapCaches = "cleanup_trap_caches", /** Whether to allow the `config-file` input to be specified via a repository property. */ ConfigFileRepositoryProperty = "config_file_repository_property", CppDependencyInstallation = "cpp_dependency_installation_enabled", @@ -216,11 +215,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: undefined, }, - [Feature.CleanupTrapCaches]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: undefined, - }, [Feature.ConfigFileRepositoryProperty]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 15ab49481..6ec3d5aba 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -6,26 +6,21 @@ import test from "ava"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { getTrapCachingExtractorConfigArgs, getTrapCachingExtractorConfigArgsForLang, createStubCodeQL, } from "./codeql"; import * as configUtils from "./config-utils"; -import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { - createFeatures, createTestConfig, getRecordingLogger, makeVersionInfo, setupTests, } from "./testing-utils"; import { - cleanupTrapCaches, downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, @@ -199,84 +194,3 @@ test.serial( }); }, ); - -test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => { - await util.withTmpDir(async (tmpDir) => { - // This config specifies that we are analyzing JavaScript and Ruby, but not Swift. - const config = getTestConfigWithTempDir(tmpDir); - - sinon.stub(gitUtils, "getRef").resolves("refs/heads/main"); - sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true); - const listStub = sinon.stub(apiClient, "listActionsCaches").resolves([ - // Should be kept, since it's not relevant to CodeQL. In reality, the API shouldn't return - // this in the first place, but this is a defensive check. - { - id: 1, - key: "some-other-key", - created_at: "2024-05-23T14:25:00Z", - size_in_bytes: 100 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for JavaScript - { - id: 2, - key: "codeql-trap-1-2.0.0-javascript-newest", - created_at: "2024-04-23T14:25:00Z", - size_in_bytes: 50 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 3, - key: "codeql-trap-1-2.0.0-javascript-older", - created_at: "2024-03-22T14:25:00Z", - size_in_bytes: 200 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 4, - key: "codeql-trap-1-2.0.0-javascript-oldest", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for Ruby - { - id: 5, - key: "codeql-trap-1-2.0.0-ruby-newest", - created_at: "2024-02-20T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 6, - key: "codeql-trap-1-2.0.0-swift-newest", - created_at: "2024-02-22T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 7, - key: "codeql-trap-1-2.0.0-swift-older", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - ]); - - const deleteStub = sinon.stub(apiClient, "deleteActionsCache").resolves(); - - const statusReport = await cleanupTrapCaches( - config, - createFeatures([Feature.CleanupTrapCaches]), - getRunnerLogger(true), - ); - - t.is(listStub.callCount, 1); - t.assert(listStub.calledWithExactly("codeql-trap", "refs/heads/main")); - - t.deepEqual(statusReport, { - trap_cache_cleanup_size_bytes: 500 * 1024 * 1024, - }); - - t.is(deleteStub.callCount, 2); - t.assert(deleteStub.calledWithExactly(3)); - t.assert(deleteStub.calledWithExactly(4)); - }); -}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index d93936832..fd920600b 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -4,21 +4,12 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; -import { DocUrl } from "./doc-url"; -import { Feature, FeatureEnablement } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { Language } from "./languages"; import { Logger } from "./logging"; -import { - asHTTPError, - getEnv, - getErrorMessage, - tryGetFolderBytes, - waitForResultWithTimeLimit, -} from "./util"; +import { getEnv, tryGetFolderBytes, waitForResultWithTimeLimit } from "./util"; // This constant should be bumped if we make a breaking change // to how the CodeQL Action stores or retrieves the TRAP cache, @@ -178,113 +169,6 @@ export async function uploadTrapCaches( return true; } -export interface TrapCacheCleanupStatusReport { - trap_cache_cleanup_error?: string; - trap_cache_cleanup_size_bytes?: number; - trap_cache_cleanup_skipped_because?: string; -} - -export async function cleanupTrapCaches( - config: Config, - features: FeatureEnablement, - logger: Logger, -): Promise { - const env = getEnv(); - - if (!(await features.getValue(Feature.CleanupTrapCaches))) { - return { - trap_cache_cleanup_skipped_because: "feature disabled", - }; - } - logger.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. " + - "We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action.", - ); - if (!(await gitUtils.isAnalyzingDefaultBranch(env, config.repositoryRoot))) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch", - }; - } - - try { - let totalBytesCleanedUp = 0; - - const allCaches = await apiClient.listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await gitUtils.getRef(env, config.repositoryRoot), - ); - - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger, - ); - // Dates returned by the API are in ISO 8601 format, so we can sort them lexicographically - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - // Keep the most recent cache - const mostRecentCache = cachesToRemove.pop(); - logger.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})`, - ); - - if (cachesToRemove.length === 0) { - logger.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - - for (const cache of cachesToRemove) { - logger.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await apiClient.deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0, - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.`, - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger.warning( - "Could not cleanup TRAP caches as the token did not have the required permissions. " + - 'To clean up TRAP caches, ensure the token has the "actions:write" permission. ' + - `See ${DocUrl.ASSIGNING_PERMISSIONS_TO_JOBS} for more information.`, - ); - } else { - logger.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} - -async function getTrapCachesForLanguage( - allCaches: apiClient.ActionsCacheItem[], - language: Language, - logger: Logger, -): Promise>> { - logger.debug(`Listing TRAP caches for ${language}`); - - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - "An unexpected cache item was returned from the API that was missing one or " + - `more required fields: ${JSON.stringify(cache)}`, - ); - } - } - - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }) as Array>; -} - export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From 9b5d335b995d625719d424b7041ad3331c3f4cf9 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:48:34 +0100 Subject: [PATCH 06/27] Warn when `CODEQL_ACTION_CLEANUP_TRAP_CACHES` is set Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 11 +++++++++++ src/analyze-action.ts | 7 ++++++- src/trap-caching.test.ts | 27 +++++++++++++++++++++++++++ src/trap-caching.ts | 20 ++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index fb4ca4736..180ce0bff 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -174237,6 +174237,16 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } +function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger: logger2 +}) { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== void 0) { + logger2.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect and can be removed from your workflow. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by passing the `trap-caching: false` input to the `init` Action." + ); + } +} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180697,6 +180707,7 @@ async function run(action) { "The 'cleanup-level' input is ignored since the CodeQL Action now automatically manages database cleanup. This input can safely be removed from your workflow." ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); const apiDetails = getApiDetails(); const outputDir = getRequiredInput("output"); action.env.export("CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */, outputDir); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 5478d818e..f273dbbd8 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,7 +49,10 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { uploadTrapCaches } from "./trap-caching"; +import { + uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, +} from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -270,6 +273,8 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); + const apiDetails = getApiDetails(); const outputDir = actionsUtil.getRequiredInput("output"); action.env.export(EnvVar.SARIF_RESULTS_OUTPUT_DIR, outputDir); diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 6ec3d5aba..99dc59706 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -15,6 +15,7 @@ import * as configUtils from "./config-utils"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; import { + callee, createTestConfig, getRecordingLogger, makeVersionInfo, @@ -24,6 +25,7 @@ import { downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, } from "./trap-caching"; import * as util from "./util"; @@ -194,3 +196,28 @@ test.serial( }); }, ); + +// `CODEQL_ACTION_CLEANUP_TRAP_CACHES` has no effect with either value, so we warn even when it's +// set to `false`. +for (const value of ["true", "false"]) { + test(`warnIfTrapCacheCleanupEnvVarIsSet warns when CODEQL_ACTION_CLEANUP_TRAP_CACHES is '${value}'`, async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet) + .withEnv((env) => env.set("CODEQL_ACTION_CLEANUP_TRAP_CACHES", value)) + .withArgs() + .logs( + t, + "CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect", + ); + await target.passes(t.is, undefined); + t.deepEqual( + target.getLogger().messages.map((m) => m.type), + ["warning"], + ); + }); +} + +test("warnIfTrapCacheCleanupEnvVarIsSet doesn't warn when CODEQL_ACTION_CLEANUP_TRAP_CACHES is unset", async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet).withArgs(); + await target.passes(t.is, undefined); + t.deepEqual(target.getLogger().messages, []); +}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index fd920600b..58d96890f 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; +import { type ActionState } from "./action-common"; import * as actionsUtil from "./actions-util"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; @@ -169,6 +170,25 @@ export async function uploadTrapCaches( return true; } +/** + * Warns if the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is set to a non-empty + * value. That variable controlled the removed TRAP cache cleanup feature, so setting it has no + * effect. + */ +export function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger, +}: ActionState<["Logger", "ReadOnlyEnv"]>): void { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== undefined) { + logger.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment " + + "variable no longer has any effect and can be removed from your workflow. If you used TRAP " + + "cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by " + + "passing the `trap-caching: false` input to the `init` Action.", + ); + } +} + export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From ba6f82195bbe4ce1dc3726b3b0fff7d82747452c Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 14:02:16 +0100 Subject: [PATCH 07/27] Add change note Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- unreleased-change-notes/remove-trap-cache-cleanup.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased-change-notes/remove-trap-cache-cleanup.md diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md new file mode 100644 index 000000000..f63b7bebd --- /dev/null +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -0,0 +1 @@ +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 734778abbe5ad6cffe44e04de30b0746864bddfc Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 16:13:47 +0100 Subject: [PATCH 08/27] Improve changelog note Co-authored-by: Michael B. Gale --- unreleased-change-notes/remove-trap-cache-cleanup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md index f63b7bebd..b3cb822b8 100644 --- a/unreleased-change-notes/remove-trap-cache-cleanup.md +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -1 +1 @@ -- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 8bb7f8f14a657f1174b107dc5608f0965226a3f0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 16:27:51 +0100 Subject: [PATCH 09/27] Add JSDocs for `Logger` logging functions --- src/logging.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/logging.ts b/src/logging.ts index ffe4e6cce..da6716872 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -7,11 +7,47 @@ export type Loggable = string | string[]; export type LoggableError = Loggable | Error; export interface Logger { + /** + * Logs {@link message} at debug-level. + * In Actions, this will only be output if workflow debugging is enabled. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ debug: (message: Loggable) => void; + /** + * Logs {@link message} at info-level. + * In Actions, this will always be output. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ info: (message: Loggable) => void; + /** + * Logs {@link message} at warning-level. + * In Actions, this will always be output and highlighted as a warning. It will additionally + * result in a warning-level workflow annotation. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ warning: (message: LoggableError) => void; + /** + * Logs {@link message} at error-level. + * In Actions, this will always be output and highlighted as an error. It will additionally + * result in an error-level workflow annotation. + * + * @param message + * A string or an array of strings. If an array of strings is provided, they are joined using + * space as the delimiter and printed as a single line. + */ error: (message: LoggableError) => void; - + /** + * Gets a value indicating whether debugging is enabled. + */ isDebug: () => boolean; startGroup: (name: string) => void; From 297dec926f76a5869199314e02c7a0b346913007 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 13:48:22 +0100 Subject: [PATCH 10/27] Add `toolcache.ts` script for `bundle-toolcache.yml` --- .github/workflows/__bundle-toolcache.yml | 52 ++++++------- pr-checks/checks/bundle-toolcache.yml | 44 ++++------- pr-checks/toolcache.ts | 94 ++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 60 deletions(-) create mode 100755 pr-checks/toolcache.ts diff --git a/.github/workflows/__bundle-toolcache.yml b/.github/workflows/__bundle-toolcache.yml index 0055f9470..96a901cf3 100644 --- a/.github/workflows/__bundle-toolcache.yml +++ b/.github/workflows/__bundle-toolcache.yml @@ -50,6 +50,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -58,47 +67,30 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 env: CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/bundle-toolcache.yml b/pr-checks/checks/bundle-toolcache.yml index f74c6af75..3317a45f4 100644 --- a/pr-checks/checks/bundle-toolcache.yml +++ b/pr-checks/checks/bundle-toolcache.yml @@ -6,47 +6,31 @@ operatingSystems: - ubuntu - macos - windows +installNode: true steps: - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts new file mode 100755 index 000000000..a14605e38 --- /dev/null +++ b/pr-checks/toolcache.ts @@ -0,0 +1,94 @@ +#!/usr/bin/env npx tsx + +/** + * Provides utility commands for working with the Actions toolcache in PR checks. + */ + +import fs from "fs"; +import { parseArgs } from "node:util"; +import path from "path"; + +import * as core from "@actions/core"; +import * as toolcache from "@actions/tool-cache"; + +function removeCodeQLFromToolcache() { + const toolcachePath = process.env["RUNNER_TOOL_CACHE"]; + + if (toolcachePath === undefined) { + throw new Error("Expected RUNNER_TOOL_CACHE to be defined"); + } + + const codeqlPath = path.join(toolcachePath, "CodeQL"); + fs.rmdirSync(codeqlPath, { recursive: true }); + + core.info(`Removed '${codeqlPath}' from the toolcache.`); +} + +function findCodeQL() { + return toolcache.findAllVersions("CodeQL"); +} + +function noCodeQLInToolcache() { + const allCodeqlVersions = findCodeQL(); + if (allCodeqlVersions.length !== 0) { + throw new Error( + `CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`, + ); + } + core.info("No versions of CodeQL found in the toolcache"); +} + +function hasCodeQLInToolcache(expectedNumber?: string) { + const expected = + expectedNumber !== undefined + ? Number.parseInt(expectedNumber, 10) + : undefined; + + const allCodeqlVersions = findCodeQL(); + core.info(`Found CodeQL versions: ${allCodeqlVersions}`); + + if (allCodeqlVersions.length === 0) { + throw new Error("CodeQL not found in toolcache"); + } + if (expected !== undefined && allCodeqlVersions.length > expected) { + throw new Error( + `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, + ); + } +} + +function main() { + const { positionals, values } = parseArgs({ + options: { + // The *number* of expected versions in the toolcache. + expectedVersions: { type: "string", short: "n" }, + }, + allowPositionals: true, + }); + + if (positionals.length < 1) { + throw new Error("Command not specified."); + } + + const cmd = positionals[0]; + + switch (cmd.trim().toLowerCase()) { + case "clear": + removeCodeQLFromToolcache(); + return; + case "absent": + noCodeQLInToolcache(); + return; + case "installed": + hasCodeQLInToolcache(values.expectedVersions); + return; + default: + throw new Error(`Unknown command '${cmd}'.`); + } +} + +try { + main(); +} catch (err) { + core.setFailed(err instanceof Error ? err.message : String(err)); +} From 24408cc688e9f8de459b9077a0990a6762587831 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 13:49:30 +0100 Subject: [PATCH 11/27] Use `toolcache.ts` in `bundle-from-toolcache.yml` --- .github/workflows/__bundle-from-toolcache.yml | 36 +++++++++---------- pr-checks/checks/bundle-from-toolcache.yml | 28 +++++---------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/.github/workflows/__bundle-from-toolcache.yml b/.github/workflows/__bundle-from-toolcache.yml index a1c1fade0..1a307ba2e 100644 --- a/.github/workflows/__bundle-from-toolcache.yml +++ b/.github/workflows/__bundle-from-toolcache.yml @@ -46,6 +46,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -53,31 +62,20 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 - name: Check toolcache contains CodeQL continue-on-error: true - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length === 0) { - throw new Error(`CodeQL could not be found in the toolcache`); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed + - id: setup-codeql uses: ./../action/setup-codeql with: tools: ${{ steps.prepare-test.outputs.tools-url }} + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed env: CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/bundle-from-toolcache.yml b/pr-checks/checks/bundle-from-toolcache.yml index 0e51e2e12..947b27390 100644 --- a/pr-checks/checks/bundle-from-toolcache.yml +++ b/pr-checks/checks/bundle-from-toolcache.yml @@ -2,30 +2,20 @@ name: "Bundle: From toolcache" description: "The CodeQL bundle should be cached within the toolcache" versions: - toolcache +installNode: true steps: - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 - name: Check toolcache contains CodeQL continue-on-error: true - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length === 0) { - throw new Error(`CodeQL could not be found in the toolcache`); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed + - id: setup-codeql uses: ./../action/setup-codeql with: tools: ${{ steps.prepare-test.outputs.tools-url }} + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed From 57804e978e65c0e15d620179b2c60df7bcf0f6ec Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 14:24:12 +0100 Subject: [PATCH 12/27] Add `@actions/tool-cache` as an explicit dependency --- package-lock.json | 1 + pr-checks/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index d702b0f6f..71a06c5d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10484,6 +10484,7 @@ "dependencies": { "@actions/core": "^2.0.3", "@actions/github": "^8.0.1", + "@actions/tool-cache": "^3.0.1", "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", diff --git a/pr-checks/package.json b/pr-checks/package.json index 3f20d119d..343f94381 100644 --- a/pr-checks/package.json +++ b/pr-checks/package.json @@ -5,6 +5,7 @@ "dependencies": { "@actions/core": "^2.0.3", "@actions/github": "^8.0.1", + "@actions/tool-cache": "^3.0.1", "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", From d0ab717e67eec1c39f68f404715b32ea3d9bcdbe Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 17:45:21 +0100 Subject: [PATCH 13/27] Replace `rmdir` with `rmSync` --- pr-checks/toolcache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index a14605e38..8ec7e80b5 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -19,7 +19,7 @@ function removeCodeQLFromToolcache() { } const codeqlPath = path.join(toolcachePath, "CodeQL"); - fs.rmdirSync(codeqlPath, { recursive: true }); + fs.rmSync(codeqlPath, { recursive: true }); core.info(`Removed '${codeqlPath}' from the toolcache.`); } From 596ae5c8cf042b08e1010164da813fdfd11a6e48 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 20 Oct 2026 18:12:38 +0100 Subject: [PATCH 14/27] Make comparison strict --- pr-checks/toolcache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 8ec7e80b5..459ecb068 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -50,7 +50,7 @@ function hasCodeQLInToolcache(expectedNumber?: string) { if (allCodeqlVersions.length === 0) { throw new Error("CodeQL not found in toolcache"); } - if (expected !== undefined && allCodeqlVersions.length > expected) { + if (expected !== undefined && allCodeqlVersions.length !== expected) { throw new Error( `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, ); From 20f5ec39109073afe1789b098456b2be0164f4ee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 14:20:41 +0000 Subject: [PATCH 15/27] Update changelog for v4.39.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b88dff6aa..ec85da14e 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.39.1 - 21 Oct 2026 - Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256) From b5e1ed9574dcfa81c88c318140f3b3e5c199bfb3 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 21 Oct 2026 10:05:32 -0500 Subject: [PATCH 16/27] Trigger workflows From 33f58aa90d0a355774a25beaff09a8c0ec561ba9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:42 +0000 Subject: [PATCH 17/27] Update changelog and version after v4.39.1 --- 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 ec85da14e..8a96e0a9c 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.39.1 - 21 Oct 2026 - Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256) diff --git a/package-lock.json b/package-lock.json index d702b0f6f..cfc9b231f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index 209ded679..9bfd79222 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "private": true, "description": "CodeQL action", "scripts": { From 4cf32242898ad79d69aed5bc5bca8d94f1a902ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:52 +0000 Subject: [PATCH 18/27] 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 98c7f0488..0b7e6c4e3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170161,7 +170161,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.39.1"; + return "4.39.2"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); From 0fcd0abe85818a2728c270830d8d51c86241810c Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 21 Oct 2026 11:10:30 -0500 Subject: [PATCH 19/27] Trigger workflows From d1db36d3020dba2af0937a898accb5b0c9d8bdbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:54:13 +0000 Subject: [PATCH 20/27] Bump the npm-minor group across 1 directory with 3 updates Bumps the npm-minor group with 3 updates in the / directory: [uuid](https://github.com/uuidjs/uuid), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint). Updates `uuid` from 14.0.2 to 14.0.3 - [Release notes](https://github.com/uuidjs/uuid/releases) - [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md) - [Commits](https://github.com/uuidjs/uuid/compare/v14.0.2...v14.0.3) Updates `eslint-plugin-jsdoc` from 65.2.0 to 65.3.4 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v65.2.0...v65.3.4) Updates `typescript-eslint` from 8.71.1 to 8.71.2 - [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.71.2/packages/typescript-eslint) --- updated-dependencies: - dependency-name: uuid dependency-version: 14.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor - dependency-name: eslint-plugin-jsdoc dependency-version: 65.3.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor - dependency-name: typescript-eslint dependency-version: 8.71.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 140 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfc9b231f..8f37440fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "node-forge": "^1.4.0", "semver": "^7.8.5", "undici": "^6.28.0", - "uuid": "^14.0.2" + "uuid": "^14.0.3" }, "devDependencies": { "@ava/typescript": "6.0.0", @@ -57,14 +57,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.2.0", + "eslint-plugin-jsdoc": "^65.3.4", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.1" + "typescript-eslint": "^8.71.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2702,17 +2702,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.1.tgz", - "integrity": "sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", + "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/type-utils": "8.71.1", - "@typescript-eslint/utils": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/type-utils": "8.71.2", + "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2725,7 +2725,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.1", + "@typescript-eslint/parser": "^8.71.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2741,16 +2741,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.1.tgz", - "integrity": "sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", + "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "debug": "^4.4.3" }, "engines": { @@ -2784,14 +2784,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.1.tgz", - "integrity": "sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", + "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.1", - "@typescript-eslint/types": "^8.71.1", + "@typescript-eslint/tsconfig-utils": "^8.71.2", + "@typescript-eslint/types": "^8.71.2", "debug": "^4.4.3" }, "engines": { @@ -2824,14 +2824,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.1.tgz", - "integrity": "sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", + "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1" + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2842,9 +2842,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.1.tgz", - "integrity": "sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", + "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", "dev": true, "license": "MIT", "engines": { @@ -2859,15 +2859,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.1.tgz", - "integrity": "sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", + "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/utils": "8.71.1", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/utils": "8.71.2", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2902,9 +2902,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.1.tgz", - "integrity": "sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", + "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", "dev": true, "license": "MIT", "engines": { @@ -2916,16 +2916,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.1.tgz", - "integrity": "sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", + "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.1", - "@typescript-eslint/tsconfig-utils": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/visitor-keys": "8.71.1", + "@typescript-eslint/project-service": "8.71.2", + "@typescript-eslint/tsconfig-utils": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3001,16 +3001,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.1.tgz", - "integrity": "sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", + "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.1", - "@typescript-eslint/types": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1" + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3025,13 +3025,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.1.tgz", - "integrity": "sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", + "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/types": "8.71.2", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5365,9 +5365,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "65.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.2.0.tgz", - "integrity": "sha512-IMZaNwdDa5otUQYGWN1pzywZLsGKswitvFFNhcO8IOsBfaWpWIDXYuZh2sYhe9MNyKN9hz0YryOFaKdpbTP5Bw==", + "version": "65.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.4.tgz", + "integrity": "sha512-Z3/ro8sZPqnXKhyAzCNa3F7KCZ3js5xVx/q9BEvTjUGzN6OIQfdb+q3Sc9lJ3zCfyPnN0tI524ulZjYRxAwnAw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9981,16 +9981,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.71.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.1.tgz", - "integrity": "sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz", + "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.71.1", - "@typescript-eslint/parser": "8.71.1", - "@typescript-eslint/typescript-estree": "8.71.1", - "@typescript-eslint/utils": "8.71.1" + "@typescript-eslint/eslint-plugin": "8.71.2", + "@typescript-eslint/parser": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/utils": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10167,9 +10167,9 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz", - "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.3.tgz", + "integrity": "sha512-Sc5u1VVln93y1Xnz4R+CunOZc7R9LUcTmhj7Rc7Eg3HVcf7rVn2FOoa812fe0W8p3jD7xeoGSYbfqCGGH2B6xw==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 9bfd79222..76ac14cf2 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "node-forge": "^1.4.0", "semver": "^7.8.5", "undici": "^6.28.0", - "uuid": "^14.0.2" + "uuid": "^14.0.3" }, "devDependencies": { "@ava/typescript": "6.0.0", @@ -65,14 +65,14 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-github": "^6.1.2", "eslint-plugin-import-x": "^4.17.1", - "eslint-plugin-jsdoc": "^65.2.0", + "eslint-plugin-jsdoc": "^65.3.4", "eslint-plugin-no-async-foreach": "^0.1.1", "glob": "^13.0.6", "globals": "^17.13.0", "nock": "^14.0.17", "sinon": "^22.1.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.71.1" + "typescript-eslint": "^8.71.2" }, "overrides": { "@actions/tool-cache": { From ec3f8658b6956d81e8d3947e0199d9b2a5ee5e44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:56:03 +0000 Subject: [PATCH 21/27] Bump the actions-minor group across 1 directory with 3 updates Bumps the actions-minor group with 3 updates in the /.github/workflows directory: [actions/setup-java](https://github.com/actions/setup-java), [ruby/setup-ruby](https://github.com/ruby/setup-ruby) and [actions/create-github-app-token](https://github.com/actions/create-github-app-token). Updates `actions/setup-java` from 6.0.1 to 6.1.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/de7274f081f381c8f8158605e0321c36c376e2e6...b843ebf9b913146b38da2eaa7aeddf76074ae1ad) Updates `ruby/setup-ruby` from 1.327.0 to 1.329.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/14594264cd68ce8a2345dd349bc3d138a4ef85c8...651ff0d62c5c79bed6d53ec518387aae20e72c1a) Updates `actions/create-github-app-token` from 3.2.0 to 3.3.0 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Changelog](https://github.com/actions/create-github-app-token/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/create-github-app-token/compare/bcd2ba49218906704ab6c1aa796996da409d3eb1...64ab729a6294000f5aa4a4bc0b73d1f32bc45510) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor - dependency-name: ruby/setup-ruby dependency-version: 1.329.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor - dependency-name: actions/create-github-app-token dependency-version: 3.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor ... Signed-off-by: dependabot[bot] --- .../workflows/__autobuild-direct-tracing-with-working-dir.yml | 2 +- .github/workflows/__build-mode-autobuild.yml | 2 +- .github/workflows/__rubocop-multi-language.yml | 2 +- .github/workflows/post-release-mergeback.yml | 2 +- .github/workflows/rollback-release.yml | 2 +- .github/workflows/update-release-branch.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml index e0ff968bd..bad4921eb 100644 --- a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml +++ b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml @@ -63,7 +63,7 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Java - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 with: java-version: ${{ inputs.java-version || '17' }} distribution: temurin diff --git a/.github/workflows/__build-mode-autobuild.yml b/.github/workflows/__build-mode-autobuild.yml index edc1d505d..76e3f348a 100644 --- a/.github/workflows/__build-mode-autobuild.yml +++ b/.github/workflows/__build-mode-autobuild.yml @@ -63,7 +63,7 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Java - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 with: java-version: ${{ inputs.java-version || '17' }} distribution: temurin diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index 7bda6ce9f..c3348db6c 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@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0 + uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: ruby-version: 2.6 - name: Install Code Scanning integration diff --git a/.github/workflows/post-release-mergeback.yml b/.github/workflows/post-release-mergeback.yml index 354da0afd..76ef6e555 100644 --- a/.github/workflows/post-release-mergeback.yml +++ b/.github/workflows/post-release-mergeback.yml @@ -134,7 +134,7 @@ jobs: echo "::endgroup::" - name: Generate token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} diff --git a/.github/workflows/rollback-release.yml b/.github/workflows/rollback-release.yml index 01651796e..14a8490b8 100644 --- a/.github/workflows/rollback-release.yml +++ b/.github/workflows/rollback-release.yml @@ -139,7 +139,7 @@ jobs: - name: Generate token if: github.event_name == 'workflow_dispatch' - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} diff --git a/.github/workflows/update-release-branch.yml b/.github/workflows/update-release-branch.yml index a506b87ce..981a38eac 100644 --- a/.github/workflows/update-release-branch.yml +++ b/.github/workflows/update-release-branch.yml @@ -95,7 +95,7 @@ jobs: pull-requests: write # needed to create pull request steps: - name: Generate token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 id: app-token with: app-id: ${{ vars.AUTOMATION_APP_ID }} From fb5d8688b9288d836fcfe44a6ea1f42cb1a47bca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:58:09 +0000 Subject: [PATCH 22/27] Rebuild --- pr-checks/checks/rubocop-multi-language.yml | 2 +- pr-checks/sync.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pr-checks/checks/rubocop-multi-language.yml b/pr-checks/checks/rubocop-multi-language.yml index 633c2a379..eec3aa833 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@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0 + uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0 with: ruby-version: 2.6 - name: Install Code Scanning integration diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index d6382786c..08b514adf 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -263,8 +263,8 @@ const languageSetups: LanguageSetups = { name: "Install Java", uses: pinnedUses( "actions/setup-java", - "de7274f081f381c8f8158605e0321c36c376e2e6", - "v6.0.1", + "b843ebf9b913146b38da2eaa7aeddf76074ae1ad", + "v6.1.0", ), with: { "java-version": `\${{ inputs.java-version || '${defaultLanguageVersions.java}' }}`, From 34f75b50e724c177539ba21befb43ab2a8b1c897 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:34:35 +0100 Subject: [PATCH 23/27] Rename argument --- pr-checks/toolcache.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 459ecb068..7339bf898 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -60,8 +60,8 @@ function hasCodeQLInToolcache(expectedNumber?: string) { function main() { const { positionals, values } = parseArgs({ options: { - // The *number* of expected versions in the toolcache. - expectedVersions: { type: "string", short: "n" }, + // The number of expected versions in the toolcache. + "expected-version-count": { type: "string", short: "n" }, }, allowPositionals: true, }); @@ -80,7 +80,7 @@ function main() { noCodeQLInToolcache(); return; case "installed": - hasCodeQLInToolcache(values.expectedVersions); + hasCodeQLInToolcache(values["expected-version-count"]); return; default: throw new Error(`Unknown command '${cmd}'.`); From 6b344309f73a7460b93a7affee262a21e60a88f0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:36:06 +0100 Subject: [PATCH 24/27] Log versions if there are some --- pr-checks/toolcache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 7339bf898..6d734a2e7 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -45,11 +45,11 @@ function hasCodeQLInToolcache(expectedNumber?: string) { : undefined; const allCodeqlVersions = findCodeQL(); - core.info(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { throw new Error("CodeQL not found in toolcache"); } + + core.info(`Found CodeQL versions: ${allCodeqlVersions.join(", ")}`); if (expected !== undefined && allCodeqlVersions.length !== expected) { throw new Error( `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, From 0a00d0c14ffb44f643486c0dfcf11dfe5f09effd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 21 Oct 2026 19:36:54 +0100 Subject: [PATCH 25/27] Rename `noCodeQLInToolcache` --- pr-checks/toolcache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts index 6d734a2e7..aa7d9afc1 100755 --- a/pr-checks/toolcache.ts +++ b/pr-checks/toolcache.ts @@ -28,7 +28,7 @@ function findCodeQL() { return toolcache.findAllVersions("CodeQL"); } -function noCodeQLInToolcache() { +function checkNoCodeQLInToolcache() { const allCodeqlVersions = findCodeQL(); if (allCodeqlVersions.length !== 0) { throw new Error( @@ -77,7 +77,7 @@ function main() { removeCodeQLFromToolcache(); return; case "absent": - noCodeQLInToolcache(); + checkNoCodeQLInToolcache(); return; case "installed": hasCodeQLInToolcache(values["expected-version-count"]); From c758339759af8b8eaa99b7db1d25882a5d1bef9f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:17:07 +0100 Subject: [PATCH 26/27] Trigger workflows From 347d5ce5d59a46d1719e8b2f20356db6ed01c040 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 22 Oct 2026 10:17:39 +0100 Subject: [PATCH 27/27] Trigger workflows