Add the CliConfigFileEnabled feature flag

Also, wire it up to the `useCodeScanningConfigInCli` function.
This commit is contained in:
Andrew Eisenberg 2022-09-26 19:56:42 -07:00
parent 314ede696b
commit e37b0d6470
27 changed files with 236 additions and 40 deletions

View file

@ -245,6 +245,7 @@ async function run() {
logger,
featureFlags
);
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
runStats = await runQueries(
outputDir,
@ -253,7 +254,8 @@ async function run() {
threads,
actionsUtil.getOptionalInput("category"),
config,
logger
logger,
featureFlags
);
}

View file

@ -14,6 +14,7 @@ import {
import { setCodeQL } from "./codeql";
import { Config } from "./config-utils";
import * as count from "./count-loc";
import { createFeatureFlags } from "./feature-flags";
import { Language } from "./languages";
import { getRunnerLogger } from "./logging";
import { setupTests, setupActionsVars } from "./testing-utils";
@ -138,7 +139,8 @@ test("status report fields and search path setting", async (t) => {
threadsFlag,
undefined,
config,
getRunnerLogger(true)
getRunnerLogger(true),
createFeatureFlags([])
);
const hasPacks = language in packs;
const statusReportKeys = Object.keys(builtinStatusReport).sort();
@ -187,7 +189,8 @@ test("status report fields and search path setting", async (t) => {
threadsFlag,
undefined,
config,
getRunnerLogger(true)
getRunnerLogger(true),
createFeatureFlags([])
);
t.deepEqual(Object.keys(customStatusReport).length, 2);
t.true(

View file

@ -213,7 +213,8 @@ export async function runQueries(
threadsFlag: string,
automationDetailsId: string | undefined,
config: configUtils.Config,
logger: Logger
logger: Logger,
featureFlags: FeatureFlags
): Promise<QueriesStatusReport> {
const statusReport: QueriesStatusReport = {};
@ -256,7 +257,7 @@ export async function runQueries(
}
try {
if (await util.useCodeScanningConfigInCli(codeql)) {
if (await util.useCodeScanningConfigInCli(codeql, featureFlags)) {
// If we are using the codescanning config in the CLI,
// much of the work needed to generate the query suites
// is done in the CLI. We just need to make a single

View file

@ -819,7 +819,11 @@ async function getCodeQLForCmd(
}
}
const configLocation = await generateCodescanningConfig(codeql, config);
const configLocation = await generateCodescanningConfig(
codeql,
config,
featureFlags
);
if (configLocation) {
extraArgs.push(`--codescanning-config=${configLocation}`);
}
@ -1269,9 +1273,10 @@ async function runTool(cmd: string, args: string[] = []) {
*/
async function generateCodescanningConfig(
codeql: CodeQL,
config: Config
config: Config,
featureFlags: FeatureFlags
): Promise<string | undefined> {
if (!(await util.useCodeScanningConfigInCli(codeql))) {
if (!(await util.useCodeScanningConfigInCli(codeql, featureFlags))) {
return;
}
const configLocation = path.resolve(config.tempDir, "user-config.yaml");

View file

@ -1704,7 +1704,7 @@ export async function initConfig(
// When using the codescanning config in the CLI, pack downloads
// happen in the CLI during the `database init` command, so no need
// to download them here.
if (!(await useCodeScanningConfigInCli(codeQL))) {
if (!(await useCodeScanningConfigInCli(codeQL, featureFlags))) {
const registries = parseRegistries(registriesInput);
await downloadPacks(
codeQL,

View file

@ -12,6 +12,7 @@ export enum FeatureFlag {
MlPoweredQueriesEnabled = "ml_powered_queries_enabled",
TrapCachingEnabled = "trap_caching_enabled",
GolangExtractionReconciliationEnabled = "golang_extraction_reconciliation_enabled",
CliConfigFileEnabled = "cli_config_file_enabled",
}
/**

View file

@ -517,7 +517,8 @@ program
threads,
cmd.category,
config,
logger
logger,
createFeatureFlags([])
);
if (!cmd.upload) {

View file

@ -9,7 +9,9 @@ import test, { ExecutionContext } from "ava";
import * as sinon from "sinon";
import * as api from "./api-client";
import { CodeQL } from "./codeql";
import { Config } from "./config-utils";
import { createFeatureFlags, FeatureFlag } from "./feature-flags";
import { getRunnerLogger, Logger } from "./logging";
import { setupTests } from "./testing-utils";
import * as util from "./util";
@ -492,3 +494,111 @@ test("listFolder", async (t) => {
]);
});
});
test("useCodeScanningConfigInCli with no env var", async (t) => {
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
))
);
// Yay! It works!
t.assert(
await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
)
);
});
for (const val of ["TRUE", "true", "True"]) {
test(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
))
);
// Yay! It works!
t.assert(
await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
)
);
t.assert(
await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([])
)
);
});
}
for (const val of ["FALSE", "false", "False"]) {
test(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
// Never turned on when env var is false
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = "false";
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.0"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
))
);
t.assert(
!(await util.useCodeScanningConfigInCli(
mockVersion("2.10.1"),
createFeatureFlags([])
))
);
});
}
function mockVersion(version) {
return {
async getVersion() {
return version;
},
} as CodeQL;
}

View file

@ -489,7 +489,7 @@ export enum Mode {
* CLI. These environment variables are relevant for both the runner
* and the action.
*/
enum EnvVar {
export enum EnvVar {
/**
* The mode of the codeql-action, either 'actions' or 'runner'.
*/
@ -593,6 +593,10 @@ export function getRequiredEnvParam(paramName: string): string {
return value;
}
function getOptionalEnvParam(paramName: string): string {
return process.env[paramName] || "";
}
export class HTTPError extends Error {
public status: number;
@ -789,12 +793,28 @@ export function isInTestMode(): boolean {
* that gets passed to the CLI.
*/
export async function useCodeScanningConfigInCli(
codeql: CodeQL
codeql: CodeQL,
featureFlags: FeatureFlags
): Promise<boolean> {
return (
process.env[EnvVar.CODEQL_PASS_CONFIG_TO_CLI] === "true" &&
(await codeQlVersionAbove(codeql, CODEQL_VERSION_CONFIG_FILES))
);
const envVarIsEnabled = getOptionalEnvParam(EnvVar.CODEQL_PASS_CONFIG_TO_CLI);
// If the user has explicitly turned off the feature, then don't use it.
if (envVarIsEnabled.toLocaleLowerCase() === "false") {
return false;
}
// If the user has explicitly turned on the feature, then use it.
// Or if the feature flag is enabled, then use it.
const isEnabled =
envVarIsEnabled.toLocaleLowerCase() === "true" ||
(await featureFlags.getValue(FeatureFlag.CliConfigFileEnabled));
if (!isEnabled) {
return false;
}
// If the CLI version is too old, then don't use it.
return await codeQlVersionAbove(codeql, CODEQL_VERSION_CONFIG_FILES);
}
/*