From 4a2ca5c068a2462212f2b7488705c0db44fc466f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 6 Oct 2026 13:36:35 +0100 Subject: [PATCH 1/5] 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 4bda956850..8de2effc4a 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 0000000000..33f6f8c162 --- /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 2c34cb54d4..177aca6c7b 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 cd60318944..1318415a72 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 2/5] 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 3237d57723..643f6d9839 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 68273d27b5..fde35b171b 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 fd1f489f7a..26b6ff4aba 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 1318415a72..dfb08d9972 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 a3c42d668d..f410d47c16 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 c7f168a9dc..5763430781 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 3/5] 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 17cf96a4a5..175fdea966 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 9d0a9eb3e0..b9d182618a 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 80fc7a5474..e60bec7193 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 56f99e1138..50c0d3fd22 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 656cfd8201..ed49dab09d 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 643f6d9839..4dcc3153e2 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 b1f5f71343..254e86338a 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 76fa918015..4a10a97017 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 e07240e322..76e5f33b4d 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 d3094a8d1c..6544d15d35 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 202f2c97b1..46795bdf09 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 6cb9b68617..6b480a777f 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 26b6ff4aba..5fa691787c 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 177aca6c7b..ffe4e6ccee 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 364eeff9c4..e965b06a7f 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 967ccf3a7d..4534006f80 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 3fef11e63e..90c3c33098 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 bd24897136..692524e811 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 2b763da700..004161efac 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 48f4e866d3..99d68b5317 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 dfb08d9972..63f9533d29 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 407e2ea489..1ba980bbe3 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 478305e577..efe93a13fd 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 2c27d56c1c..ebfc5cd404 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 d310bce92a..f9318b1966 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 074310279f..a4b7576b81 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 4/5] 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 63f9533d29..04f0d17013 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 8bb7f8f14a657f1174b107dc5608f0965226a3f0 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 16 Oct 2026 16:27:51 +0100 Subject: [PATCH 5/5] 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 ffe4e6ccee..da67168725 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;