Rename featureEnablement to features
This is more succinct and removes a few line breaks
This commit is contained in:
parent
fc1366f6ec
commit
485cc11a24
21 changed files with 160 additions and 174 deletions
8
lib/analyze.js
generated
8
lib/analyze.js
generated
|
|
@ -123,17 +123,17 @@ async function finalizeDatabaseCreation(config, threadsFlag, memoryFlag, logger)
|
|||
};
|
||||
}
|
||||
// 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 codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
|
||||
const queryFlags = [memoryFlag, threadsFlag];
|
||||
await util.logCodeScanningConfigInCli(codeql, featureEnablement, logger);
|
||||
await util.logCodeScanningConfigInCli(codeql, features, logger);
|
||||
for (const language of config.languages) {
|
||||
const queries = config.queries[language];
|
||||
const queryFilters = validateQueryFilters(config.originalUserInput["query-filters"]);
|
||||
const packsWithVersion = config.packs[language] || [];
|
||||
try {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
// If we are using the code scanning 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
|
||||
|
|
@ -218,7 +218,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
return statusReport;
|
||||
async function runInterpretResults(language, queries, sarifFile, enableDebugLogging) {
|
||||
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) {
|
||||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
8
lib/codeql.js
generated
8
lib/codeql.js
generated
|
|
@ -313,7 +313,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
|||
...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}`);
|
||||
if (config.languages.filter((l) => (0, languages_1.isTracedLanguage)(l)).length > 0) {
|
||||
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.
|
||||
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.
|
||||
let externalRepositoryToken;
|
||||
if (codeScanningConfigFile) {
|
||||
|
|
@ -731,8 +731,8 @@ async function runTool(cmd, args = [], opts = {}) {
|
|||
* @param config The configuration to use.
|
||||
* @returns the path to the generated user configuration file.
|
||||
*/
|
||||
async function generateCodeScanningConfig(codeql, config, featureEnablement, logger) {
|
||||
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) {
|
||||
async function generateCodeScanningConfig(codeql, config, features, logger) {
|
||||
if (!(await util.useCodeScanningConfigInCli(codeql, features))) {
|
||||
return;
|
||||
}
|
||||
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
34
lib/config-utils.js
generated
|
|
@ -141,7 +141,7 @@ const builtinSuites = [
|
|||
* 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.
|
||||
*/
|
||||
async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suiteName, featureEnablement, configFile) {
|
||||
async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suiteName, features, configFile) {
|
||||
let injectedMlQueries = false;
|
||||
const found = builtinSuites.find((suite) => suite === suiteName);
|
||||
if (!found) {
|
||||
|
|
@ -165,7 +165,7 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
|
|||
found === "security-extended" ||
|
||||
found === "security-and-quality") &&
|
||||
!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) {
|
||||
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
|
||||
*/
|
||||
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();
|
||||
if (queryUses === "") {
|
||||
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
|
||||
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.
|
||||
// If config parsing is handled in CLI, then this repo will be downloaded
|
||||
// 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);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -503,13 +503,13 @@ async function getRawLanguages(languagesInput, repository, logger) {
|
|||
return { rawLanguages, autodetected };
|
||||
}
|
||||
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;
|
||||
queriesInput = queriesInput.trim();
|
||||
// "+" means "don't override config file" - see shouldAddConfigFileQueries
|
||||
queriesInput = queriesInput.replace(/^\+/, "");
|
||||
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;
|
||||
}
|
||||
return injectedMlQueries;
|
||||
|
|
@ -527,7 +527,7 @@ function shouldAddConfigFileQueries(queriesInput) {
|
|||
/**
|
||||
* 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 queries = {};
|
||||
for (const language of languages) {
|
||||
|
|
@ -545,7 +545,7 @@ async function getDefaultConfig(languagesInput, rawQueriesInput, rawPacksInput,
|
|||
: {};
|
||||
if (rawQueriesInput) {
|
||||
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);
|
||||
return {
|
||||
|
|
@ -581,7 +581,7 @@ async function downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logg
|
|||
/**
|
||||
* 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;
|
||||
if (isLocal(configFile)) {
|
||||
// Treat the config file as relative to the workspace
|
||||
|
|
@ -629,7 +629,7 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
|
|||
// in the config file.
|
||||
if (rawQueriesInput) {
|
||||
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) &&
|
||||
QUERIES_PROPERTY in parsedYAML) {
|
||||
|
|
@ -641,7 +641,7 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
|
|||
if (typeof query[QUERIES_USES_PROPERTY] !== "string") {
|
||||
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) {
|
||||
|
|
@ -932,21 +932,21 @@ function dbLocationOrDefault(dbLocation, tempDir) {
|
|||
* 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.
|
||||
*/
|
||||
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;
|
||||
// If no config file was provided create an empty one
|
||||
if (!configFile) {
|
||||
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 {
|
||||
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
|
||||
// happen in the CLI during the `database init` command, so no need
|
||||
// to download them here.
|
||||
await (0, util_1.logCodeScanningConfigInCli)(codeQL, featureEnablement, logger);
|
||||
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, featureEnablement))) {
|
||||
await (0, util_1.logCodeScanningConfigInCli)(codeQL, features, logger);
|
||||
if (!(await (0, util_1.useCodeScanningConfigInCli)(codeQL, features))) {
|
||||
// The list of queries should not be empty for any language. If it is then
|
||||
// it is a user configuration error.
|
||||
// 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
6
lib/feature-flags.js
generated
|
|
@ -188,12 +188,12 @@ class GitHubFeatureFlags {
|
|||
this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`);
|
||||
return false;
|
||||
}
|
||||
const featureEnablement = response[feature];
|
||||
if (featureEnablement === undefined) {
|
||||
const features = response[feature];
|
||||
if (features === undefined) {
|
||||
this.logger.debug(`Feature '${feature}' undefined in API response, considering it disabled.`);
|
||||
return false;
|
||||
}
|
||||
return !!featureEnablement;
|
||||
return !!features;
|
||||
}
|
||||
async getAllFeatures() {
|
||||
// if we have an in memory cache, use that
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
74
lib/feature-flags.test.js
generated
74
lib/feature-flags.test.js
generated
|
|
@ -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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
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)) {
|
||||
t.false(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||
t.false(await features.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||
}
|
||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||
v.message ===
|
||||
|
|
@ -64,10 +64,11 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
(0, ava_1.default)("API response missing", async (t) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
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, {});
|
||||
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);
|
||||
});
|
||||
|
|
@ -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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
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, {});
|
||||
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);
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("Feature flags exception is propagated if the API request errors", async (t) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
(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",
|
||||
});
|
||||
});
|
||||
|
|
@ -95,7 +97,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
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) => {
|
||||
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
|
||||
const expectedFeatureEnablement = {};
|
||||
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
|
||||
const actualFeatureEnablement = {};
|
||||
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
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(false);
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||
// 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
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||
// 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
|
||||
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) {
|
||||
(0, ava_1.default)(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(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.`,
|
||||
});
|
||||
});
|
||||
|
|
@ -150,24 +152,24 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||
// feature should be disabled when an old CLI version is set
|
||||
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
|
||||
// the minimum CLI version is not met
|
||||
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
|
||||
// and env var is not set
|
||||
process.env[feature_flags_1.featureConfig[feature].envVar] = "";
|
||||
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
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||
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.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");
|
||||
const actualFeatureEnablement = JSON.parse(fs.readFileSync(cachedFeatureFlags, "utf8"));
|
||||
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;
|
||||
fs.writeFileSync(cachedFeatureFlags, JSON.stringify(actualFeatureEnablement));
|
||||
// delete the in memory cache so that we are forced to use the cached file
|
||||
featureEnablement.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");
|
||||
features.gitHubFeatureFlags.cachedApiResponse = undefined;
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||
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");
|
||||
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]) {
|
||||
|
|
@ -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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
expectedFeatureEnablement["default_codeql_version_2_12_0_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_5_enabled"] = false;
|
||||
(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, {
|
||||
cliVersion: "2.12.1",
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
(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, {
|
||||
cliVersion: defaults.cliVersion,
|
||||
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) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
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);
|
||||
expectedFeatureEnablement["default_codeql_version_2_12_0_enabled"] = true;
|
||||
expectedFeatureEnablement["default_codeql_version_2_12_1_enabled"] = true;
|
||||
expectedFeatureEnablement["default_codeql_version_2_12_invalid_enabled"] =
|
||||
true;
|
||||
(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, {
|
||||
cliVersion: "2.12.1",
|
||||
toolsFeatureFlagsValid: true,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
10
lib/init.js
generated
10
lib/init.js
generated
|
|
@ -49,15 +49,15 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe
|
|||
return { codeql, toolsDownloadDurationMs, toolsSource, toolsVersion };
|
||||
}
|
||||
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");
|
||||
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);
|
||||
logger.endGroup();
|
||||
return config;
|
||||
}
|
||||
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 });
|
||||
try {
|
||||
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.
|
||||
let registriesAuthTokens;
|
||||
let qlconfigFile;
|
||||
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
({ registriesAuthTokens, qlconfigFile } =
|
||||
await configUtils.generateRegistries(registriesInput, codeql, config.tempDir, logger));
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ async function runInit(codeql, config, sourceRoot, processName, registriesInput,
|
|||
CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
|
||||
},
|
||||
// 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 {
|
||||
for (const language of config.languages) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
8
lib/util.js
generated
8
lib/util.js
generated
|
|
@ -560,12 +560,12 @@ exports.isInTestMode = isInTestMode;
|
|||
* @returns true if the action should generate a conde-scanning config file
|
||||
* that gets passed to the CLI.
|
||||
*/
|
||||
async function useCodeScanningConfigInCli(codeql, featureEnablement) {
|
||||
return await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, codeql);
|
||||
async function useCodeScanningConfigInCli(codeql, features) {
|
||||
return await features.getValue(feature_flags_1.Feature.CliConfigFileEnabled, codeql);
|
||||
}
|
||||
exports.useCodeScanningConfigInCli = useCodeScanningConfigInCli;
|
||||
async function logCodeScanningConfigInCli(codeql, featureEnablement, logger) {
|
||||
if (await useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
async function logCodeScanningConfigInCli(codeql, features, logger) {
|
||||
if (await useCodeScanningConfigInCli(codeql, features)) {
|
||||
logger.info("Code Scanning configuration file being processed in the codeql CLI.");
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -207,14 +207,14 @@ export async function runQueries(
|
|||
automationDetailsId: string | undefined,
|
||||
config: configUtils.Config,
|
||||
logger: Logger,
|
||||
featureEnablement: FeatureEnablement
|
||||
features: FeatureEnablement
|
||||
): Promise<QueriesStatusReport> {
|
||||
const statusReport: QueriesStatusReport = {};
|
||||
|
||||
const codeql = await getCodeQL(config.codeQLCmd);
|
||||
const queryFlags = [memoryFlag, threadsFlag];
|
||||
|
||||
await util.logCodeScanningConfigInCli(codeql, featureEnablement, logger);
|
||||
await util.logCodeScanningConfigInCli(codeql, features, logger);
|
||||
|
||||
for (const language of config.languages) {
|
||||
const queries = config.queries[language];
|
||||
|
|
@ -224,7 +224,7 @@ export async function runQueries(
|
|||
const packsWithVersion = config.packs[language] || [];
|
||||
|
||||
try {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
// If we are using the code scanning 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
|
||||
|
|
@ -369,7 +369,7 @@ export async function runQueries(
|
|||
enableDebugLogging ? "-vv" : "-v",
|
||||
automationDetailsId,
|
||||
config,
|
||||
featureEnablement
|
||||
features
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export interface CodeQL {
|
|||
config: Config,
|
||||
sourceRoot: string,
|
||||
processName: string | undefined,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
qlconfigFile: string | undefined,
|
||||
logger: Logger
|
||||
): Promise<void>;
|
||||
|
|
@ -584,7 +584,7 @@ export async function getCodeQLForCmd(
|
|||
config: Config,
|
||||
sourceRoot: string,
|
||||
processName: string | undefined,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
qlconfigFile: string | undefined,
|
||||
logger: Logger
|
||||
) {
|
||||
|
|
@ -619,7 +619,7 @@ export async function getCodeQLForCmd(
|
|||
const codeScanningConfigFile = await generateCodeScanningConfig(
|
||||
codeql,
|
||||
config,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
// 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(
|
||||
codeql: CodeQL,
|
||||
config: Config,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<string | undefined> {
|
||||
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) {
|
||||
if (!(await util.useCodeScanningConfigInCli(codeql, features))) {
|
||||
return;
|
||||
}
|
||||
const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config);
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ async function addBuiltinSuiteQueries(
|
|||
resultMap: Queries,
|
||||
packs: Packs,
|
||||
suiteName: string,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
configFile?: string
|
||||
): Promise<boolean> {
|
||||
let injectedMlQueries = false;
|
||||
|
|
@ -435,7 +435,7 @@ async function addBuiltinSuiteQueries(
|
|||
found === "security-extended" ||
|
||||
found === "security-and-quality") &&
|
||||
!packs.javascript?.some(isMlPoweredJsQueriesPack) &&
|
||||
(await featureEnablement.getValue(Feature.MlPoweredQueriesEnabled, codeQL))
|
||||
(await features.getValue(Feature.MlPoweredQueriesEnabled, codeQL))
|
||||
) {
|
||||
if (!packs.javascript) {
|
||||
packs.javascript = [];
|
||||
|
|
@ -567,7 +567,7 @@ async function parseQueryUses(
|
|||
tempDir: string,
|
||||
workspacePath: string,
|
||||
apiDetails: api.GitHubApiExternalRepoDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
configFile?: string
|
||||
): Promise<boolean> {
|
||||
|
|
@ -596,7 +596,7 @@ async function parseQueryUses(
|
|||
resultMap,
|
||||
packs,
|
||||
queryUses,
|
||||
featureEnablement,
|
||||
features,
|
||||
configFile
|
||||
);
|
||||
}
|
||||
|
|
@ -604,7 +604,7 @@ async function parseQueryUses(
|
|||
// Otherwise, must be a reference to another repo.
|
||||
// If config parsing is handled in CLI, then this repo will be downloaded
|
||||
// later by the CLI.
|
||||
if (!(await useCodeScanningConfigInCli(codeQL, featureEnablement))) {
|
||||
if (!(await useCodeScanningConfigInCli(codeQL, features))) {
|
||||
await addRemoteQueries(
|
||||
codeQL,
|
||||
resultMap,
|
||||
|
|
@ -1011,7 +1011,7 @@ async function addQueriesAndPacksFromWorkflow(
|
|||
tempDir: string,
|
||||
workspacePath: string,
|
||||
apiDetails: api.GitHubApiExternalRepoDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<boolean> {
|
||||
let injectedMlQueries = false;
|
||||
|
|
@ -1029,7 +1029,7 @@ async function addQueriesAndPacksFromWorkflow(
|
|||
tempDir,
|
||||
workspacePath,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
injectedMlQueries = injectedMlQueries || didInject;
|
||||
|
|
@ -1068,7 +1068,7 @@ export async function getDefaultConfig(
|
|||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
apiDetails: api.GitHubApiCombinedDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<Config> {
|
||||
const languages = await getLanguages(
|
||||
|
|
@ -1106,7 +1106,7 @@ export async function getDefaultConfig(
|
|||
tempDir,
|
||||
workspacePath,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
}
|
||||
|
|
@ -1176,7 +1176,7 @@ async function loadConfig(
|
|||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
apiDetails: api.GitHubApiCombinedDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<Config> {
|
||||
let parsedYAML: UserConfig;
|
||||
|
|
@ -1256,7 +1256,7 @@ async function loadConfig(
|
|||
tempDir,
|
||||
workspacePath,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
}
|
||||
|
|
@ -1281,7 +1281,7 @@ async function loadConfig(
|
|||
tempDir,
|
||||
workspacePath,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger,
|
||||
configFile
|
||||
);
|
||||
|
|
@ -1700,7 +1700,7 @@ export async function initConfig(
|
|||
workspacePath: string,
|
||||
gitHubVersion: GitHubVersion,
|
||||
apiDetails: api.GitHubApiCombinedDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<Config> {
|
||||
let config: Config;
|
||||
|
|
@ -1723,7 +1723,7 @@ export async function initConfig(
|
|||
workspacePath,
|
||||
gitHubVersion,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
} else {
|
||||
|
|
@ -1743,7 +1743,7 @@ export async function initConfig(
|
|||
workspacePath,
|
||||
gitHubVersion,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
}
|
||||
|
|
@ -1751,9 +1751,9 @@ 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.
|
||||
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
|
||||
// it is a user configuration error.
|
||||
// This check occurs in the CLI when it parses the config 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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages = [];
|
||||
const featureEnablement = setUpFeatureFlagTests(
|
||||
const features = setUpFeatureFlagTests(
|
||||
tmpDir,
|
||||
getRecordingLogger(loggedMessages),
|
||||
variant.gitHubVersion
|
||||
|
|
@ -55,10 +55,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
|
||||
for (const feature of Object.values(Feature)) {
|
||||
t.false(
|
||||
await featureEnablement.getValue(
|
||||
feature,
|
||||
includeCodeQlIfRequired(feature)
|
||||
)
|
||||
await features.getValue(feature, includeCodeQlIfRequired(feature))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +74,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
test("API response missing", async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages: LoggedMessage[] = [];
|
||||
const featureEnablement = setUpFeatureFlagTests(
|
||||
const features = setUpFeatureFlagTests(
|
||||
tmpDir,
|
||||
getRecordingLogger(loggedMessages)
|
||||
);
|
||||
|
|
@ -86,10 +83,8 @@ test("API response missing", async (t) => {
|
|||
|
||||
for (const feature of Object.values(Feature)) {
|
||||
t.assert(
|
||||
(await featureEnablement.getValue(
|
||||
feature,
|
||||
includeCodeQlIfRequired(feature)
|
||||
)) === false
|
||||
(await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
|
||||
false
|
||||
);
|
||||
}
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages: LoggedMessage[] = [];
|
||||
const featureEnablement = setUpFeatureFlagTests(
|
||||
const features = setUpFeatureFlagTests(
|
||||
tmpDir,
|
||||
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)) {
|
||||
t.assert(
|
||||
(await featureEnablement.getValue(
|
||||
feature,
|
||||
includeCodeQlIfRequired(feature)
|
||||
)) === false
|
||||
(await features.getValue(feature, 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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
mockFeatureFlagApiEndpoint(500, {});
|
||||
|
||||
await t.throwsAsync(
|
||||
async () =>
|
||||
featureEnablement.getValue(
|
||||
features.getValue(
|
||||
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)) {
|
||||
test(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
// set all features to false except the one we're testing
|
||||
const expectedFeatureEnablement: { [feature: string]: boolean } = {};
|
||||
|
|
@ -154,7 +147,7 @@ for (const feature of Object.keys(featureConfig)) {
|
|||
// retrieve the values of the actual features
|
||||
const actualFeatureEnablement: { [feature: string]: boolean } = {};
|
||||
for (const f of Object.keys(featureConfig)) {
|
||||
actualFeatureEnablement[f] = await featureEnablement.getValue(
|
||||
actualFeatureEnablement[f] = await features.getValue(
|
||||
f as Feature,
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
const expectedFeatureEnablement = initializeFeatures(false);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
// feature should be disabled initially
|
||||
t.assert(
|
||||
!(await featureEnablement.getValue(
|
||||
!(await features.getValue(
|
||||
feature as 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
|
||||
process.env[featureConfig[feature].envVar] = "true";
|
||||
t.assert(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
feature as 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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
// feature should be enabled initially
|
||||
t.assert(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
feature as 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
|
||||
process.env[featureConfig[feature].envVar] = "false";
|
||||
t.assert(
|
||||
!(await featureEnablement.getValue(
|
||||
!(await features.getValue(
|
||||
feature as Feature,
|
||||
includeCodeQlIfRequired(feature)
|
||||
))
|
||||
|
|
@ -220,17 +213,14 @@ for (const feature of Object.keys(featureConfig)) {
|
|||
if (featureConfig[feature].minimumVersion !== undefined) {
|
||||
test(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
await t.throwsAsync(
|
||||
async () => featureEnablement.getValue(feature as Feature),
|
||||
{
|
||||
message: `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`,
|
||||
}
|
||||
);
|
||||
await t.throwsAsync(async () => features.getValue(feature as Feature), {
|
||||
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) {
|
||||
test(`Feature '${feature}' is disabled if the minimum CLI version is below ${featureConfig[feature].minimumVersion}`, async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
// feature should be disabled when an old CLI version is set
|
||||
let codeql = mockCodeQLVersion("2.0.0");
|
||||
t.assert(
|
||||
!(await featureEnablement.getValue(feature as Feature, codeql))
|
||||
);
|
||||
t.assert(!(await features.getValue(feature as Feature, codeql)));
|
||||
|
||||
// even setting the env var to true should not enable the feature if
|
||||
// the minimum CLI version is not met
|
||||
process.env[featureConfig[feature].envVar] = "true";
|
||||
t.assert(
|
||||
!(await featureEnablement.getValue(feature as Feature, codeql))
|
||||
);
|
||||
t.assert(!(await features.getValue(feature as Feature, codeql)));
|
||||
|
||||
// feature should be enabled when a new CLI version is set
|
||||
// and env var is not set
|
||||
process.env[featureConfig[feature].envVar] = "";
|
||||
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
|
||||
process.env[featureConfig[feature].envVar] = "false";
|
||||
t.assert(
|
||||
!(await featureEnablement.getValue(feature as Feature, codeql))
|
||||
);
|
||||
t.assert(!(await features.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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
|
|
@ -304,7 +288,7 @@ test("Feature flags are saved to disk", async (t) => {
|
|||
);
|
||||
|
||||
t.true(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
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
|
||||
(featureEnablement as any).gitHubFeatureFlags.cachedApiResponse = undefined;
|
||||
(features as any).gitHubFeatureFlags.cachedApiResponse = undefined;
|
||||
|
||||
t.false(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
const cachedFeatureFlags = path.join(tmpDir, FEATURE_FLAGS_FILE_NAME);
|
||||
t.true(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
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";
|
||||
|
||||
t.false(
|
||||
await featureEnablement.getValue(
|
||||
await features.getValue(
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
expectedFeatureEnablement["default_codeql_version_2_12_0_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;
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(
|
||||
const defaultCliVersion = await features.getDefaultCliVersion(
|
||||
GitHubVariant.DOTCOM
|
||||
);
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||
const features = setUpFeatureFlagTests(tmpDir);
|
||||
const expectedFeatureEnablement = initializeFeatures(true);
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(
|
||||
const defaultCliVersion = await features.getDefaultCliVersion(
|
||||
GitHubVariant.DOTCOM
|
||||
);
|
||||
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) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages = [];
|
||||
const featureEnablement = setUpFeatureFlagTests(
|
||||
const features = setUpFeatureFlagTests(
|
||||
tmpDir,
|
||||
getRecordingLogger(loggedMessages)
|
||||
);
|
||||
|
|
@ -441,7 +425,7 @@ test("ignores invalid version numbers in default version feature flags", async (
|
|||
true;
|
||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||
|
||||
const defaultCliVersion = await featureEnablement.getDefaultCliVersion(
|
||||
const defaultCliVersion = await features.getDefaultCliVersion(
|
||||
GitHubVariant.DOTCOM
|
||||
);
|
||||
t.deepEqual(defaultCliVersion, {
|
||||
|
|
|
|||
|
|
@ -264,14 +264,14 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
const featureEnablement = response[feature];
|
||||
if (featureEnablement === undefined) {
|
||||
const features = response[feature];
|
||||
if (features === undefined) {
|
||||
this.logger.debug(
|
||||
`Feature '${feature}' undefined in API response, considering it disabled.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return !!featureEnablement;
|
||||
return !!features;
|
||||
}
|
||||
|
||||
private async getAllFeatures(): Promise<GitHubFeatureFlagsApiResponse> {
|
||||
|
|
|
|||
10
src/init.ts
10
src/init.ts
|
|
@ -68,7 +68,7 @@ export async function initConfig(
|
|||
workspacePath: string,
|
||||
gitHubVersion: util.GitHubVersion,
|
||||
apiDetails: GitHubApiCombinedDetails,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
): Promise<configUtils.Config> {
|
||||
logger.startGroup("Load language configuration");
|
||||
|
|
@ -89,7 +89,7 @@ export async function initConfig(
|
|||
workspacePath,
|
||||
gitHubVersion,
|
||||
apiDetails,
|
||||
featureEnablement,
|
||||
features,
|
||||
logger
|
||||
);
|
||||
analysisPaths.printPathFiltersWarning(config, logger);
|
||||
|
|
@ -103,7 +103,7 @@ export async function runInit(
|
|||
sourceRoot: string,
|
||||
processName: string | undefined,
|
||||
registriesInput: string | undefined,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
apiDetails: GitHubApiCombinedDetails,
|
||||
logger: Logger
|
||||
): 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.
|
||||
let registriesAuthTokens: string | undefined;
|
||||
let qlconfigFile: string | undefined;
|
||||
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
({ registriesAuthTokens, qlconfigFile } =
|
||||
await configUtils.generateRegistries(
|
||||
registriesInput,
|
||||
|
|
@ -138,7 +138,7 @@ export async function runInit(
|
|||
config,
|
||||
sourceRoot,
|
||||
processName,
|
||||
featureEnablement,
|
||||
features,
|
||||
qlconfigFile,
|
||||
logger
|
||||
)
|
||||
|
|
|
|||
|
|
@ -664,17 +664,17 @@ export function isInTestMode(): boolean {
|
|||
*/
|
||||
export async function useCodeScanningConfigInCli(
|
||||
codeql: CodeQL,
|
||||
featureEnablement: FeatureEnablement
|
||||
features: FeatureEnablement
|
||||
): Promise<boolean> {
|
||||
return await featureEnablement.getValue(Feature.CliConfigFileEnabled, codeql);
|
||||
return await features.getValue(Feature.CliConfigFileEnabled, codeql);
|
||||
}
|
||||
|
||||
export async function logCodeScanningConfigInCli(
|
||||
codeql: CodeQL,
|
||||
featureEnablement: FeatureEnablement,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger
|
||||
) {
|
||||
if (await useCodeScanningConfigInCli(codeql, featureEnablement)) {
|
||||
if (await useCodeScanningConfigInCli(codeql, features)) {
|
||||
logger.info(
|
||||
"Code Scanning configuration file being processed in the codeql CLI."
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue