mirror of
https://github.com/github/codeql-action.git
synced 2026-04-17 04:23:16 +00:00
Prefer providing CodeQL via dependency injection
This commit is contained in:
@@ -71,8 +71,10 @@ test("analyze action with RAM & threads from environment variables", async (t) =
|
||||
// wait for the action promise to complete before starting verification.
|
||||
await analyzeAction.runPromise;
|
||||
|
||||
t.assert(runFinalizeStub.calledOnce);
|
||||
t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1");
|
||||
t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=4992");
|
||||
t.assert(runQueriesStub.calledOnce);
|
||||
t.deepEqual(runQueriesStub.firstCall.args[3], "--threads=-1");
|
||||
t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=4992");
|
||||
});
|
||||
|
||||
@@ -71,8 +71,10 @@ test("analyze action with RAM & threads from action inputs", async (t) => {
|
||||
// wait for the action promise to complete before starting verification.
|
||||
await analyzeAction.runPromise;
|
||||
|
||||
t.assert(runFinalizeStub.calledOnce);
|
||||
t.deepEqual(runFinalizeStub.firstCall.args[1], "--threads=-1");
|
||||
t.deepEqual(runFinalizeStub.firstCall.args[2], "--ram=3012");
|
||||
t.assert(runQueriesStub.calledOnce);
|
||||
t.deepEqual(runQueriesStub.firstCall.args[3], "--threads=-1");
|
||||
t.deepEqual(runQueriesStub.firstCall.args[1], "--ram=3012");
|
||||
});
|
||||
|
||||
@@ -308,6 +308,7 @@ async function run() {
|
||||
threads,
|
||||
diffRangePackDir,
|
||||
actionsUtil.getOptionalInput("category"),
|
||||
codeql,
|
||||
config,
|
||||
logger,
|
||||
features,
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
defaultSuites,
|
||||
resolveQuerySuiteAlias,
|
||||
} from "./analyze";
|
||||
import { setCodeQL } from "./codeql";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
@@ -42,7 +42,7 @@ test("status report fields", async (t) => {
|
||||
sinon.stub(uploadLib, "validateSarifFileSchema");
|
||||
|
||||
for (const language of Object.values(KnownLanguage)) {
|
||||
setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
databaseRunQueries: async () => {},
|
||||
packDownload: async () => ({ packs: [] }),
|
||||
databaseInterpretResults: async (
|
||||
@@ -108,6 +108,7 @@ test("status report fields", async (t) => {
|
||||
threadsFlag,
|
||||
undefined,
|
||||
undefined,
|
||||
codeql,
|
||||
config,
|
||||
getRunnerLogger(true),
|
||||
createFeatures([Feature.QaTelemetryEnabled]),
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "./actions-util";
|
||||
import { getApiClient } from "./api-client";
|
||||
import { setupCppAutobuild } from "./autobuild";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import { type CodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { getJavaTempDependencyDir } from "./dependency-caching";
|
||||
import { addDiagnostic, makeDiagnostic } from "./diagnostics";
|
||||
@@ -614,6 +614,7 @@ export async function runQueries(
|
||||
threadsFlag: string,
|
||||
diffRangePackDir: string | undefined,
|
||||
automationDetailsId: string | undefined,
|
||||
codeql: CodeQL,
|
||||
config: configUtils.Config,
|
||||
logger: Logger,
|
||||
features: FeatureEnablement,
|
||||
@@ -655,8 +656,6 @@ export async function runQueries(
|
||||
? `--sarif-run-property=incrementalMode=${incrementalMode.join(",")}`
|
||||
: undefined;
|
||||
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
|
||||
for (const language of config.languages) {
|
||||
try {
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
|
||||
@@ -285,7 +285,6 @@ interface PackDownloadItem {
|
||||
|
||||
/**
|
||||
* Stores the CodeQL object, and is populated by `setupCodeQL` or `getCodeQL`.
|
||||
* Can be overridden in tests using `setCodeQL`.
|
||||
*/
|
||||
let cachedCodeQL: CodeQL | undefined = undefined;
|
||||
|
||||
@@ -424,6 +423,17 @@ export async function getCodeQL(cmd: string): Promise<CodeQL> {
|
||||
return cachedCodeQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the CodeQL object. Only for use in tests that cannot override
|
||||
* CodeQL via dependency injection.
|
||||
*
|
||||
* Accepts a partial object. Any undefined methods will be implemented
|
||||
* to immediately throw an exception indicating which method is missing.
|
||||
*/
|
||||
export function setCodeQL(codeql: Partial<CodeQL>): void {
|
||||
cachedCodeQL = createStubCodeQL(codeql);
|
||||
}
|
||||
|
||||
function resolveFunction<T>(
|
||||
partialCodeql: Partial<CodeQL>,
|
||||
methodName: string,
|
||||
@@ -442,13 +452,13 @@ function resolveFunction<T>(
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the functionality for CodeQL methods. Only for use in tests.
|
||||
* Creates a stub CodeQL object. Only for use in tests.
|
||||
*
|
||||
* Accepts a partial object and any undefined methods will be implemented
|
||||
* Accepts a partial object. Any undefined methods will be implemented
|
||||
* to immediately throw an exception indicating which method is missing.
|
||||
*/
|
||||
export function setCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
cachedCodeQL = {
|
||||
export function createStubCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
return {
|
||||
getPath: resolveFunction(partialCodeql, "getPath", () => "/tmp/dummy-path"),
|
||||
getVersion: resolveFunction(partialCodeql, "getVersion", async () => ({
|
||||
version: "1.0.0",
|
||||
@@ -509,21 +519,6 @@ export function setCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
resolveExtractor: resolveFunction(partialCodeql, "resolveExtractor"),
|
||||
mergeResults: resolveFunction(partialCodeql, "mergeResults"),
|
||||
};
|
||||
return cachedCodeQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cached CodeQL object. Should only be used from tests.
|
||||
*
|
||||
* TODO: Work out a good way for tests to get this from the test context
|
||||
* instead of having to have this method.
|
||||
*/
|
||||
export function getCachedCodeQL(): CodeQL {
|
||||
if (cachedCodeQL === undefined) {
|
||||
// Should never happen as setCodeQL is called by testing-utils.setupTests
|
||||
throw new Error("cachedCodeQL undefined");
|
||||
}
|
||||
return cachedCodeQL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,12 +9,7 @@ import * as sinon from "sinon";
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import * as api from "./api-client";
|
||||
import { CachingKind } from "./caching-utils";
|
||||
import {
|
||||
CodeQL,
|
||||
getCachedCodeQL,
|
||||
PackDownloadOutput,
|
||||
setCodeQL,
|
||||
} from "./codeql";
|
||||
import { PackDownloadOutput, createStubCodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { Feature } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
@@ -64,7 +59,15 @@ function createTestInitConfigInputs(
|
||||
debugDatabaseName: "",
|
||||
repository: { owner: "github", repo: "example" },
|
||||
tempDir: "",
|
||||
codeql: {} as CodeQL,
|
||||
codeql: createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
javascript: [{ extractor_root: "" }],
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
workspacePath: "",
|
||||
sourceRoot: "",
|
||||
githubVersion,
|
||||
@@ -127,7 +130,7 @@ test("load empty config", async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const languages = "javascript,python";
|
||||
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
@@ -179,7 +182,7 @@ test("loading config saves config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
@@ -240,7 +243,6 @@ test("load input outside of workspace", async (t) => {
|
||||
createTestInitConfigInputs({
|
||||
configFile: "../input",
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -268,7 +270,6 @@ test("load non-local input with invalid repo syntax", async (t) => {
|
||||
createTestInitConfigInputs({
|
||||
configFile,
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -298,7 +299,6 @@ test("load non-existent input", async (t) => {
|
||||
languagesInput,
|
||||
configFile,
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -318,7 +318,7 @@ test("load non-existent input", async (t) => {
|
||||
|
||||
test("load non-empty input", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
@@ -449,7 +449,7 @@ test("Using config input and file together, config input should be used.", async
|
||||
queries: string[];
|
||||
extraSearchPath: string | undefined;
|
||||
}> = [];
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
@@ -490,7 +490,7 @@ test("Using config input and file together, config input should be used.", async
|
||||
|
||||
test("API client used when reading remote config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async betterResolveLanguages() {
|
||||
return {
|
||||
extractors: {
|
||||
@@ -561,7 +561,6 @@ test("Remote config handles the case where a directory is provided", async (t) =
|
||||
createTestInitConfigInputs({
|
||||
configFile: repoReference,
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -590,7 +589,6 @@ test("Invalid format of remote config handled correctly", async (t) => {
|
||||
createTestInitConfigInputs({
|
||||
configFile: repoReference,
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -609,7 +607,7 @@ test("Invalid format of remote config handled correctly", async (t) => {
|
||||
test("No detected languages", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
mockListLanguages([]);
|
||||
const codeql = setCodeQL({
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
return {};
|
||||
},
|
||||
@@ -645,7 +643,6 @@ test("Unknown languages", async (t) => {
|
||||
createTestInitConfigInputs({
|
||||
languagesInput,
|
||||
tempDir,
|
||||
codeql: getCachedCodeQL(),
|
||||
workspacePath: tempDir,
|
||||
}),
|
||||
);
|
||||
@@ -1134,7 +1131,7 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
|
||||
const stubExtractorEntry = {
|
||||
extractor_root: "",
|
||||
};
|
||||
const codeQL = setCodeQL({
|
||||
const codeQL = createStubCodeQL({
|
||||
betterResolveLanguages: () =>
|
||||
Promise.resolve({
|
||||
aliases: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as sinon from "sinon";
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { GitHubApiDetails } from "./api-client";
|
||||
import * as apiClient from "./api-client";
|
||||
import { setCodeQL } from "./codeql";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import { uploadDatabases } from "./database-upload";
|
||||
import * as gitUtils from "./git-utils";
|
||||
@@ -70,7 +70,7 @@ async function mockHttpRequests(databaseUploadStatusCode: number) {
|
||||
}
|
||||
|
||||
function getCodeQL() {
|
||||
return setCodeQL({
|
||||
return createStubCodeQL({
|
||||
async databaseBundle(_: string, outputFilePath: string) {
|
||||
fs.writeFileSync(outputFilePath, "");
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ import del from "del";
|
||||
|
||||
import { getOptionalInput, getTemporaryDirectory } from "./actions-util";
|
||||
import { dbIsFinalized } from "./analyze";
|
||||
import { getCodeQL } from "./codeql";
|
||||
import { type CodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Language } from "./languages";
|
||||
@@ -134,6 +134,7 @@ function tryPrepareSarifDebugArtifact(
|
||||
* @return The path to the database bundle, or undefined if an error occurs.
|
||||
*/
|
||||
async function tryBundleDatabase(
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
language: Language,
|
||||
logger: Logger,
|
||||
@@ -141,7 +142,7 @@ async function tryBundleDatabase(
|
||||
try {
|
||||
if (dbIsFinalized(config, language, logger)) {
|
||||
try {
|
||||
return await createDatabaseBundleCli(config, language);
|
||||
return await createDatabaseBundleCli(codeql, config, language);
|
||||
} catch (e) {
|
||||
logger.warning(
|
||||
`Failed to bundle database for ${language} using the CLI. ` +
|
||||
@@ -166,6 +167,7 @@ async function tryBundleDatabase(
|
||||
* Logs and suppresses any errors that occur.
|
||||
*/
|
||||
export async function tryUploadAllAvailableDebugArtifacts(
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
logger: Logger,
|
||||
codeQlVersion: string | undefined,
|
||||
@@ -207,6 +209,7 @@ export async function tryUploadAllAvailableDebugArtifacts(
|
||||
// Add database bundle
|
||||
logger.info("Preparing database bundle debug artifact...");
|
||||
const databaseBundle = await tryBundleDatabase(
|
||||
codeql,
|
||||
config,
|
||||
language,
|
||||
logger,
|
||||
@@ -369,13 +372,14 @@ async function createPartialDatabaseBundle(
|
||||
* Runs `codeql database bundle` command and returns the path.
|
||||
*/
|
||||
async function createDatabaseBundleCli(
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
language: Language,
|
||||
): Promise<string> {
|
||||
const databaseBundlePath = await bundleDb(
|
||||
config,
|
||||
language,
|
||||
await getCodeQL(config.codeQLCmd),
|
||||
codeql,
|
||||
`${config.debugDatabaseName}-${language}`,
|
||||
);
|
||||
return databaseBundlePath;
|
||||
|
||||
@@ -41,6 +41,7 @@ test("post: init action with debug mode off", async (t) => {
|
||||
await initActionPostHelper.run(
|
||||
uploadAllAvailableDebugArtifactsSpy,
|
||||
printDebugLogsSpy,
|
||||
codeql.createStubCodeQL({}),
|
||||
createTestConfig({ debugMode: false }),
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([]),
|
||||
@@ -63,6 +64,7 @@ test("post: init action with debug mode on", async (t) => {
|
||||
await initActionPostHelper.run(
|
||||
uploadAllAvailableDebugArtifactsSpy,
|
||||
printDebugLogsSpy,
|
||||
codeql.createStubCodeQL({}),
|
||||
createTestConfig({ debugMode: true }),
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([]),
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as github from "@actions/github";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { getApiClient } from "./api-client";
|
||||
import { getCodeQL } from "./codeql";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import { Config } from "./config-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||
@@ -160,11 +160,13 @@ export async function tryUploadSarifIfRunFailed(
|
||||
|
||||
export async function run(
|
||||
uploadAllAvailableDebugArtifacts: (
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
logger: Logger,
|
||||
codeQlVersion: string,
|
||||
) => Promise<void>,
|
||||
printDebugLogs: (config: Config) => Promise<void>,
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
repositoryNwo: RepositoryNwo,
|
||||
features: FeatureEnablement,
|
||||
@@ -212,9 +214,13 @@ export async function run(
|
||||
logger.info(
|
||||
"Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...",
|
||||
);
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
const version = await codeql.getVersion();
|
||||
await uploadAllAvailableDebugArtifacts(config, logger, version.version);
|
||||
await uploadAllAvailableDebugArtifacts(
|
||||
codeql,
|
||||
config,
|
||||
logger,
|
||||
version.version,
|
||||
);
|
||||
await printDebugLogs(config);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
printDebugLogs,
|
||||
} from "./actions-util";
|
||||
import { getGitHubVersion } from "./api-client";
|
||||
import { getCodeQL } from "./codeql";
|
||||
import { Config, getConfig } from "./config-utils";
|
||||
import * as debugArtifacts from "./debug-artifacts";
|
||||
import { Features } from "./feature-flags";
|
||||
@@ -61,9 +62,12 @@ async function runWrapper() {
|
||||
"Debugging artifacts are unavailable since the 'init' Action failed before it could produce any.",
|
||||
);
|
||||
} else {
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
|
||||
uploadFailedSarifResult = await initActionPostHelper.run(
|
||||
debugArtifacts.tryUploadAllAvailableDebugArtifacts,
|
||||
printDebugLogs,
|
||||
codeql,
|
||||
config,
|
||||
repositoryNwo,
|
||||
features,
|
||||
|
||||
@@ -263,7 +263,7 @@ export function mockCodeQLVersion(
|
||||
version: string,
|
||||
features?: { [name: string]: boolean },
|
||||
) {
|
||||
return codeql.setCodeQL({
|
||||
return codeql.createStubCodeQL({
|
||||
async getVersion() {
|
||||
return makeVersionInfo(version, features);
|
||||
},
|
||||
|
||||
@@ -8,9 +8,9 @@ import * as sinon from "sinon";
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import * as apiClient from "./api-client";
|
||||
import {
|
||||
setCodeQL,
|
||||
getTrapCachingExtractorConfigArgs,
|
||||
getTrapCachingExtractorConfigArgsForLang,
|
||||
createStubCodeQL,
|
||||
} from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { Feature } from "./feature-flags";
|
||||
@@ -34,7 +34,7 @@ import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
const stubCodeql = setCodeQL({
|
||||
const stubCodeql = createStubCodeQL({
|
||||
async getVersion() {
|
||||
return makeVersionInfo("2.10.3");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user