Rename featureEnablement to features

This is more succinct and removes a few line breaks
This commit is contained in:
Henry Mercer 2023-03-09 16:46:51 +00:00
parent fc1366f6ec
commit 485cc11a24
21 changed files with 160 additions and 174 deletions

8
lib/analyze.js generated
View file

@ -123,17 +123,17 @@ async function finalizeDatabaseCreation(config, threadsFlag, memoryFlag, logger)
}; };
} }
// Runs queries and creates sarif files in the given folder // Runs queries and creates sarif files in the given folder
async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, automationDetailsId, config, logger, featureEnablement) { async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, automationDetailsId, config, logger, features) {
const statusReport = {}; const statusReport = {};
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd); const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
const queryFlags = [memoryFlag, threadsFlag]; const queryFlags = [memoryFlag, threadsFlag];
await util.logCodeScanningConfigInCli(codeql, featureEnablement, logger); await util.logCodeScanningConfigInCli(codeql, features, logger);
for (const language of config.languages) { for (const language of config.languages) {
const queries = config.queries[language]; const queries = config.queries[language];
const queryFilters = validateQueryFilters(config.originalUserInput["query-filters"]); const queryFilters = validateQueryFilters(config.originalUserInput["query-filters"]);
const packsWithVersion = config.packs[language] || []; const packsWithVersion = config.packs[language] || [];
try { try {
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await util.useCodeScanningConfigInCli(codeql, features)) {
// If we are using the code scanning config in the CLI, // If we are using the code scanning config in the CLI,
// much of the work needed to generate the query suites // much of the work needed to generate the query suites
// is done in the CLI. We just need to make a single // is done in the CLI. We just need to make a single
@ -218,7 +218,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
return statusReport; return statusReport;
async function runInterpretResults(language, queries, sarifFile, enableDebugLogging) { async function runInterpretResults(language, queries, sarifFile, enableDebugLogging) {
const databasePath = util.getCodeQLDatabasePath(config, language); const databasePath = util.getCodeQLDatabasePath(config, language);
return await codeql.databaseInterpretResults(databasePath, queries, sarifFile, addSnippetsFlag, threadsFlag, enableDebugLogging ? "-vv" : "-v", automationDetailsId, config, featureEnablement); return await codeql.databaseInterpretResults(databasePath, queries, sarifFile, addSnippetsFlag, threadsFlag, enableDebugLogging ? "-vv" : "-v", automationDetailsId, config, features);
} }
async function runPrintLinesOfCode(language) { async function runPrintLinesOfCode(language) {
const databasePath = util.getCodeQLDatabasePath(config, language); const databasePath = util.getCodeQLDatabasePath(config, language);

File diff suppressed because one or more lines are too long

8
lib/codeql.js generated
View file

@ -313,7 +313,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...getExtraOptionsFromEnv(["database", "init"]), ...getExtraOptionsFromEnv(["database", "init"]),
]); ]);
}, },
async databaseInitCluster(config, sourceRoot, processName, featureEnablement, qlconfigFile, logger) { async databaseInitCluster(config, sourceRoot, processName, features, qlconfigFile, logger) {
const extraArgs = config.languages.map((language) => `--language=${language}`); const extraArgs = config.languages.map((language) => `--language=${language}`);
if (config.languages.filter((l) => (0, languages_1.isTracedLanguage)(l)).length > 0) { if (config.languages.filter((l) => (0, languages_1.isTracedLanguage)(l)).length > 0) {
extraArgs.push("--begin-tracing"); extraArgs.push("--begin-tracing");
@ -332,7 +332,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
} }
} }
// A code scanning config file is only generated if the CliConfigFileEnabled feature flag is enabled. // A code scanning config file is only generated if the CliConfigFileEnabled feature flag is enabled.
const codeScanningConfigFile = await generateCodeScanningConfig(codeql, config, featureEnablement, logger); const codeScanningConfigFile = await generateCodeScanningConfig(codeql, config, features, logger);
// Only pass external repository token if a config file is going to be parsed by the CLI. // Only pass external repository token if a config file is going to be parsed by the CLI.
let externalRepositoryToken; let externalRepositoryToken;
if (codeScanningConfigFile) { if (codeScanningConfigFile) {
@ -731,8 +731,8 @@ async function runTool(cmd, args = [], opts = {}) {
* @param config The configuration to use. * @param config The configuration to use.
* @returns the path to the generated user configuration file. * @returns the path to the generated user configuration file.
*/ */
async function generateCodeScanningConfig(codeql, config, featureEnablement, logger) { async function generateCodeScanningConfig(codeql, config, features, logger) {
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) { if (!(await util.useCodeScanningConfigInCli(codeql, features))) {
return; return;
} }
const codeScanningConfigFile = (0, config_utils_1.getGeneratedCodeScanningConfigPath)(config); const codeScanningConfigFile = (0, config_utils_1.getGeneratedCodeScanningConfigPath)(config);

File diff suppressed because one or more lines are too long

34
lib/config-utils.js generated
View file

@ -141,7 +141,7 @@ const builtinSuites = [
* Throws an error if suiteName is not a valid builtin suite. * Throws an error if suiteName is not a valid builtin suite.
* May inject ML queries, and the return value will declare if this was done. * May inject ML queries, and the return value will declare if this was done.
*/ */
async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suiteName, featureEnablement, configFile) { async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suiteName, features, configFile) {
let injectedMlQueries = false; let injectedMlQueries = false;
const found = builtinSuites.find((suite) => suite === suiteName); const found = builtinSuites.find((suite) => suite === suiteName);
if (!found) { if (!found) {
@ -165,7 +165,7 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
found === "security-extended" || found === "security-extended" ||
found === "security-and-quality") && found === "security-and-quality") &&
!packs.javascript?.some(isMlPoweredJsQueriesPack) && !packs.javascript?.some(isMlPoweredJsQueriesPack) &&
(await featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, codeQL))) { (await features.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, codeQL))) {
if (!packs.javascript) { if (!packs.javascript) {
packs.javascript = []; packs.javascript = [];
} }
@ -240,7 +240,7 @@ async function addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetail
* *
* @returns whether or not we injected ML queries into the packs * @returns whether or not we injected ML queries into the packs
*/ */
async function parseQueryUses(languages, codeQL, resultMap, packs, queryUses, tempDir, workspacePath, apiDetails, featureEnablement, logger, configFile) { async function parseQueryUses(languages, codeQL, resultMap, packs, queryUses, tempDir, workspacePath, apiDetails, features, logger, configFile) {
queryUses = queryUses.trim(); queryUses = queryUses.trim();
if (queryUses === "") { if (queryUses === "") {
throw new Error(getQueryUsesInvalid(configFile)); throw new Error(getQueryUsesInvalid(configFile));
@ -252,12 +252,12 @@ async function parseQueryUses(languages, codeQL, resultMap, packs, queryUses, te
} }
// Check for one of the builtin suites // Check for one of the builtin suites
if (queryUses.indexOf("/") === -1 && queryUses.indexOf("@") === -1) { if (queryUses.indexOf("/") === -1 && queryUses.indexOf("@") === -1) {
return await addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, queryUses, featureEnablement, configFile); return await addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, queryUses, features, configFile);
} }
// Otherwise, must be a reference to another repo. // Otherwise, must be a reference to another repo.
// If config parsing is handled in CLI, then this repo will be downloaded // If config parsing is handled in CLI, then this repo will be downloaded
// later by the CLI. // later by the CLI.
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) { if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, features))) {
await addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetails, logger, configFile); await addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetails, logger, configFile);
} }
return false; return false;
@ -503,13 +503,13 @@ async function getRawLanguages(languagesInput, repository, logger) {
return { rawLanguages, autodetected }; return { rawLanguages, autodetected };
} }
exports.getRawLanguages = getRawLanguages; exports.getRawLanguages = getRawLanguages;
async function addQueriesAndPacksFromWorkflow(codeQL, queriesInput, languages, resultMap, packs, tempDir, workspacePath, apiDetails, featureEnablement, logger) { async function addQueriesAndPacksFromWorkflow(codeQL, queriesInput, languages, resultMap, packs, tempDir, workspacePath, apiDetails, features, logger) {
let injectedMlQueries = false; let injectedMlQueries = false;
queriesInput = queriesInput.trim(); queriesInput = queriesInput.trim();
// "+" means "don't override config file" - see shouldAddConfigFileQueries // "+" means "don't override config file" - see shouldAddConfigFileQueries
queriesInput = queriesInput.replace(/^\+/, ""); queriesInput = queriesInput.replace(/^\+/, "");
for (const query of queriesInput.split(",")) { for (const query of queriesInput.split(",")) {
const didInject = await parseQueryUses(languages, codeQL, resultMap, packs, query, tempDir, workspacePath, apiDetails, featureEnablement, logger); const didInject = await parseQueryUses(languages, codeQL, resultMap, packs, query, tempDir, workspacePath, apiDetails, features, logger);
injectedMlQueries = injectedMlQueries || didInject; injectedMlQueries = injectedMlQueries || didInject;
} }
return injectedMlQueries; return injectedMlQueries;
@ -527,7 +527,7 @@ function shouldAddConfigFileQueries(queriesInput) {
/** /**
* Get the default config for when the user has not supplied one. * Get the default config for when the user has not supplied one.
*/ */
async function getDefaultConfig(languagesInput, rawQueriesInput, rawPacksInput, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger) { async function getDefaultConfig(languagesInput, rawQueriesInput, rawPacksInput, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger) {
const languages = await getLanguages(codeQL, languagesInput, repository, logger); const languages = await getLanguages(codeQL, languagesInput, repository, logger);
const queries = {}; const queries = {};
for (const language of languages) { for (const language of languages) {
@ -545,7 +545,7 @@ async function getDefaultConfig(languagesInput, rawQueriesInput, rawPacksInput,
: {}; : {};
if (rawQueriesInput) { if (rawQueriesInput) {
augmentationProperties.injectedMlQueries = augmentationProperties.injectedMlQueries =
await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureEnablement, logger); await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, features, logger);
} }
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logger); const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logger);
return { return {
@ -581,7 +581,7 @@ async function downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logg
/** /**
* Load the config from the given file. * Load the config from the given file.
*/ */
async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger) { async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger) {
let parsedYAML; let parsedYAML;
if (isLocal(configFile)) { if (isLocal(configFile)) {
// Treat the config file as relative to the workspace // Treat the config file as relative to the workspace
@ -629,7 +629,7 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
// in the config file. // in the config file.
if (rawQueriesInput) { if (rawQueriesInput) {
augmentationProperties.injectedMlQueries = augmentationProperties.injectedMlQueries =
await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureEnablement, logger); await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, features, logger);
} }
if (shouldAddConfigFileQueries(rawQueriesInput) && if (shouldAddConfigFileQueries(rawQueriesInput) &&
QUERIES_PROPERTY in parsedYAML) { QUERIES_PROPERTY in parsedYAML) {
@ -641,7 +641,7 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
if (typeof query[QUERIES_USES_PROPERTY] !== "string") { if (typeof query[QUERIES_USES_PROPERTY] !== "string") {
throw new Error(getQueriesMissingUses(configFile)); throw new Error(getQueriesMissingUses(configFile));
} }
await parseQueryUses(languages, codeQL, queries, packs, query[QUERIES_USES_PROPERTY], tempDir, workspacePath, apiDetails, featureEnablement, logger, configFile); await parseQueryUses(languages, codeQL, queries, packs, query[QUERIES_USES_PROPERTY], tempDir, workspacePath, apiDetails, features, logger, configFile);
} }
} }
if (PATHS_IGNORE_PROPERTY in parsedYAML) { if (PATHS_IGNORE_PROPERTY in parsedYAML) {
@ -932,21 +932,21 @@ function dbLocationOrDefault(dbLocation, tempDir) {
* This will parse the config from the user input if present, or generate * This will parse the config from the user input if present, or generate
* a default config. The parsed config is then stored to a known location. * a default config. The parsed config is then stored to a known location.
*/ */
async function initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger) { async function initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger) {
let config; let config;
// If no config file was provided create an empty one // If no config file was provided create an empty one
if (!configFile) { if (!configFile) {
logger.debug("No configuration file was provided"); logger.debug("No configuration file was provided");
config = await getDefaultConfig(languagesInput, queriesInput, packsInput, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger); config = await getDefaultConfig(languagesInput, queriesInput, packsInput, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger);
} }
else { else {
config = await loadConfig(languagesInput, queriesInput, packsInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger); config = await loadConfig(languagesInput, queriesInput, packsInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger);
} }
// When using the codescanning config in the CLI, pack downloads // When using the codescanning config in the CLI, pack downloads
// happen in the CLI during the `database init` command, so no need // happen in the CLI during the `database init` command, so no need
// to download them here. // to download them here.
await (0, util_1.logCodeScanningConfigInCli)(codeQL, featureEnablement, logger); await (0, util_1.logCodeScanningConfigInCli)(codeQL, features, logger);
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) { if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, features))) {
// The list of queries should not be empty for any language. If it is then // The list of queries should not be empty for any language. If it is then
// it is a user configuration error. // it is a user configuration error.
// This check occurs in the CLI when it parses the config file. // This check occurs in the CLI when it parses the config file.

File diff suppressed because one or more lines are too long

6
lib/feature-flags.js generated
View file

@ -188,12 +188,12 @@ class GitHubFeatureFlags {
this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`); this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`);
return false; return false;
} }
const featureEnablement = response[feature]; const features = response[feature];
if (featureEnablement === undefined) { if (features === undefined) {
this.logger.debug(`Feature '${feature}' undefined in API response, considering it disabled.`); this.logger.debug(`Feature '${feature}' undefined in API response, considering it disabled.`);
return false; return false;
} }
return !!featureEnablement; return !!features;
} }
async getAllFeatures() { async getAllFeatures() {
// if we have an in memory cache, use that // if we have an in memory cache, use that

File diff suppressed because one or more lines are too long

View file

@ -51,9 +51,9 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
(0, ava_1.default)(`All features are disabled if running against ${variant.description}`, async (t) => { (0, ava_1.default)(`All features are disabled if running against ${variant.description}`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion); const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion);
for (const feature of Object.values(feature_flags_1.Feature)) { for (const feature of Object.values(feature_flags_1.Feature)) {
t.false(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))); t.false(await features.getValue(feature, includeCodeQlIfRequired(feature)));
} }
t.assert(loggedMessages.find((v) => v.type === "debug" && t.assert(loggedMessages.find((v) => v.type === "debug" &&
v.message === v.message ===
@ -64,10 +64,11 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
(0, ava_1.default)("API response missing", async (t) => { (0, ava_1.default)("API response missing", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages)); const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {}); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
for (const feature of Object.values(feature_flags_1.Feature)) { for (const feature of Object.values(feature_flags_1.Feature)) {
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false); t.assert((await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
false);
} }
assertAllFeaturesUndefinedInApi(t, loggedMessages); assertAllFeaturesUndefinedInApi(t, loggedMessages);
}); });
@ -75,19 +76,20 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
(0, ava_1.default)("Features are disabled if they're not returned in API response", async (t) => { (0, ava_1.default)("Features are disabled if they're not returned in API response", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages)); const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {}); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
for (const feature of Object.values(feature_flags_1.Feature)) { for (const feature of Object.values(feature_flags_1.Feature)) {
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false); t.assert((await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
false);
} }
assertAllFeaturesUndefinedInApi(t, loggedMessages); assertAllFeaturesUndefinedInApi(t, loggedMessages);
}); });
}); });
(0, ava_1.default)("Feature flags exception is propagated if the API request errors", async (t) => { (0, ava_1.default)("Feature flags exception is propagated if the API request errors", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {}); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {});
await t.throwsAsync(async () => featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.MlPoweredQueriesEnabled)), { await t.throwsAsync(async () => features.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.MlPoweredQueriesEnabled)), {
message: "Encountered an error while trying to determine feature enablement: Error: some error message", message: "Encountered an error while trying to determine feature enablement: Error: some error message",
}); });
}); });
@ -95,7 +97,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
for (const feature of Object.keys(feature_flags_1.featureConfig)) { for (const feature of Object.keys(feature_flags_1.featureConfig)) {
(0, ava_1.default)(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => { (0, ava_1.default)(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
// set all features to false except the one we're testing // set all features to false except the one we're testing
const expectedFeatureEnablement = {}; const expectedFeatureEnablement = {};
for (const f of Object.keys(feature_flags_1.featureConfig)) { for (const f of Object.keys(feature_flags_1.featureConfig)) {
@ -105,7 +107,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
// retrieve the values of the actual features // retrieve the values of the actual features
const actualFeatureEnablement = {}; const actualFeatureEnablement = {};
for (const f of Object.keys(feature_flags_1.featureConfig)) { for (const f of Object.keys(feature_flags_1.featureConfig)) {
actualFeatureEnablement[f] = await featureEnablement.getValue(f, includeCodeQlIfRequired(f)); actualFeatureEnablement[f] = await features.getValue(f, includeCodeQlIfRequired(f));
} }
// All features should be false except the one we're testing // All features should be false except the one we're testing
t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement); t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement);
@ -113,35 +115,35 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
}); });
(0, ava_1.default)(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => { (0, ava_1.default)(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(false); const expectedFeatureEnablement = initializeFeatures(false);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
// feature should be disabled initially // feature should be disabled initially
t.assert(!(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature)))); t.assert(!(await features.getValue(feature, includeCodeQlIfRequired(feature))));
// set env var to true and check that the feature is now enabled // set env var to true and check that the feature is now enabled
process.env[feature_flags_1.featureConfig[feature].envVar] = "true"; process.env[feature_flags_1.featureConfig[feature].envVar] = "true";
t.assert(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))); t.assert(await features.getValue(feature, includeCodeQlIfRequired(feature)));
}); });
}); });
(0, ava_1.default)(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => { (0, ava_1.default)(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
// feature should be enabled initially // feature should be enabled initially
t.assert(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))); t.assert(await features.getValue(feature, includeCodeQlIfRequired(feature)));
// set env var to false and check that the feature is now disabled // set env var to false and check that the feature is now disabled
process.env[feature_flags_1.featureConfig[feature].envVar] = "false"; process.env[feature_flags_1.featureConfig[feature].envVar] = "false";
t.assert(!(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature)))); t.assert(!(await features.getValue(feature, includeCodeQlIfRequired(feature))));
}); });
}); });
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) { if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
(0, ava_1.default)(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => { (0, ava_1.default)(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
await t.throwsAsync(async () => featureEnablement.getValue(feature), { await t.throwsAsync(async () => features.getValue(feature), {
message: `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`, message: `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`,
}); });
}); });
@ -150,24 +152,24 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) { if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
(0, ava_1.default)(`Feature '${feature}' is disabled if the minimum CLI version is below ${feature_flags_1.featureConfig[feature].minimumVersion}`, async (t) => { (0, ava_1.default)(`Feature '${feature}' is disabled if the minimum CLI version is below ${feature_flags_1.featureConfig[feature].minimumVersion}`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
// feature should be disabled when an old CLI version is set // feature should be disabled when an old CLI version is set
let codeql = (0, testing_utils_1.mockCodeQLVersion)("2.0.0"); let codeql = (0, testing_utils_1.mockCodeQLVersion)("2.0.0");
t.assert(!(await featureEnablement.getValue(feature, codeql))); t.assert(!(await features.getValue(feature, codeql)));
// even setting the env var to true should not enable the feature if // even setting the env var to true should not enable the feature if
// the minimum CLI version is not met // the minimum CLI version is not met
process.env[feature_flags_1.featureConfig[feature].envVar] = "true"; process.env[feature_flags_1.featureConfig[feature].envVar] = "true";
t.assert(!(await featureEnablement.getValue(feature, codeql))); t.assert(!(await features.getValue(feature, codeql)));
// feature should be enabled when a new CLI version is set // feature should be enabled when a new CLI version is set
// and env var is not set // and env var is not set
process.env[feature_flags_1.featureConfig[feature].envVar] = ""; process.env[feature_flags_1.featureConfig[feature].envVar] = "";
codeql = (0, testing_utils_1.mockCodeQLVersion)(feature_flags_1.featureConfig[feature].minimumVersion); codeql = (0, testing_utils_1.mockCodeQLVersion)(feature_flags_1.featureConfig[feature].minimumVersion);
t.assert(await featureEnablement.getValue(feature, codeql)); t.assert(await features.getValue(feature, codeql));
// set env var to false and check that the feature is now disabled // set env var to false and check that the feature is now disabled
process.env[feature_flags_1.featureConfig[feature].envVar] = "false"; process.env[feature_flags_1.featureConfig[feature].envVar] = "false";
t.assert(!(await featureEnablement.getValue(feature, codeql))); t.assert(!(await features.getValue(feature, codeql)));
}); });
}); });
} }
@ -184,12 +186,12 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
}); });
(0, ava_1.default)("Feature flags are saved to disk", async (t) => { (0, ava_1.default)("Feature flags are saved to disk", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME); const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME);
t.false(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should not exist before getting feature flags"); t.false(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should not exist before getting feature flags");
t.true(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially"); t.true(await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially");
t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags"); t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags");
const actualFeatureEnablement = JSON.parse(fs.readFileSync(cachedFeatureFlags, "utf8")); const actualFeatureEnablement = JSON.parse(fs.readFileSync(cachedFeatureFlags, "utf8"));
t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement); t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement);
@ -197,20 +199,20 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
actualFeatureEnablement[feature_flags_1.Feature.CliConfigFileEnabled] = false; actualFeatureEnablement[feature_flags_1.Feature.CliConfigFileEnabled] = false;
fs.writeFileSync(cachedFeatureFlags, JSON.stringify(actualFeatureEnablement)); fs.writeFileSync(cachedFeatureFlags, JSON.stringify(actualFeatureEnablement));
// delete the in memory cache so that we are forced to use the cached file // delete the in memory cache so that we are forced to use the cached file
featureEnablement.gitHubFeatureFlags.cachedApiResponse = undefined; features.gitHubFeatureFlags.cachedApiResponse = undefined;
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled after reading from cached file"); t.false(await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled after reading from cached file");
}); });
}); });
(0, ava_1.default)("Environment variable can override feature flag cache", async (t) => { (0, ava_1.default)("Environment variable can override feature flag cache", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME); const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME);
t.true(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially"); t.true(await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially");
t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags"); t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags");
process.env.CODEQL_PASS_CONFIG_TO_CLI = "false"; process.env.CODEQL_PASS_CONFIG_TO_CLI = "false";
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be disabled after setting env var"); t.false(await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be disabled after setting env var");
}); });
}); });
for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) { for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
@ -228,7 +230,7 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
} }
(0, ava_1.default)("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => { (0, ava_1.default)("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
@ -237,7 +239,7 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_12_4_enabled"] = false;
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false;
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM); const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.12.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,
@ -247,10 +249,10 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
}); });
(0, ava_1.default)(`selects CLI from defaults.json on Dotcom when no default version feature flags are enabled`, async (t) => { (0, ava_1.default)(`selects CLI from defaults.json on Dotcom when no default version feature flags are enabled`, async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM); const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: defaults.cliVersion, cliVersion: defaults.cliVersion,
toolsFeatureFlagsValid: false, toolsFeatureFlagsValid: false,
@ -261,14 +263,14 @@ for (const variant of [util_1.GitHubVariant.GHAE, util_1.GitHubVariant.GHES]) {
(0, ava_1.default)("ignores invalid version numbers in default version feature flags", async (t) => { (0, ava_1.default)("ignores invalid version numbers in default version feature flags", async (t) => {
await (0, util_1.withTmpDir)(async (tmpDir) => { await (0, util_1.withTmpDir)(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages)); const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] = expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] =
true; true;
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement); (0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM); const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
cliVersion: "2.12.1", cliVersion: "2.12.1",
toolsFeatureFlagsValid: true, toolsFeatureFlagsValid: true,

File diff suppressed because one or more lines are too long

10
lib/init.js generated
View file

@ -49,15 +49,15 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion }; return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion };
} }
exports.initCodeQL = initCodeQL; exports.initCodeQL = initCodeQL;
async function initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger) { async function initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger) {
logger.startGroup("Load language configuration"); logger.startGroup("Load language configuration");
const config = await configUtils.initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureEnablement, logger); const config = await configUtils.initConfig(languagesInput, queriesInput, packsInput, registriesInput, configFile, dbLocation, trapCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeQL, workspacePath, gitHubVersion, apiDetails, features, logger);
analysisPaths.printPathFiltersWarning(config, logger); analysisPaths.printPathFiltersWarning(config, logger);
logger.endGroup(); logger.endGroup();
return config; return config;
} }
exports.initConfig = initConfig; exports.initConfig = initConfig;
async function runInit(codeql, config, sourceRoot, processName, registriesInput, featureEnablement, apiDetails, logger) { async function runInit(codeql, config, sourceRoot, processName, registriesInput, features, apiDetails, logger) {
fs.mkdirSync(config.dbLocation, { recursive: true }); fs.mkdirSync(config.dbLocation, { recursive: true });
try { try {
if (await (0, util_1.codeQlVersionAbove)(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) { if (await (0, util_1.codeQlVersionAbove)(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) {
@ -67,7 +67,7 @@ async function runInit(codeql, config, sourceRoot, processName, registriesInput,
// before the `pack download` command was invoked. It is not required for the init command. // before the `pack download` command was invoked. It is not required for the init command.
let registriesAuthTokens; let registriesAuthTokens;
let qlconfigFile; let qlconfigFile;
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await util.useCodeScanningConfigInCli(codeql, features)) {
({ registriesAuthTokens, qlconfigFile } = ({ registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(registriesInput, codeql, config.tempDir, logger)); await configUtils.generateRegistries(registriesInput, codeql, config.tempDir, logger));
} }
@ -76,7 +76,7 @@ async function runInit(codeql, config, sourceRoot, processName, registriesInput,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens, CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
}, },
// Init a database cluster // Init a database cluster
async () => await codeql.databaseInitCluster(config, sourceRoot, processName, featureEnablement, qlconfigFile, logger)); async () => await codeql.databaseInitCluster(config, sourceRoot, processName, features, qlconfigFile, logger));
} }
else { else {
for (const language of config.languages) { for (const language of config.languages) {

File diff suppressed because one or more lines are too long

8
lib/util.js generated
View file

@ -560,12 +560,12 @@ exports.isInTestMode = isInTestMode;
* @returns true if the action should generate a conde-scanning config file * @returns true if the action should generate a conde-scanning config file
* that gets passed to the CLI. * that gets passed to the CLI.
*/ */
async function useCodeScanningConfigInCli(codeql, featureEnablement) { async function useCodeScanningConfigInCli(codeql, features) {
return await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, codeql); return await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, codeql);
} }
exports.useCodeScanningConfigInCli = useCodeScanningConfigInCli; exports.useCodeScanningConfigInCli = useCodeScanningConfigInCli;
async function logCodeScanningConfigInCli(codeql, featureEnablement, logger) { async function logCodeScanningConfigInCli(codeql, features, logger) {
if (await useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await useCodeScanningConfigInCli(codeql, features)) {
logger.info("Code Scanning configuration file being processed in the codeql CLI."); logger.info("Code Scanning configuration file being processed in the codeql CLI.");
} }
else { else {

File diff suppressed because one or more lines are too long

View file

@ -207,14 +207,14 @@ export async function runQueries(
automationDetailsId: string | undefined, automationDetailsId: string | undefined,
config: configUtils.Config, config: configUtils.Config,
logger: Logger, logger: Logger,
featureEnablement: FeatureEnablement features: FeatureEnablement
): Promise<QueriesStatusReport> { ): Promise<QueriesStatusReport> {
const statusReport: QueriesStatusReport = {}; const statusReport: QueriesStatusReport = {};
const codeql = await getCodeQL(config.codeQLCmd); const codeql = await getCodeQL(config.codeQLCmd);
const queryFlags = [memoryFlag, threadsFlag]; const queryFlags = [memoryFlag, threadsFlag];
await util.logCodeScanningConfigInCli(codeql, featureEnablement, logger); await util.logCodeScanningConfigInCli(codeql, features, logger);
for (const language of config.languages) { for (const language of config.languages) {
const queries = config.queries[language]; const queries = config.queries[language];
@ -224,7 +224,7 @@ export async function runQueries(
const packsWithVersion = config.packs[language] || []; const packsWithVersion = config.packs[language] || [];
try { try {
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await util.useCodeScanningConfigInCli(codeql, features)) {
// If we are using the code scanning config in the CLI, // If we are using the code scanning config in the CLI,
// much of the work needed to generate the query suites // much of the work needed to generate the query suites
// is done in the CLI. We just need to make a single // is done in the CLI. We just need to make a single
@ -369,7 +369,7 @@ export async function runQueries(
enableDebugLogging ? "-vv" : "-v", enableDebugLogging ? "-vv" : "-v",
automationDetailsId, automationDetailsId,
config, config,
featureEnablement features
); );
} }

View file

@ -94,7 +94,7 @@ export interface CodeQL {
config: Config, config: Config,
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
qlconfigFile: string | undefined, qlconfigFile: string | undefined,
logger: Logger logger: Logger
): Promise<void>; ): Promise<void>;
@ -584,7 +584,7 @@ export async function getCodeQLForCmd(
config: Config, config: Config,
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
qlconfigFile: string | undefined, qlconfigFile: string | undefined,
logger: Logger logger: Logger
) { ) {
@ -619,7 +619,7 @@ export async function getCodeQLForCmd(
const codeScanningConfigFile = await generateCodeScanningConfig( const codeScanningConfigFile = await generateCodeScanningConfig(
codeql, codeql,
config, config,
featureEnablement, features,
logger logger
); );
// Only pass external repository token if a config file is going to be parsed by the CLI. // Only pass external repository token if a config file is going to be parsed by the CLI.
@ -1138,10 +1138,10 @@ async function runTool(
async function generateCodeScanningConfig( async function generateCodeScanningConfig(
codeql: CodeQL, codeql: CodeQL,
config: Config, config: Config,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<string | undefined> { ): Promise<string | undefined> {
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) { if (!(await util.useCodeScanningConfigInCli(codeql, features))) {
return; return;
} }
const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config);

View file

@ -398,7 +398,7 @@ async function addBuiltinSuiteQueries(
resultMap: Queries, resultMap: Queries,
packs: Packs, packs: Packs,
suiteName: string, suiteName: string,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
configFile?: string configFile?: string
): Promise<boolean> { ): Promise<boolean> {
let injectedMlQueries = false; let injectedMlQueries = false;
@ -435,7 +435,7 @@ async function addBuiltinSuiteQueries(
found === "security-extended" || found === "security-extended" ||
found === "security-and-quality") && found === "security-and-quality") &&
!packs.javascript?.some(isMlPoweredJsQueriesPack) && !packs.javascript?.some(isMlPoweredJsQueriesPack) &&
(await featureEnablement.getValue(Feature.MlPoweredQueriesEnabled, codeQL)) (await features.getValue(Feature.MlPoweredQueriesEnabled, codeQL))
) { ) {
if (!packs.javascript) { if (!packs.javascript) {
packs.javascript = []; packs.javascript = [];
@ -567,7 +567,7 @@ async function parseQueryUses(
tempDir: string, tempDir: string,
workspacePath: string, workspacePath: string,
apiDetails: api.GitHubApiExternalRepoDetails, apiDetails: api.GitHubApiExternalRepoDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger, logger: Logger,
configFile?: string configFile?: string
): Promise<boolean> { ): Promise<boolean> {
@ -596,7 +596,7 @@ async function parseQueryUses(
resultMap, resultMap,
packs, packs,
queryUses, queryUses,
featureEnablement, features,
configFile configFile
); );
} }
@ -604,7 +604,7 @@ async function parseQueryUses(
// Otherwise, must be a reference to another repo. // Otherwise, must be a reference to another repo.
// If config parsing is handled in CLI, then this repo will be downloaded // If config parsing is handled in CLI, then this repo will be downloaded
// later by the CLI. // later by the CLI.
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) { if (!(await useCodeScanningConfigInCli(codeQL, features))) {
await addRemoteQueries( await addRemoteQueries(
codeQL, codeQL,
resultMap, resultMap,
@ -1011,7 +1011,7 @@ async function addQueriesAndPacksFromWorkflow(
tempDir: string, tempDir: string,
workspacePath: string, workspacePath: string,
apiDetails: api.GitHubApiExternalRepoDetails, apiDetails: api.GitHubApiExternalRepoDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<boolean> { ): Promise<boolean> {
let injectedMlQueries = false; let injectedMlQueries = false;
@ -1029,7 +1029,7 @@ async function addQueriesAndPacksFromWorkflow(
tempDir, tempDir,
workspacePath, workspacePath,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
injectedMlQueries = injectedMlQueries || didInject; injectedMlQueries = injectedMlQueries || didInject;
@ -1068,7 +1068,7 @@ export async function getDefaultConfig(
workspacePath: string, workspacePath: string,
gitHubVersion: GitHubVersion, gitHubVersion: GitHubVersion,
apiDetails: api.GitHubApiCombinedDetails, apiDetails: api.GitHubApiCombinedDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<Config> { ): Promise<Config> {
const languages = await getLanguages( const languages = await getLanguages(
@ -1106,7 +1106,7 @@ export async function getDefaultConfig(
tempDir, tempDir,
workspacePath, workspacePath,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
} }
@ -1176,7 +1176,7 @@ async function loadConfig(
workspacePath: string, workspacePath: string,
gitHubVersion: GitHubVersion, gitHubVersion: GitHubVersion,
apiDetails: api.GitHubApiCombinedDetails, apiDetails: api.GitHubApiCombinedDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<Config> { ): Promise<Config> {
let parsedYAML: UserConfig; let parsedYAML: UserConfig;
@ -1256,7 +1256,7 @@ async function loadConfig(
tempDir, tempDir,
workspacePath, workspacePath,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
} }
@ -1281,7 +1281,7 @@ async function loadConfig(
tempDir, tempDir,
workspacePath, workspacePath,
apiDetails, apiDetails,
featureEnablement, features,
logger, logger,
configFile configFile
); );
@ -1700,7 +1700,7 @@ export async function initConfig(
workspacePath: string, workspacePath: string,
gitHubVersion: GitHubVersion, gitHubVersion: GitHubVersion,
apiDetails: api.GitHubApiCombinedDetails, apiDetails: api.GitHubApiCombinedDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<Config> { ): Promise<Config> {
let config: Config; let config: Config;
@ -1723,7 +1723,7 @@ export async function initConfig(
workspacePath, workspacePath,
gitHubVersion, gitHubVersion,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
} else { } else {
@ -1743,7 +1743,7 @@ export async function initConfig(
workspacePath, workspacePath,
gitHubVersion, gitHubVersion,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
} }
@ -1751,9 +1751,9 @@ export async function initConfig(
// When using the codescanning config in the CLI, pack downloads // When using the codescanning config in the CLI, pack downloads
// happen in the CLI during the `database init` command, so no need // happen in the CLI during the `database init` command, so no need
// to download them here. // to download them here.
await logCodeScanningConfigInCli(codeQL, featureEnablement, logger); await logCodeScanningConfigInCli(codeQL, features, logger);
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) { if (!(await useCodeScanningConfigInCli(codeQL, features))) {
// The list of queries should not be empty for any language. If it is then // The list of queries should not be empty for any language. If it is then
// it is a user configuration error. // it is a user configuration error.
// This check occurs in the CLI when it parses the config file. // This check occurs in the CLI when it parses the config file.

View file

@ -47,7 +47,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
test(`All features are disabled if running against ${variant.description}`, async (t) => { test(`All features are disabled if running against ${variant.description}`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests( const features = setUpFeatureFlagTests(
tmpDir, tmpDir,
getRecordingLogger(loggedMessages), getRecordingLogger(loggedMessages),
variant.gitHubVersion variant.gitHubVersion
@ -55,10 +55,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
for (const feature of Object.values(Feature)) { for (const feature of Object.values(Feature)) {
t.false( t.false(
await featureEnablement.getValue( await features.getValue(feature, includeCodeQlIfRequired(feature))
feature,
includeCodeQlIfRequired(feature)
)
); );
} }
@ -77,7 +74,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
test("API response missing", async (t) => { test("API response missing", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const loggedMessages: LoggedMessage[] = []; const loggedMessages: LoggedMessage[] = [];
const featureEnablement = setUpFeatureFlagTests( const features = setUpFeatureFlagTests(
tmpDir, tmpDir,
getRecordingLogger(loggedMessages) getRecordingLogger(loggedMessages)
); );
@ -86,10 +83,8 @@ test("API response missing", async (t) => {
for (const feature of Object.values(Feature)) { for (const feature of Object.values(Feature)) {
t.assert( t.assert(
(await featureEnablement.getValue( (await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
feature, false
includeCodeQlIfRequired(feature)
)) === false
); );
} }
assertAllFeaturesUndefinedInApi(t, loggedMessages); assertAllFeaturesUndefinedInApi(t, loggedMessages);
@ -99,7 +94,7 @@ test("API response missing", async (t) => {
test("Features are disabled if they're not returned in API response", async (t) => { test("Features are disabled if they're not returned in API response", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const loggedMessages: LoggedMessage[] = []; const loggedMessages: LoggedMessage[] = [];
const featureEnablement = setUpFeatureFlagTests( const features = setUpFeatureFlagTests(
tmpDir, tmpDir,
getRecordingLogger(loggedMessages) getRecordingLogger(loggedMessages)
); );
@ -108,10 +103,8 @@ test("Features are disabled if they're not returned in API response", async (t)
for (const feature of Object.values(Feature)) { for (const feature of Object.values(Feature)) {
t.assert( t.assert(
(await featureEnablement.getValue( (await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
feature, false
includeCodeQlIfRequired(feature)
)) === false
); );
} }
@ -121,13 +114,13 @@ test("Features are disabled if they're not returned in API response", async (t)
test("Feature flags exception is propagated if the API request errors", async (t) => { test("Feature flags exception is propagated if the API request errors", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
mockFeatureFlagApiEndpoint(500, {}); mockFeatureFlagApiEndpoint(500, {});
await t.throwsAsync( await t.throwsAsync(
async () => async () =>
featureEnablement.getValue( features.getValue(
Feature.MlPoweredQueriesEnabled, Feature.MlPoweredQueriesEnabled,
includeCodeQlIfRequired(Feature.MlPoweredQueriesEnabled) includeCodeQlIfRequired(Feature.MlPoweredQueriesEnabled)
), ),
@ -142,7 +135,7 @@ test("Feature flags exception is propagated if the API request errors", async (t
for (const feature of Object.keys(featureConfig)) { for (const feature of Object.keys(featureConfig)) {
test(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => { test(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
// set all features to false except the one we're testing // set all features to false except the one we're testing
const expectedFeatureEnablement: { [feature: string]: boolean } = {}; const expectedFeatureEnablement: { [feature: string]: boolean } = {};
@ -154,7 +147,7 @@ for (const feature of Object.keys(featureConfig)) {
// retrieve the values of the actual features // retrieve the values of the actual features
const actualFeatureEnablement: { [feature: string]: boolean } = {}; const actualFeatureEnablement: { [feature: string]: boolean } = {};
for (const f of Object.keys(featureConfig)) { for (const f of Object.keys(featureConfig)) {
actualFeatureEnablement[f] = await featureEnablement.getValue( actualFeatureEnablement[f] = await features.getValue(
f as Feature, f as Feature,
includeCodeQlIfRequired(f) includeCodeQlIfRequired(f)
); );
@ -167,14 +160,14 @@ for (const feature of Object.keys(featureConfig)) {
test(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => { test(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(false); const expectedFeatureEnablement = initializeFeatures(false);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
// feature should be disabled initially // feature should be disabled initially
t.assert( t.assert(
!(await featureEnablement.getValue( !(await features.getValue(
feature as Feature, feature as Feature,
includeCodeQlIfRequired(feature) includeCodeQlIfRequired(feature)
)) ))
@ -183,7 +176,7 @@ for (const feature of Object.keys(featureConfig)) {
// set env var to true and check that the feature is now enabled // set env var to true and check that the feature is now enabled
process.env[featureConfig[feature].envVar] = "true"; process.env[featureConfig[feature].envVar] = "true";
t.assert( t.assert(
await featureEnablement.getValue( await features.getValue(
feature as Feature, feature as Feature,
includeCodeQlIfRequired(feature) includeCodeQlIfRequired(feature)
) )
@ -193,14 +186,14 @@ for (const feature of Object.keys(featureConfig)) {
test(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => { test(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
// feature should be enabled initially // feature should be enabled initially
t.assert( t.assert(
await featureEnablement.getValue( await features.getValue(
feature as Feature, feature as Feature,
includeCodeQlIfRequired(feature) includeCodeQlIfRequired(feature)
) )
@ -209,7 +202,7 @@ for (const feature of Object.keys(featureConfig)) {
// set env var to false and check that the feature is now disabled // set env var to false and check that the feature is now disabled
process.env[featureConfig[feature].envVar] = "false"; process.env[featureConfig[feature].envVar] = "false";
t.assert( t.assert(
!(await featureEnablement.getValue( !(await features.getValue(
feature as Feature, feature as Feature,
includeCodeQlIfRequired(feature) includeCodeQlIfRequired(feature)
)) ))
@ -220,17 +213,14 @@ for (const feature of Object.keys(featureConfig)) {
if (featureConfig[feature].minimumVersion !== undefined) { if (featureConfig[feature].minimumVersion !== undefined) {
test(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => { test(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
await t.throwsAsync( await t.throwsAsync(async () => features.getValue(feature as Feature), {
async () => featureEnablement.getValue(feature as Feature), message: `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`,
{ });
message: `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`,
}
);
}); });
}); });
} }
@ -238,35 +228,29 @@ for (const feature of Object.keys(featureConfig)) {
if (featureConfig[feature].minimumVersion !== undefined) { if (featureConfig[feature].minimumVersion !== undefined) {
test(`Feature '${feature}' is disabled if the minimum CLI version is below ${featureConfig[feature].minimumVersion}`, async (t) => { test(`Feature '${feature}' is disabled if the minimum CLI version is below ${featureConfig[feature].minimumVersion}`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
// feature should be disabled when an old CLI version is set // feature should be disabled when an old CLI version is set
let codeql = mockCodeQLVersion("2.0.0"); let codeql = mockCodeQLVersion("2.0.0");
t.assert( t.assert(!(await features.getValue(feature as Feature, codeql)));
!(await featureEnablement.getValue(feature as Feature, codeql))
);
// even setting the env var to true should not enable the feature if // even setting the env var to true should not enable the feature if
// the minimum CLI version is not met // the minimum CLI version is not met
process.env[featureConfig[feature].envVar] = "true"; process.env[featureConfig[feature].envVar] = "true";
t.assert( t.assert(!(await features.getValue(feature as Feature, codeql)));
!(await featureEnablement.getValue(feature as Feature, codeql))
);
// feature should be enabled when a new CLI version is set // feature should be enabled when a new CLI version is set
// and env var is not set // and env var is not set
process.env[featureConfig[feature].envVar] = ""; process.env[featureConfig[feature].envVar] = "";
codeql = mockCodeQLVersion(featureConfig[feature].minimumVersion); codeql = mockCodeQLVersion(featureConfig[feature].minimumVersion);
t.assert(await featureEnablement.getValue(feature as Feature, codeql)); t.assert(await features.getValue(feature as Feature, codeql));
// set env var to false and check that the feature is now disabled // set env var to false and check that the feature is now disabled
process.env[featureConfig[feature].envVar] = "false"; process.env[featureConfig[feature].envVar] = "false";
t.assert( t.assert(!(await features.getValue(feature as Feature, codeql)));
!(await featureEnablement.getValue(feature as Feature, codeql))
);
}); });
}); });
} }
@ -292,7 +276,7 @@ test("At least one feature has a minimum version specified", (t) => {
test("Feature flags are saved to disk", async (t) => { test("Feature flags are saved to disk", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
@ -304,7 +288,7 @@ test("Feature flags are saved to disk", async (t) => {
); );
t.true( t.true(
await featureEnablement.getValue( await features.getValue(
Feature.CliConfigFileEnabled, Feature.CliConfigFileEnabled,
includeCodeQlIfRequired(Feature.CliConfigFileEnabled) includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
), ),
@ -329,10 +313,10 @@ test("Feature flags are saved to disk", async (t) => {
); );
// delete the in memory cache so that we are forced to use the cached file // delete the in memory cache so that we are forced to use the cached file
(featureEnablement as any).gitHubFeatureFlags.cachedApiResponse = undefined; (features as any).gitHubFeatureFlags.cachedApiResponse = undefined;
t.false( t.false(
await featureEnablement.getValue( await features.getValue(
Feature.CliConfigFileEnabled, Feature.CliConfigFileEnabled,
includeCodeQlIfRequired(Feature.CliConfigFileEnabled) includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
), ),
@ -343,13 +327,13 @@ test("Feature flags are saved to disk", async (t) => {
test("Environment variable can override feature flag cache", async (t) => { test("Environment variable can override feature flag cache", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const cachedFeatureFlags = path.join(tmpDir, FEATURE_FLAGS_FILE_NAME); const cachedFeatureFlags = path.join(tmpDir, FEATURE_FLAGS_FILE_NAME);
t.true( t.true(
await featureEnablement.getValue( await features.getValue(
Feature.CliConfigFileEnabled, Feature.CliConfigFileEnabled,
includeCodeQlIfRequired(Feature.CliConfigFileEnabled) includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
), ),
@ -363,7 +347,7 @@ test("Environment variable can override feature flag cache", async (t) => {
process.env.CODEQL_PASS_CONFIG_TO_CLI = "false"; process.env.CODEQL_PASS_CONFIG_TO_CLI = "false";
t.false( t.false(
await featureEnablement.getValue( await features.getValue(
Feature.CliConfigFileEnabled, Feature.CliConfigFileEnabled,
includeCodeQlIfRequired(Feature.CliConfigFileEnabled) includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
), ),
@ -389,7 +373,7 @@ for (const variant of [GitHubVariant.GHAE, GitHubVariant.GHES]) {
test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => { test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.1", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true; expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
@ -399,7 +383,7 @@ test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.
expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false; expectedFeatureEnablement["default_codeql_version_2_12_5_enabled"] = false;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion( const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.DOTCOM GitHubVariant.DOTCOM
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
@ -412,11 +396,11 @@ test("selects CLI v2.12.1 on Dotcom when feature flags enable v2.12.0 and v2.12.
test(`selects CLI from defaults.json on Dotcom when no default version feature flags are enabled`, async (t) => { test(`selects CLI from defaults.json on Dotcom when no default version feature flags are enabled`, async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const featureEnablement = setUpFeatureFlagTests(tmpDir); const features = setUpFeatureFlagTests(tmpDir);
const expectedFeatureEnablement = initializeFeatures(true); const expectedFeatureEnablement = initializeFeatures(true);
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion( const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.DOTCOM GitHubVariant.DOTCOM
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {
@ -430,7 +414,7 @@ test(`selects CLI from defaults.json on Dotcom when no default version feature f
test("ignores invalid version numbers in default version feature flags", async (t) => { test("ignores invalid version numbers in default version feature flags", async (t) => {
await withTmpDir(async (tmpDir) => { await withTmpDir(async (tmpDir) => {
const loggedMessages = []; const loggedMessages = [];
const featureEnablement = setUpFeatureFlagTests( const features = setUpFeatureFlagTests(
tmpDir, tmpDir,
getRecordingLogger(loggedMessages) getRecordingLogger(loggedMessages)
); );
@ -441,7 +425,7 @@ test("ignores invalid version numbers in default version feature flags", async (
true; true;
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement); mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
const defaultCliVersion = await featureEnablement.getDefaultCliVersion( const defaultCliVersion = await features.getDefaultCliVersion(
GitHubVariant.DOTCOM GitHubVariant.DOTCOM
); );
t.deepEqual(defaultCliVersion, { t.deepEqual(defaultCliVersion, {

View file

@ -264,14 +264,14 @@ class GitHubFeatureFlags implements FeatureEnablement {
); );
return false; return false;
} }
const featureEnablement = response[feature]; const features = response[feature];
if (featureEnablement === undefined) { if (features === undefined) {
this.logger.debug( this.logger.debug(
`Feature '${feature}' undefined in API response, considering it disabled.` `Feature '${feature}' undefined in API response, considering it disabled.`
); );
return false; return false;
} }
return !!featureEnablement; return !!features;
} }
private async getAllFeatures(): Promise<GitHubFeatureFlagsApiResponse> { private async getAllFeatures(): Promise<GitHubFeatureFlagsApiResponse> {

View file

@ -68,7 +68,7 @@ export async function initConfig(
workspacePath: string, workspacePath: string,
gitHubVersion: util.GitHubVersion, gitHubVersion: util.GitHubVersion,
apiDetails: GitHubApiCombinedDetails, apiDetails: GitHubApiCombinedDetails,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
): Promise<configUtils.Config> { ): Promise<configUtils.Config> {
logger.startGroup("Load language configuration"); logger.startGroup("Load language configuration");
@ -89,7 +89,7 @@ export async function initConfig(
workspacePath, workspacePath,
gitHubVersion, gitHubVersion,
apiDetails, apiDetails,
featureEnablement, features,
logger logger
); );
analysisPaths.printPathFiltersWarning(config, logger); analysisPaths.printPathFiltersWarning(config, logger);
@ -103,7 +103,7 @@ export async function runInit(
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
registriesInput: string | undefined, registriesInput: string | undefined,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
apiDetails: GitHubApiCombinedDetails, apiDetails: GitHubApiCombinedDetails,
logger: Logger logger: Logger
): Promise<TracerConfig | undefined> { ): Promise<TracerConfig | undefined> {
@ -117,7 +117,7 @@ export async function runInit(
// before the `pack download` command was invoked. It is not required for the init command. // before the `pack download` command was invoked. It is not required for the init command.
let registriesAuthTokens: string | undefined; let registriesAuthTokens: string | undefined;
let qlconfigFile: string | undefined; let qlconfigFile: string | undefined;
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await util.useCodeScanningConfigInCli(codeql, features)) {
({ registriesAuthTokens, qlconfigFile } = ({ registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries( await configUtils.generateRegistries(
registriesInput, registriesInput,
@ -138,7 +138,7 @@ export async function runInit(
config, config,
sourceRoot, sourceRoot,
processName, processName,
featureEnablement, features,
qlconfigFile, qlconfigFile,
logger logger
) )

View file

@ -664,17 +664,17 @@ export function isInTestMode(): boolean {
*/ */
export async function useCodeScanningConfigInCli( export async function useCodeScanningConfigInCli(
codeql: CodeQL, codeql: CodeQL,
featureEnablement: FeatureEnablement features: FeatureEnablement
): Promise<boolean> { ): Promise<boolean> {
return await featureEnablement.getValue(Feature.CliConfigFileEnabled, codeql); return await features.getValue(Feature.CliConfigFileEnabled, codeql);
} }
export async function logCodeScanningConfigInCli( export async function logCodeScanningConfigInCli(
codeql: CodeQL, codeql: CodeQL,
featureEnablement: FeatureEnablement, features: FeatureEnablement,
logger: Logger logger: Logger
) { ) {
if (await useCodeScanningConfigInCli(codeql, featureEnablement)) { if (await useCodeScanningConfigInCli(codeql, features)) {
logger.info( logger.info(
"Code Scanning configuration file being processed in the codeql CLI." "Code Scanning configuration file being processed in the codeql CLI."
); );