Skip to content

Commit c59e24e

Browse files
committed
Prevent combineSarifFilesUsingCLI initialising CodeQL instance more than once
1 parent 7cbb19e commit c59e24e

11 files changed

+52556
-54738
lines changed

lib/analyze-action.js

Lines changed: 1026 additions & 2124 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/init-action-post.js

Lines changed: 2010 additions & 3152 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/upload-lib.js

Lines changed: 3232 additions & 3268 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/upload-sarif-action.js

Lines changed: 46197 additions & 46178 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/analyze-action.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ async function run(startedAt: Date) {
363363

364364
uploadResults = await postProcessAndUploadSarif(
365365
logger,
366+
config.tempDir,
366367
features,
368+
async () => codeql,
367369
uploadKind,
368370
checkoutPath,
369371
outputDir,

src/init-action-post-helper.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,8 @@ async function testFailedSarifUpload(
424424
}
425425
t.true(
426426
uploadFiles.calledOnceWith(
427+
sinon.match.string,
428+
codeqlObject,
427429
sinon.match.string,
428430
sinon.match.string,
429431
category,

src/init-action-post-helper.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ async function maybeUploadFailedSarif(
104104

105105
logger.info(`Uploading failed SARIF file ${sarifFile}`);
106106
const uploadResult = await uploadLib.uploadFiles(
107+
config.tempDir,
108+
codeql,
107109
sarifFile,
108110
checkoutPath,
109111
category,

src/upload-lib.ts

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import * as actionsUtil from "./actions-util";
1111
import * as analyses from "./analyses";
1212
import * as api from "./api-client";
1313
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
14-
import { getCodeQL, type CodeQL } from "./codeql";
15-
import { getConfig } from "./config-utils";
14+
import { type CodeQL } from "./codeql";
1615
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
1716
import { EnvVar } from "./environment";
1817
import { FeatureEnablement } from "./feature-flags";
@@ -219,15 +218,19 @@ export async function minimalInitCodeQL(
219218
return initCodeQLResult.codeql;
220219
}
221220

221+
export type CodeQLGetter = () => Promise<CodeQL>;
222+
222223
// Takes a list of paths to sarif files and combines them together using the
223224
// CLI `github merge-results` command when all SARIF files are produced by
224225
// CodeQL. Otherwise, it will fall back to combining the files in the action.
225226
// Returns the contents of the combined sarif file.
226227
async function combineSarifFilesUsingCLI(
227228
sarifFiles: string[],
228229
gitHubVersion: GitHubVersion,
229-
features: FeatureEnablement,
230+
_features: FeatureEnablement,
230231
logger: Logger,
232+
getCodeQL: CodeQLGetter,
233+
tempDir: string,
231234
): Promise<SarifFile> {
232235
logger.info("Combining SARIF files using the CodeQL CLI");
233236

@@ -265,18 +268,10 @@ async function combineSarifFilesUsingCLI(
265268
return combineSarifFiles(sarifFiles, logger);
266269
}
267270

268-
// Initialize CodeQL, either by using the config file from the 'init' step,
269-
// or by initializing it here.
270-
let codeQL: CodeQL;
271-
let tempDir: string = actionsUtil.getTemporaryDirectory();
272-
273-
const config = await getConfig(tempDir, logger);
274-
if (config !== undefined) {
275-
codeQL = await getCodeQL(config.codeQLCmd);
276-
tempDir = config.tempDir;
277-
} else {
278-
codeQL = await minimalInitCodeQL(logger, gitHubVersion, features);
279-
}
271+
// Obtain a `CodeQL` instance. For `analyze`, this is typically the instance that was used for running the queries.
272+
// For `upload-sarif`, this either initialises a new instance or returns a previously initialised one if `getCodeQL`
273+
// is called more than once.
274+
const codeQL: CodeQL = await getCodeQL();
280275

281276
const baseTempDir = path.resolve(tempDir, "combined-sarif");
282277
fs.mkdirSync(baseTempDir, { recursive: true });
@@ -682,6 +677,8 @@ export interface PostProcessingResults {
682677
*
683678
* @param logger The logger to use.
684679
* @param features Information about enabled features.
680+
* @param getCodeQL A function to retrieve a `CodeQL` instance.
681+
* @param tempPath A path to a temporary directory.
685682
* @param checkoutPath The path where the repo was checked out at.
686683
* @param sarifPaths The paths of the SARIF files to post-process.
687684
* @param category The analysis category.
@@ -693,6 +690,8 @@ export interface PostProcessingResults {
693690
export async function postProcessSarifFiles(
694691
logger: Logger,
695692
features: FeatureEnablement,
693+
getCodeQL: CodeQLGetter,
694+
tempPath: string,
696695
checkoutPath: string,
697696
sarifPaths: string[],
698697
category: string | undefined,
@@ -717,6 +716,8 @@ export async function postProcessSarifFiles(
717716
gitHubVersion,
718717
features,
719718
logger,
719+
getCodeQL,
720+
tempPath,
720721
);
721722
} else {
722723
const sarifPath = sarifPaths[0];
@@ -777,6 +778,8 @@ export async function writePostProcessedFiles(
777778
* to.
778779
*/
779780
export async function uploadFiles(
781+
tempDir: string,
782+
codeql: CodeQL,
780783
inputSarifPath: string,
781784
checkoutPath: string,
782785
category: string | undefined,
@@ -790,6 +793,8 @@ export async function uploadFiles(
790793
);
791794

792795
return uploadSpecifiedFiles(
796+
tempDir,
797+
codeql,
793798
sarifPaths,
794799
checkoutPath,
795800
category,
@@ -803,6 +808,8 @@ export async function uploadFiles(
803808
* Uploads the given array of SARIF files.
804809
*/
805810
async function uploadSpecifiedFiles(
811+
tempDir: string,
812+
codeql: CodeQL,
806813
sarifPaths: string[],
807814
checkoutPath: string,
808815
category: string | undefined,
@@ -813,6 +820,8 @@ async function uploadSpecifiedFiles(
813820
const processingResults: PostProcessingResults = await postProcessSarifFiles(
814821
logger,
815822
features,
823+
async () => codeql,
824+
tempDir,
816825
checkoutPath,
817826
sarifPaths,
818827
category,

src/upload-sarif-action.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import * as actionsUtil from "./actions-util";
44
import { getActionVersion, getTemporaryDirectory } from "./actions-util";
55
import * as analyses from "./analyses";
66
import { getGitHubVersion } from "./api-client";
7-
import { initFeatures } from "./feature-flags";
7+
import { CodeQL, getCodeQL } from "./codeql";
8+
import { Config, getConfig } from "./config-utils";
9+
import { FeatureEnablement, initFeatures } from "./feature-flags";
810
import { Logger, getActionsLogger } from "./logging";
911
import { getRepositoryNwo } from "./repository";
1012
import {
@@ -20,6 +22,7 @@ import * as upload_lib from "./upload-lib";
2022
import { postProcessAndUploadSarif } from "./upload-sarif";
2123
import {
2224
ConfigurationError,
25+
GitHubVersion,
2326
checkActionVersion,
2427
checkDiskUsage,
2528
getErrorMessage,
@@ -54,6 +57,35 @@ async function sendSuccessStatusReport(
5457
}
5558
}
5659

60+
/** The cached `CodeQL` instance, if any. */
61+
let codeql: CodeQL | undefined;
62+
63+
/** Get or initialise a `CodeQL` instance for use by the `upload-sarif` action. */
64+
async function getOrInitCodeQL(
65+
logger: Logger,
66+
gitHubVersion: GitHubVersion,
67+
features: FeatureEnablement,
68+
config: Config | undefined,
69+
): Promise<CodeQL> {
70+
// Return the cached instance, if we have one.
71+
if (codeql !== undefined) return codeql;
72+
73+
// If we have been able to load a `Config` from an earlier CodeQL Action step in the job,
74+
// then use the CodeQL executable that we have used previously. Otherwise, initialise the
75+
// CLI specifically for `upload-sarif`. Either way, we cache the instance.
76+
if (config !== undefined) {
77+
codeql = await getCodeQL(config.codeQLCmd);
78+
} else {
79+
codeql = await upload_lib.minimalInitCodeQL(
80+
logger,
81+
gitHubVersion,
82+
features,
83+
);
84+
}
85+
86+
return codeql;
87+
}
88+
5789
async function run(startedAt: Date) {
5890
// To capture errors appropriately, keep as much code within the try-catch as
5991
// possible, and only use safe functions outside.
@@ -94,9 +126,20 @@ async function run(startedAt: Date) {
94126
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
95127
const category = actionsUtil.getOptionalInput("category");
96128

129+
// Determine the temporary directory to use. If we are able to read a `Config` from a previous CodeQL Action
130+
// step in the job, then use the temporary directory configured there. Otherwise, use our default.
131+
let tempDir: string = actionsUtil.getTemporaryDirectory();
132+
133+
const config = await getConfig(tempDir, logger);
134+
if (config !== undefined) {
135+
tempDir = config.tempDir;
136+
}
137+
97138
const uploadResults = await postProcessAndUploadSarif(
98139
logger,
140+
tempDir,
99141
features,
142+
() => getOrInitCodeQL(logger, gitHubVersion, features, config),
100143
"always",
101144
checkoutPath,
102145
sarifPath,

src/upload-sarif.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import test, { ExecutionContext } from "ava";
55
import * as sinon from "sinon";
66

77
import { AnalysisKind, getAnalysisConfig } from "./analyses";
8+
import { getCodeQLForTesting } from "./codeql";
89
import { getRunnerLogger } from "./logging";
910
import { createFeatures, setupTests } from "./testing-utils";
1011
import { UploadResult } from "./upload-lib";
@@ -31,6 +32,8 @@ function mockPostProcessSarifFiles() {
3132
sinon.match.any,
3233
sinon.match.any,
3334
sinon.match.any,
35+
sinon.match.any,
36+
sinon.match.any,
3437
analysisConfig,
3538
)
3639
.resolves({ sarif: { runs: [] }, analysisKey: "", environment: "" });
@@ -73,7 +76,9 @@ const postProcessAndUploadSarifMacro = test.macro({
7376

7477
const actual = await postProcessAndUploadSarif(
7578
logger,
79+
tempDir,
7680
features,
81+
async () => getCodeQLForTesting(),
7782
"always",
7883
"",
7984
testPath,
@@ -90,6 +95,8 @@ const postProcessAndUploadSarifMacro = test.macro({
9095
postProcessSarifFiles.calledWith(
9196
logger,
9297
features,
98+
sinon.match.func,
99+
tempDir,
93100
sinon.match.any,
94101
analysisKindResult.expectedFiles?.map(toFullPath) ??
95102
fullSarifPaths,
@@ -221,7 +228,9 @@ test("postProcessAndUploadSarif doesn't upload if upload is disabled", async (t)
221228

222229
const actual = await postProcessAndUploadSarif(
223230
logger,
231+
tempDir,
224232
features,
233+
() => getCodeQLForTesting(),
225234
"never",
226235
"",
227236
tempDir,
@@ -248,7 +257,9 @@ test("postProcessAndUploadSarif writes post-processed SARIF files if output dire
248257
const postProcessedOutPath = path.join(tempDir, "post-processed");
249258
const actual = await postProcessAndUploadSarif(
250259
logger,
260+
tempDir,
251261
features,
262+
() => getCodeQLForTesting(),
252263
"never",
253264
"",
254265
tempDir,

0 commit comments

Comments
 (0)