From 8c165744687004941ae92faf249031aaca2a8716 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Nov 2026 11:01:09 +0000 Subject: [PATCH] Make `jsonFilePath` an explicit input to functions in `diff-informed/index.ts` --- lib/entry-points.js | 29 +++++++++++++++++------------ package-lock.json | 2 +- src/analyze.ts | 10 ++++++++-- src/config-utils.test.ts | 29 ++++++++++++++++++----------- src/config-utils.ts | 6 ++++-- src/diff-informed/index.test.ts | 21 +++++++++++++-------- src/diff-informed/index.ts | 26 ++++++++++++++------------ src/upload-lib.test.ts | 2 ++ src/upload-lib.ts | 5 ++++- 9 files changed, 81 insertions(+), 49 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 7f85887bb..fabc3fe7c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -181851,7 +181851,7 @@ async function getDiffInformedAnalysisBranches(codeql, features, logger2) { } return branches; } -async function prepareDiffInformedAnalysis(codeql, features, logger2) { +async function prepareDiffInformedAnalysis(logger2, features, codeql, jsonFilePath) { let branches; try { branches = await getDiffInformedAnalysisBranches(codeql, features, logger2); @@ -181865,7 +181865,7 @@ async function prepareDiffInformedAnalysis(codeql, features, logger2) { return false; } try { - return await computeAndPersistDiffRanges(branches, logger2); + return await computeAndPersistDiffRanges(logger2, jsonFilePath, branches); } catch (e) { logger2.warning( `Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}` @@ -181873,17 +181873,15 @@ async function prepareDiffInformedAnalysis(codeql, features, logger2) { return false; } } -function writeDiffRangesJsonFile(logger2, ranges) { +function writeDiffRangesJsonFile(logger2, jsonFilePath, ranges) { const jsonContents = JSON.stringify(ranges, null, 2); - const jsonFilePath = getDiffRangesJsonFilePath(); fs8.writeFileSync(jsonFilePath, jsonContents); logger2.debug( `Wrote pr-diff-range JSON file to ${jsonFilePath}: ${jsonContents}` ); } -function readDiffRangesJsonFile(logger2) { - const jsonFilePath = getDiffRangesJsonFilePath(); +function readDiffRangesJsonFile(logger2, jsonFilePath) { if (!fs8.existsSync(jsonFilePath)) { logger2.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`); return void 0; @@ -181923,13 +181921,13 @@ async function getPullRequestEditedDiffRanges(branches, logger2) { } return results; } -async function computeAndPersistDiffRanges(branches, logger2) { +async function computeAndPersistDiffRanges(logger2, jsonFilePath, branches) { logger2.info("Computing PR diff ranges..."); const ranges = await getPullRequestEditedDiffRanges(branches, logger2); if (ranges === void 0) { return false; } - writeDiffRangesJsonFile(logger2, ranges); + writeDiffRangesJsonFile(logger2, jsonFilePath, ranges); const distinctFiles = new Set(ranges.map((r) => r.path)).size; logger2.info( `Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).` @@ -183066,9 +183064,10 @@ async function initConfig(actionState, inputs) { ); } const hasDiffRanges = await prepareDiffInformedAnalysis( - inputs.codeql, + logger2, inputs.features, - logger2 + inputs.codeql, + getDiffRangesJsonFilePath(actionState.env) ); await applyIncrementalAnalysisSettings( config, @@ -186255,7 +186254,10 @@ async function setupDiffInformedQueryRun(logger2, checkoutPath) { return await withGroupAsync( "Generating diff range extension pack", async () => { - const diffRanges = readDiffRangesJsonFile(logger2); + const diffRanges = readDiffRangesJsonFile( + logger2, + getDiffRangesJsonFilePath() + ); if (diffRanges === void 0) { logger2.info( "No precomputed diff ranges found; skipping diff-informed analysis stage." @@ -188758,7 +188760,10 @@ function sanitize(str) { return (str ?? "_").replace(/[^a-zA-Z0-9_]/g, "_").toLocaleUpperCase(); } function filterAlertsByDiffRange(logger2, sarifLog) { - const diffRanges = readDiffRangesJsonFile(logger2); + const diffRanges = readDiffRangesJsonFile( + logger2, + getDiffRangesJsonFilePath() + ); if (!diffRanges?.length) { return sarifLog; } diff --git a/package-lock.json b/package-lock.json index 2e17a0606..f7bb64e69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10570,7 +10570,7 @@ "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": ">=16.0.0", "@octokit/plugin-rest-endpoint-methods": "^18.0.0", - "glob": "^13.0.6", + "glob": "^14.0.3", "lite-matter": "^0.1.2", "mdast-util-from-markdown": "^2.1.0", "semver": "^7.8.5", diff --git a/src/analyze.ts b/src/analyze.ts index 7e32d4036..57e1b6078 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -6,7 +6,10 @@ import * as io from "@actions/io"; import * as yaml from "js-yaml"; import type { ActionState } from "./action-common"; -import { getTemporaryDirectory } from "./actions-util"; +import { + getDiffRangesJsonFilePath, + getTemporaryDirectory, +} from "./actions-util"; import * as analyses from "./analyses"; import { setupCppAutobuild } from "./autobuild"; import { type CodeQL } from "./codeql"; @@ -292,7 +295,10 @@ export async function setupDiffInformedQueryRun( return await withGroupAsync( "Generating diff range extension pack", async () => { - const diffRanges = readDiffRangesJsonFile(logger); + const diffRanges = readDiffRangesJsonFile( + logger, + getDiffRangesJsonFilePath(), + ); if (diffRanges === undefined) { logger.info( "No precomputed diff ranges found; skipping diff-informed analysis stage.", diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index b66d4a797..592291408 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -15,6 +15,7 @@ import { createStubCodeQL } from "./codeql"; import { UserConfig } from "./config/db-config"; import * as file from "./config/file"; import * as configUtils from "./config-utils"; +import { ActionsEnvVars } from "./environment"; import * as errorMessages from "./error-messages"; import { Feature } from "./feature-flags"; import { RepositoryProperties } from "./feature-flags/properties"; @@ -42,6 +43,7 @@ import { SAMPLE_DOTCOM_API_DETAILS, AssertableTarget, RecordingLogger, + getTestEnv, } from "./testing-utils"; import { GitHubVariant, @@ -151,9 +153,11 @@ function mockListLanguages(languages: string[]) { test.serial("load empty config", async (t) => { return await withTmpDir(async (tempDir) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); + const languages = "javascript,python"; - setupActionsVars(tempDir, tempDir); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -166,7 +170,6 @@ test.serial("load empty config", async (t) => { }, }); - const state = initAllState({ logger }); const config = await configUtils.initConfig( state, createTestInitConfigInputs({ @@ -197,9 +200,10 @@ test.serial("load empty config", async (t) => { test.serial("load code quality config", async (t) => { return await withTmpDir(async (tempDir) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); const languages = "actions"; - setupActionsVars(tempDir, tempDir); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -211,7 +215,6 @@ test.serial("load code quality config", async (t) => { }, }); - const state = initAllState({ logger }); const config = await configUtils.initConfig( state, createTestInitConfigInputs({ @@ -253,9 +256,10 @@ test.serial( async (t) => { return await withTmpDir(async (tempDir) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); const languages = "javascript"; - setupActionsVars(tempDir, tempDir); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -291,7 +295,6 @@ test.serial( repositoryProperties, }); - const state = initAllState({ logger }); await t.notThrowsAsync(async () => { const config = await configUtils.initConfig( state, @@ -316,6 +319,8 @@ test.serial( test.serial("loading a saved config produces the same config", async (t) => { return await withTmpDir(async (tempDir) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -334,7 +339,6 @@ test.serial("loading a saved config produces the same config", async (t) => { // Sanity check that getConfig returns undefined before we have called initConfig t.deepEqual(await configUtils.getConfig(tempDir, logger), undefined); - const state = initAllState({ logger }); const config1 = await configUtils.initConfig( state, createTestInitConfigInputs({ @@ -364,6 +368,8 @@ 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 = new RecordingLogger(); + const state = initAllState({ logger }); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -387,7 +393,6 @@ test.serial("loading config with version mismatch throws", async (t) => { .stub(actionsUtil, "getActionVersion") .returns("does-not-exist"); - const state = initAllState({ logger }); const config = await configUtils.initConfig( state, createTestInitConfigInputs({ @@ -497,7 +502,8 @@ const otherConfigFileContents = ` test.serial("load non-empty input", async (t) => { return await withTmpDir(async (tempDir) => { - setupActionsVars(tempDir, tempDir); + const state = initAllState(); + setupActionsVars(tempDir, tempDir, {}, state.env); const codeql = createStubCodeQL({ async resolveLanguages() { @@ -538,7 +544,6 @@ test.serial("load non-empty input", async (t) => { const languagesInput = "javascript"; const configFilePath = createConfigFile(otherConfigFileContents, tempDir); - const state = initAllState(); const actualConfig = await configUtils.initConfig( state, createTestInitConfigInputs({ @@ -657,7 +662,9 @@ test.serial("API client used when reading remote config", async (t) => { const configFile = "octo-org/codeql-config/config.yaml@main"; const languagesInput = "javascript"; - const state = initAllState(); + const state = initAllState({ + env: getTestEnv({ [ActionsEnvVars.RUNNER_TEMP]: tempDir }), + }); await configUtils.initConfig( state, createTestInitConfigInputs({ diff --git a/src/config-utils.ts b/src/config-utils.ts index 33f1f3cd0..3726cc20a 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -7,6 +7,7 @@ import * as yaml from "js-yaml"; import { ActionState } from "./action-common"; import { getActionVersion, + getDiffRangesJsonFilePath, getOptionalInput, isAnalyzingPullRequest, isDefaultSetup, @@ -1288,9 +1289,10 @@ export async function initConfig( } const hasDiffRanges = await prepareDiffInformedAnalysis( - inputs.codeql, - inputs.features, logger, + inputs.features, + inputs.codeql, + getDiffRangesJsonFilePath(actionState.env), ); await applyIncrementalAnalysisSettings( diff --git a/src/diff-informed/index.test.ts b/src/diff-informed/index.test.ts index 73460dade..156d8a223 100644 --- a/src/diff-informed/index.test.ts +++ b/src/diff-informed/index.test.ts @@ -4,6 +4,7 @@ import * as sinon from "sinon"; import * as actionsUtil from "../actions-util"; import type { PullRequestBranches } from "../actions-util"; import * as apiClient from "../api-client"; +import { getEnv } from "../environment"; import { Feature, FeatureEnablement, initFeatures } from "../feature-flags"; import { parseRepositoryNwo } from "../repository"; import { @@ -193,9 +194,10 @@ test.serial( .resolves({ type: GitHubVariant.DOTCOM }); const result = await prepareDiffInformedAnalysis( - codeql, - features, logger, + features, + codeql, + actionsUtil.getDiffRangesJsonFilePath(getEnv()), ); t.false(result); @@ -223,9 +225,10 @@ test.serial( }; const result = await prepareDiffInformedAnalysis( - codeql, - features, logger, + features, + codeql, + actionsUtil.getDiffRangesJsonFilePath(getEnv()), ); t.false(result); @@ -260,9 +263,10 @@ test.serial( } as any); const result = await prepareDiffInformedAnalysis( - codeql, - features, logger, + features, + codeql, + actionsUtil.getDiffRangesJsonFilePath(getEnv()), ); t.true(result); @@ -297,9 +301,10 @@ test.serial( } as any); const result = await prepareDiffInformedAnalysis( - codeql, - features, logger, + features, + codeql, + actionsUtil.getDiffRangesJsonFilePath(getEnv()), ); t.false(result); diff --git a/src/diff-informed/index.ts b/src/diff-informed/index.ts index 44566b7e1..953096fa5 100644 --- a/src/diff-informed/index.ts +++ b/src/diff-informed/index.ts @@ -67,9 +67,10 @@ export async function getDiffInformedAnalysisBranches( * and are therefore available for use, `false` otherwise. */ export async function prepareDiffInformedAnalysis( - codeql: CodeQL, - features: FeatureEnablement, logger: Logger, + features: FeatureEnablement, + codeql: CodeQL, + jsonFilePath: string, ): Promise { let branches: PullRequestBranches | undefined; try { @@ -88,7 +89,7 @@ export async function prepareDiffInformedAnalysis( } try { - return await computeAndPersistDiffRanges(branches, logger); + return await computeAndPersistDiffRanges(logger, jsonFilePath, branches); } catch (e) { logger.warning( `Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}`, @@ -108,18 +109,18 @@ export interface DiffThunkRange { } /** - * Writes an array of {@link DiffThunkRange} objects to the file given by - * {@link actionsUtil.getDiffRangesJsonFilePath}. + * Writes an array of {@link DiffThunkRange} objects to the file given by {@link jsonFilePath}. * * @param logger The logger to use. + * @param jsonFilePath The path of the file to write. * @param ranges The changed line ranges to write. */ export function writeDiffRangesJsonFile( logger: Logger, + jsonFilePath: string, ranges: DiffThunkRange[], ): void { const jsonContents = JSON.stringify(ranges, null, 2); - const jsonFilePath = actionsUtil.getDiffRangesJsonFilePath(); fs.writeFileSync(jsonFilePath, jsonContents); logger.debug( `Wrote pr-diff-range JSON file to ${jsonFilePath}:\n${jsonContents}`, @@ -127,16 +128,15 @@ export function writeDiffRangesJsonFile( } /** - * Reads an array of {@link DiffThunkRange} objects from the file given by - * {@link actionsUtil.getDiffRangesJsonFilePath}. + * Reads an array of {@link DiffThunkRange} objects from the file given by {@link jsonFilePath}. * * @param logger The logger to use. * @returns The array of {@link DiffThunkRange} objects or `undefined` if the file couldn't be read. */ export function readDiffRangesJsonFile( logger: Logger, + jsonFilePath: string, ): DiffThunkRange[] | undefined { - const jsonFilePath = actionsUtil.getDiffRangesJsonFilePath(); if (!fs.existsSync(jsonFilePath)) { logger.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`); return undefined; @@ -201,23 +201,25 @@ export async function getPullRequestEditedDiffRanges( * diff from the GitHub API and writes it to the diff ranges JSON file so that * CodeQL can use it for diff-informed analysis. * + * @param logger The logger to use. + * @param jsonFilePath The path of the JSON file to write. * @param branches The base and head branches of the pull request, as returned * by `getDiffInformedAnalysisBranches`. - * @param logger The logger to use. * * @returns `true` if the diff ranges were successfully computed and persisted, * otherwise `false`. */ export async function computeAndPersistDiffRanges( - branches: PullRequestBranches, logger: Logger, + jsonFilePath: string, + branches: PullRequestBranches, ): Promise { logger.info("Computing PR diff ranges..."); const ranges = await getPullRequestEditedDiffRanges(branches, logger); if (ranges === undefined) { return false; } - writeDiffRangesJsonFile(logger, ranges); + writeDiffRangesJsonFile(logger, jsonFilePath, ranges); const distinctFiles = new Set(ranges.map((r) => r.path)).size; logger.info( `Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`, diff --git a/src/upload-lib.test.ts b/src/upload-lib.test.ts index d207c526a..1cbf64f64 100644 --- a/src/upload-lib.test.ts +++ b/src/upload-lib.test.ts @@ -6,6 +6,7 @@ import { HTTPError } from "@actions/tool-cache"; import test from "ava"; import * as sinon from "sinon"; +import * as actionsUtil from "./actions-util"; import * as analyses from "./analyses"; import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses"; import * as api from "./api-client"; @@ -1074,6 +1075,7 @@ function runFilterAlertsByDiffRange( logger: Logger = new RecordingLogger(), ): Partial { sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges); + sinon.stub(actionsUtil, "getDiffRangesJsonFilePath").returns(""); return uploadLib.filterAlertsByDiffRange(logger, input); } diff --git a/src/upload-lib.ts b/src/upload-lib.ts index e9e094e29..2ea517835 100644 --- a/src/upload-lib.ts +++ b/src/upload-lib.ts @@ -1079,7 +1079,10 @@ export function filterAlertsByDiffRange( logger: Logger, sarifLog: Partial, ): Partial { - const diffRanges = readDiffRangesJsonFile(logger); + const diffRanges = readDiffRangesJsonFile( + logger, + actionsUtil.getDiffRangesJsonFilePath(), + ); if (!diffRanges?.length) { return sarifLog; }