From 8a884bdb366e48fe97d4249777075f9079de8cd1 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 3 Mar 2026 19:09:57 +0100 Subject: [PATCH 1/3] Extend `setupActionsVars` --- src/testing-utils.ts | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 3abc1f4f4c..317f9fa9b0 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -139,13 +139,40 @@ export function setupTests(test: TestFn) { }); } +/** + * Default values for environment variables typically set in an Actions + * environment. Tests can override individual variables by passing them in the + * `overrides` parameter. + */ +const DEFAULT_ACTIONS_VARS: Record = { + GITHUB_ACTION_REPOSITORY: "github/codeql-action", + GITHUB_API_URL: "https://api.github.com", + GITHUB_EVENT_NAME: "push", + GITHUB_JOB: "test-job", + GITHUB_REF: "refs/heads/main", + GITHUB_REPOSITORY: "github/codeql-action-testing", + GITHUB_RUN_ATTEMPT: "1", + GITHUB_RUN_ID: "1", + GITHUB_SERVER_URL: "https://github.com", + GITHUB_SHA: "0".repeat(40), + GITHUB_WORKFLOW: "test-workflow", + RUNNER_OS: "Linux", +}; + // Sets environment variables that make using some libraries designed for // use only on actions safe to use outside of actions. -export function setupActionsVars(tempDir: string, toolsDir: string) { +export function setupActionsVars( + tempDir: string, + toolsDir: string, + overrides?: Partial>, +) { + const vars = { ...DEFAULT_ACTIONS_VARS, ...overrides }; + for (const [key, value] of Object.entries(vars)) { + process.env[key] = value; + } process.env["RUNNER_TEMP"] = tempDir; process.env["RUNNER_TOOL_CACHE"] = toolsDir; process.env["GITHUB_WORKSPACE"] = tempDir; - process.env["GITHUB_EVENT_NAME"] = "push"; } type LogLevel = "debug" | "info" | "warning" | "error"; From d4f1b14259579a43fd08377af66704b7f5f53199 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Tue, 3 Mar 2026 19:24:18 +0100 Subject: [PATCH 2/3] Use new `setupActionsVars` pattern --- src/analyze-action-env.test.ts | 5 +---- src/analyze-action-input.test.ts | 5 +---- src/init-action-post-helper.test.ts | 34 +++++++++++------------------ src/setup-codeql.test.ts | 6 ++--- src/status-report.test.ts | 14 +++++------- src/testing-utils.ts | 2 +- 6 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/analyze-action-env.test.ts b/src/analyze-action-env.test.ts index aecbae4b02..e1538bf4b4 100644 --- a/src/analyze-action-env.test.ts +++ b/src/analyze-action-env.test.ts @@ -28,9 +28,7 @@ test("analyze action with RAM & threads from environment variables", async (t) = // it a bit to 20s. t.timeout(1000 * 20); await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_SERVER_URL"] = util.GITHUB_DOTCOM_URL; - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["GITHUB_API_URL"] = "https://api.github.com"; + setupActionsVars(tmpDir, tmpDir); sinon .stub(statusReport, "createStatusReportBase") .resolves({} as statusReport.StatusReportBase); @@ -54,7 +52,6 @@ test("analyze action with RAM & threads from environment variables", async (t) = const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput"); optionalInputStub.withArgs("expect-error").returns("false"); sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion); - setupActionsVars(tmpDir, tmpDir); mockFeatureFlagApiEndpoint(200, {}); // When there are no action inputs for RAM and threads, the action uses diff --git a/src/analyze-action-input.test.ts b/src/analyze-action-input.test.ts index 74c03923da..b2c56e119e 100644 --- a/src/analyze-action-input.test.ts +++ b/src/analyze-action-input.test.ts @@ -26,9 +26,7 @@ setupTests(test); test("analyze action with RAM & threads from action inputs", async (t) => { t.timeout(1000 * 20); await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_SERVER_URL"] = util.GITHUB_DOTCOM_URL; - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["GITHUB_API_URL"] = "https://api.github.com"; + setupActionsVars(tmpDir, tmpDir); sinon .stub(statusReport, "createStatusReportBase") .resolves({} as statusReport.StatusReportBase); @@ -51,7 +49,6 @@ test("analyze action with RAM & threads from action inputs", async (t) => { optionalInputStub.withArgs("expect-error").returns("false"); sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion); sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true); - setupActionsVars(tmpDir, tmpDir); mockFeatureFlagApiEndpoint(200, {}); process.env["CODEQL_THREADS"] = "1"; diff --git a/src/init-action-post-helper.test.ts b/src/init-action-post-helper.test.ts index 039c96ef75..9e6eadc088 100644 --- a/src/init-action-post-helper.test.ts +++ b/src/init-action-post-helper.test.ts @@ -15,7 +15,9 @@ import { parseRepositoryNwo } from "./repository"; import { createFeatures, createTestConfig, + DEFAULT_ACTIONS_VARS, makeVersionInfo, + setupActionsVars, setupTests, } from "./testing-utils"; import * as uploadLib from "./upload-lib"; @@ -28,8 +30,7 @@ setupTests(test); test("init-post action with debug mode off", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); const gitHubVersion: util.GitHubVersion = { type: util.GitHubVariant.DOTCOM, @@ -62,8 +63,7 @@ test("init-post action with debug mode off", async (t) => { test("init-post action with debug mode on", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); const uploadAllAvailableDebugArtifactsSpy = sinon.spy(); const printDebugLogsSpy = sinon.spy(); @@ -315,11 +315,7 @@ test("not uploading failed SARIF when `code-scanning` is not an enabled analysis test("saves overlay status when overlay-base analysis did not complete successfully", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["GITHUB_RUN_ID"] = "12345"; - process.env["GITHUB_RUN_ATTEMPT"] = "1"; - process.env["GITHUB_JOB"] = "analyze"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); // Ensure analyze did not complete successfully. delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY]; @@ -374,9 +370,9 @@ test("saves overlay status when overlay-base analysis did not complete successfu attemptedToBuildOverlayBaseDatabase: true, builtOverlayBaseDatabase: false, job: { - workflowRunId: 12345, - workflowRunAttempt: 1, - name: "analyze", + workflowRunId: Number(DEFAULT_ACTIONS_VARS.GITHUB_RUN_ID), + workflowRunAttempt: Number(DEFAULT_ACTIONS_VARS.GITHUB_RUN_ATTEMPT), + name: DEFAULT_ACTIONS_VARS.GITHUB_JOB, }, }, "fourth arg should be the overlay status recording an unsuccessful build attempt with job details", @@ -386,8 +382,7 @@ test("saves overlay status when overlay-base analysis did not complete successfu test("does not save overlay status when OverlayAnalysisStatusSave feature flag is disabled", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); // Ensure analyze did not complete successfully. delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY]; @@ -423,8 +418,7 @@ test("does not save overlay status when OverlayAnalysisStatusSave feature flag i test("does not save overlay status when build successful", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); // Mark analyze as having completed successfully. process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] = "true"; @@ -460,8 +454,7 @@ test("does not save overlay status when build successful", async (t) => { test("does not save overlay status when overlay not enabled", async (t) => { return await util.withTmpDir(async (tmpDir) => { - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["RUNNER_TEMP"] = tmpDir; + setupActionsVars(tmpDir, tmpDir); delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY]; sinon.stub(util, "checkDiskUsage").resolves({ @@ -546,9 +539,8 @@ async function testFailedSarifUpload( config.dbLocation = "path/to/database"; } process.env["GITHUB_JOB"] = "analyze"; - process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository"; - process.env["GITHUB_WORKSPACE"] = - "/home/runner/work/codeql-action/codeql-action"; + process.env["GITHUB_REPOSITORY"] = DEFAULT_ACTIONS_VARS.GITHUB_REPOSITORY; + process.env["GITHUB_WORKSPACE"] = "/tmp"; sinon .stub(actionsUtil, "getRequiredInput") .withArgs("matrix") diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 5b1587ab0a..91ace0196c 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -353,8 +353,7 @@ test("getCodeQLSource correctly returns nightly CLI version when forced by FF", sinon.stub(api, "getApiClient").value(() => client); await withTmpDir(async (tmpDir) => { - setupActionsVars(tmpDir, tmpDir); - process.env["GITHUB_EVENT_NAME"] = "dynamic"; + setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" }); const source = await setupCodeql.getCodeQLSource( undefined, @@ -405,8 +404,7 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools .returns(latestVersionPath); await withTmpDir(async (tmpDir) => { - setupActionsVars(tmpDir, tmpDir); - process.env["GITHUB_EVENT_NAME"] = "dynamic"; + setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" }); const source = await setupCodeql.getCodeQLSource( "toolcache", diff --git a/src/status-report.test.ts b/src/status-report.test.ts index e051c54a27..6f4bb11f89 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -25,18 +25,14 @@ import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util"; setupTests(test); function setupEnvironmentAndStub(tmpDir: string) { - setupActionsVars(tmpDir, tmpDir); + setupActionsVars(tmpDir, tmpDir, { + GITHUB_EVENT_NAME: "dynamic", + GITHUB_RUN_ATTEMPT: "2", + GITHUB_RUN_ID: "100", + }); process.env[EnvVar.ANALYSIS_KEY] = "analysis-key"; - process.env["GITHUB_EVENT_NAME"] = "dynamic"; - process.env["GITHUB_REF"] = "refs/heads/main"; - process.env["GITHUB_REPOSITORY"] = "octocat/HelloWorld"; - process.env["GITHUB_RUN_ATTEMPT"] = "2"; - process.env["GITHUB_RUN_ID"] = "100"; - process.env["GITHUB_SHA"] = "a".repeat(40); process.env["ImageVersion"] = "2023.05.19.1"; - process.env["RUNNER_OS"] = "macOS"; - process.env["RUNNER_TEMP"] = tmpDir; const getRequiredInput = sinon.stub(actionsUtil, "getRequiredInput"); getRequiredInput.withArgs("matrix").resolves("input/matrix"); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 317f9fa9b0..b24e2d360d 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -144,7 +144,7 @@ export function setupTests(test: TestFn) { * environment. Tests can override individual variables by passing them in the * `overrides` parameter. */ -const DEFAULT_ACTIONS_VARS: Record = { +export const DEFAULT_ACTIONS_VARS: Record = { GITHUB_ACTION_REPOSITORY: "github/codeql-action", GITHUB_API_URL: "https://api.github.com", GITHUB_EVENT_NAME: "push", From 71d7981285d42c7fab260e18624f00ba6c2ae000 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Wed, 4 Mar 2026 13:27:59 +0100 Subject: [PATCH 3/3] Address review comments --- src/testing-utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/testing-utils.ts b/src/testing-utils.ts index b24e2d360d..8a7cf8e2d9 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -144,7 +144,7 @@ export function setupTests(test: TestFn) { * environment. Tests can override individual variables by passing them in the * `overrides` parameter. */ -export const DEFAULT_ACTIONS_VARS: Record = { +export const DEFAULT_ACTIONS_VARS = { GITHUB_ACTION_REPOSITORY: "github/codeql-action", GITHUB_API_URL: "https://api.github.com", GITHUB_EVENT_NAME: "push", @@ -157,14 +157,14 @@ export const DEFAULT_ACTIONS_VARS: Record = { GITHUB_SHA: "0".repeat(40), GITHUB_WORKFLOW: "test-workflow", RUNNER_OS: "Linux", -}; +} as const satisfies Record; // Sets environment variables that make using some libraries designed for // use only on actions safe to use outside of actions. export function setupActionsVars( tempDir: string, toolsDir: string, - overrides?: Partial>, + overrides?: Partial>, ) { const vars = { ...DEFAULT_ACTIONS_VARS, ...overrides }; for (const [key, value] of Object.entries(vars)) {