mirror of
https://github.com/github/codeql-action.git
synced 2025-12-23 07:40:10 +08:00
build: refresh js files
This commit is contained in:
55
lib/codeql.js
generated
55
lib/codeql.js
generated
@@ -50,6 +50,7 @@ const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
|||||||
const yaml = __importStar(require("js-yaml"));
|
const yaml = __importStar(require("js-yaml"));
|
||||||
const actions_util_1 = require("./actions-util");
|
const actions_util_1 = require("./actions-util");
|
||||||
const cli_errors_1 = require("./cli-errors");
|
const cli_errors_1 = require("./cli-errors");
|
||||||
|
const config_utils_1 = require("./config-utils");
|
||||||
const doc_url_1 = require("./doc-url");
|
const doc_url_1 = require("./doc-url");
|
||||||
const environment_1 = require("./environment");
|
const environment_1 = require("./environment");
|
||||||
const feature_flags_1 = require("./feature-flags");
|
const feature_flags_1 = require("./feature-flags");
|
||||||
@@ -261,7 +262,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
|||||||
extraArgs.push(...(await getTrapCachingExtractorConfigArgs(config)));
|
extraArgs.push(...(await getTrapCachingExtractorConfigArgs(config)));
|
||||||
extraArgs.push(`--trace-process-name=${processName}`);
|
extraArgs.push(`--trace-process-name=${processName}`);
|
||||||
}
|
}
|
||||||
const codeScanningConfigFile = await generateCodeScanningConfig(config, logger);
|
const codeScanningConfigFile = await writeCodeScanningConfigFile(config, logger);
|
||||||
const externalRepositoryToken = (0, actions_util_1.getOptionalInput)("external-repository-token");
|
const externalRepositoryToken = (0, actions_util_1.getOptionalInput)("external-repository-token");
|
||||||
extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`);
|
extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`);
|
||||||
if (externalRepositoryToken) {
|
if (externalRepositoryToken) {
|
||||||
@@ -756,57 +757,9 @@ async function runCli(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(config, logger) {
|
async function writeCodeScanningConfigFile(config, logger) {
|
||||||
const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config);
|
const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config);
|
||||||
// make a copy so we can modify it
|
const augmentedConfig = (0, config_utils_1.generateCodeScanningConfig)(config.originalUserInput, config.augmentationProperties);
|
||||||
const augmentedConfig = (0, util_1.cloneObject)(config.originalUserInput);
|
|
||||||
// Inject the queries from the input
|
|
||||||
if (config.augmentationProperties.queriesInput) {
|
|
||||||
if (config.augmentationProperties.queriesInputCombines) {
|
|
||||||
augmentedConfig.queries = (augmentedConfig.queries || []).concat(config.augmentationProperties.queriesInput);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
augmentedConfig.queries = config.augmentationProperties.queriesInput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (augmentedConfig.queries?.length === 0) {
|
|
||||||
delete augmentedConfig.queries;
|
|
||||||
}
|
|
||||||
// Inject the packs from the input
|
|
||||||
if (config.augmentationProperties.packsInput) {
|
|
||||||
if (config.augmentationProperties.packsInputCombines) {
|
|
||||||
// At this point, we already know that this is a single-language analysis
|
|
||||||
if (Array.isArray(augmentedConfig.packs)) {
|
|
||||||
augmentedConfig.packs = (augmentedConfig.packs || []).concat(config.augmentationProperties.packsInput);
|
|
||||||
}
|
|
||||||
else if (!augmentedConfig.packs) {
|
|
||||||
augmentedConfig.packs = config.augmentationProperties.packsInput;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// At this point, we know there is only one language.
|
|
||||||
// If there were more than one language, an error would already have been thrown.
|
|
||||||
const language = Object.keys(augmentedConfig.packs)[0];
|
|
||||||
augmentedConfig.packs[language] = augmentedConfig.packs[language].concat(config.augmentationProperties.packsInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
augmentedConfig.packs = config.augmentationProperties.packsInput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Array.isArray(augmentedConfig.packs) && !augmentedConfig.packs.length) {
|
|
||||||
delete augmentedConfig.packs;
|
|
||||||
}
|
|
||||||
augmentedConfig["query-filters"] = [
|
|
||||||
// Ordering matters. If the first filter is an inclusion, it implicitly
|
|
||||||
// excludes all queries that are not included. If it is an exclusion,
|
|
||||||
// it implicitly includes all queries that are not excluded. So user
|
|
||||||
// filters (if any) should always be first to preserve intent.
|
|
||||||
...(augmentedConfig["query-filters"] || []),
|
|
||||||
...(config.augmentationProperties.extraQueryExclusions || []),
|
|
||||||
];
|
|
||||||
if (augmentedConfig["query-filters"]?.length === 0) {
|
|
||||||
delete augmentedConfig["query-filters"];
|
|
||||||
}
|
|
||||||
logger.info(`Writing augmented user configuration file to ${codeScanningConfigFile}`);
|
logger.info(`Writing augmented user configuration file to ${codeScanningConfigFile}`);
|
||||||
logger.startGroup("Augmented user configuration file contents");
|
logger.startGroup("Augmented user configuration file contents");
|
||||||
logger.info(yaml.dump(augmentedConfig));
|
logger.info(yaml.dump(augmentedConfig));
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
204
lib/config-utils.js
generated
204
lib/config-utils.js
generated
@@ -58,6 +58,7 @@ exports.getConfig = getConfig;
|
|||||||
exports.generateRegistries = generateRegistries;
|
exports.generateRegistries = generateRegistries;
|
||||||
exports.wrapEnvironment = wrapEnvironment;
|
exports.wrapEnvironment = wrapEnvironment;
|
||||||
exports.parseBuildModeInput = parseBuildModeInput;
|
exports.parseBuildModeInput = parseBuildModeInput;
|
||||||
|
exports.generateCodeScanningConfig = generateCodeScanningConfig;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const perf_hooks_1 = require("perf_hooks");
|
const perf_hooks_1 = require("perf_hooks");
|
||||||
@@ -231,12 +232,12 @@ async function getRawLanguages(languagesInput, repository, logger) {
|
|||||||
return { rawLanguages, autodetected };
|
return { rawLanguages, autodetected };
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the default config for when the user has not supplied one.
|
* Get the default config, populated without user configuration file.
|
||||||
*/
|
*/
|
||||||
async function getDefaultConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, sourceRoot, githubVersion, features, logger, }) {
|
async function getDefaultConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, githubVersion, features, logger, }) {
|
||||||
const languages = await getLanguages(codeql, languagesInput, repository, logger);
|
const languages = await getLanguages(codeql, languagesInput, repository, logger);
|
||||||
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
|
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
|
||||||
const augmentationProperties = await calculateAugmentation(codeql, repository, features, packsInput, queriesInput, qualityQueriesInput, languages, sourceRoot, buildMode, logger);
|
const augmentationProperties = await calculateAugmentation(packsInput, queriesInput, qualityQueriesInput, languages);
|
||||||
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
|
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
|
||||||
return {
|
return {
|
||||||
languages,
|
languages,
|
||||||
@@ -265,11 +266,7 @@ async function downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logg
|
|||||||
}
|
}
|
||||||
return { trapCaches, trapCacheDownloadTime };
|
return { trapCaches, trapCacheDownloadTime };
|
||||||
}
|
}
|
||||||
/**
|
async function loadUserConfig(configFile, workspacePath, apiDetails, tempDir) {
|
||||||
* Load the config from the given file.
|
|
||||||
*/
|
|
||||||
async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, packsInput, buildModeInput, configFile, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, workspacePath, sourceRoot, githubVersion, apiDetails, features, logger, }) {
|
|
||||||
let parsedYAML;
|
|
||||||
if (isLocal(configFile)) {
|
if (isLocal(configFile)) {
|
||||||
if (configFile !== userConfigFromActionPath(tempDir)) {
|
if (configFile !== userConfigFromActionPath(tempDir)) {
|
||||||
// If the config file is not generated by the Action, it should be relative to the workspace.
|
// If the config file is not generated by the Action, it should be relative to the workspace.
|
||||||
@@ -279,31 +276,11 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
|
|||||||
throw new util_1.ConfigurationError(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
throw new util_1.ConfigurationError(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsedYAML = getLocalConfig(configFile);
|
return getLocalConfig(configFile);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parsedYAML = await getRemoteConfig(configFile, apiDetails);
|
return await getRemoteConfig(configFile, apiDetails);
|
||||||
}
|
}
|
||||||
const languages = await getLanguages(codeql, languagesInput, repository, logger);
|
|
||||||
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
|
|
||||||
const augmentationProperties = await calculateAugmentation(codeql, repository, features, packsInput, queriesInput, qualityQueriesInput, languages, sourceRoot, buildMode, logger);
|
|
||||||
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
|
|
||||||
return {
|
|
||||||
languages,
|
|
||||||
buildMode,
|
|
||||||
originalUserInput: parsedYAML,
|
|
||||||
tempDir,
|
|
||||||
codeQLCmd: codeql.getPath(),
|
|
||||||
gitHubVersion: githubVersion,
|
|
||||||
dbLocation: dbLocationOrDefault(dbLocation, tempDir),
|
|
||||||
debugMode,
|
|
||||||
debugArtifactName,
|
|
||||||
debugDatabaseName,
|
|
||||||
augmentationProperties,
|
|
||||||
trapCaches,
|
|
||||||
trapCacheDownloadTime,
|
|
||||||
dependencyCachingEnabled: (0, caching_utils_1.getCachingKind)(dependencyCachingEnabled),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Calculates how the codeql config file needs to be augmented before passing
|
* Calculates how the codeql config file needs to be augmented before passing
|
||||||
@@ -312,17 +289,11 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
|
|||||||
* and the CLI does not know about these inputs so we need to inject them into
|
* and the CLI does not know about these inputs so we need to inject them into
|
||||||
* the config file sent to the CLI.
|
* the config file sent to the CLI.
|
||||||
*
|
*
|
||||||
* @param codeql The CodeQL object.
|
|
||||||
* @param repository The repository to analyze.
|
|
||||||
* @param features The feature enablement object.
|
|
||||||
* @param rawPacksInput The packs input from the action configuration.
|
* @param rawPacksInput The packs input from the action configuration.
|
||||||
* @param rawQueriesInput The queries input from the action configuration.
|
* @param rawQueriesInput The queries input from the action configuration.
|
||||||
* @param languages The languages that the config file is for. If the packs input
|
* @param languages The languages that the config file is for. If the packs input
|
||||||
* is non-empty, then there must be exactly one language. Otherwise, an
|
* is non-empty, then there must be exactly one language. Otherwise, an
|
||||||
* error is thrown.
|
* error is thrown.
|
||||||
* @param sourceRoot The source root of the repository.
|
|
||||||
* @param buildMode The build mode to use.
|
|
||||||
* @param logger The logger to use for logging.
|
|
||||||
*
|
*
|
||||||
* @returns The properties that need to be augmented in the config file.
|
* @returns The properties that need to be augmented in the config file.
|
||||||
*
|
*
|
||||||
@@ -330,30 +301,21 @@ async function loadConfig({ languagesInput, queriesInput, qualityQueriesInput, p
|
|||||||
* not have exactly one language.
|
* not have exactly one language.
|
||||||
*/
|
*/
|
||||||
// exported for testing.
|
// exported for testing.
|
||||||
async function calculateAugmentation(codeql, repository, features, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, sourceRoot, buildMode, logger) {
|
async function calculateAugmentation(rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages) {
|
||||||
const packsInputCombines = shouldCombine(rawPacksInput);
|
const packsInputCombines = shouldCombine(rawPacksInput);
|
||||||
const packsInput = parsePacksFromInput(rawPacksInput, languages, packsInputCombines);
|
const packsInput = parsePacksFromInput(rawPacksInput, languages, packsInputCombines);
|
||||||
const queriesInputCombines = shouldCombine(rawQueriesInput);
|
const queriesInputCombines = shouldCombine(rawQueriesInput);
|
||||||
const queriesInput = parseQueriesFromInput(rawQueriesInput, queriesInputCombines);
|
const queriesInput = parseQueriesFromInput(rawQueriesInput, queriesInputCombines);
|
||||||
const { overlayDatabaseMode, useOverlayDatabaseCaching } = await getOverlayDatabaseMode(codeql, repository, features, languages, sourceRoot, buildMode, logger);
|
|
||||||
logger.info(`Using overlay database mode: ${overlayDatabaseMode} ` +
|
|
||||||
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`);
|
|
||||||
const qualityQueriesInput = parseQueriesFromInput(rawQualityQueriesInput, false);
|
const qualityQueriesInput = parseQueriesFromInput(rawQualityQueriesInput, false);
|
||||||
const extraQueryExclusions = [];
|
|
||||||
if (await (0, diff_informed_analysis_utils_1.shouldPerformDiffInformedAnalysis)(codeql, features, logger)) {
|
|
||||||
extraQueryExclusions.push({
|
|
||||||
exclude: { tags: "exclude-from-incremental" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
packsInputCombines,
|
packsInputCombines,
|
||||||
packsInput: packsInput?.[languages[0]],
|
packsInput: packsInput?.[languages[0]],
|
||||||
queriesInput,
|
queriesInput,
|
||||||
queriesInputCombines,
|
queriesInputCombines,
|
||||||
qualityQueriesInput,
|
qualityQueriesInput,
|
||||||
extraQueryExclusions,
|
extraQueryExclusions: [],
|
||||||
overlayDatabaseMode,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
useOverlayDatabaseCaching,
|
useOverlayDatabaseCaching: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
||||||
@@ -368,6 +330,64 @@ function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
|||||||
}
|
}
|
||||||
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
|
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
|
||||||
}
|
}
|
||||||
|
const OVERLAY_ANALYSIS_FEATURES = {
|
||||||
|
actions: feature_flags_1.Feature.OverlayAnalysisActions,
|
||||||
|
cpp: feature_flags_1.Feature.OverlayAnalysisCpp,
|
||||||
|
csharp: feature_flags_1.Feature.OverlayAnalysisCsharp,
|
||||||
|
go: feature_flags_1.Feature.OverlayAnalysisGo,
|
||||||
|
java: feature_flags_1.Feature.OverlayAnalysisJava,
|
||||||
|
javascript: feature_flags_1.Feature.OverlayAnalysisJavascript,
|
||||||
|
python: feature_flags_1.Feature.OverlayAnalysisPython,
|
||||||
|
ruby: feature_flags_1.Feature.OverlayAnalysisRuby,
|
||||||
|
rust: feature_flags_1.Feature.OverlayAnalysisRust,
|
||||||
|
swift: feature_flags_1.Feature.OverlayAnalysisSwift,
|
||||||
|
};
|
||||||
|
const OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES = {
|
||||||
|
actions: feature_flags_1.Feature.OverlayAnalysisCodeScanningActions,
|
||||||
|
cpp: feature_flags_1.Feature.OverlayAnalysisCodeScanningCpp,
|
||||||
|
csharp: feature_flags_1.Feature.OverlayAnalysisCodeScanningCsharp,
|
||||||
|
go: feature_flags_1.Feature.OverlayAnalysisCodeScanningGo,
|
||||||
|
java: feature_flags_1.Feature.OverlayAnalysisCodeScanningJava,
|
||||||
|
javascript: feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
python: feature_flags_1.Feature.OverlayAnalysisCodeScanningPython,
|
||||||
|
ruby: feature_flags_1.Feature.OverlayAnalysisCodeScanningRuby,
|
||||||
|
rust: feature_flags_1.Feature.OverlayAnalysisCodeScanningRust,
|
||||||
|
swift: feature_flags_1.Feature.OverlayAnalysisCodeScanningSwift,
|
||||||
|
};
|
||||||
|
async function isOverlayAnalysisFeatureEnabled(repository, features, codeql, languages, codeScanningConfig) {
|
||||||
|
// TODO: Remove the repository owner check once support for overlay analysis
|
||||||
|
// stabilizes, and no more backward-incompatible changes are expected.
|
||||||
|
if (!["github", "dsp-testing"].includes(repository.owner)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(await features.getValue(feature_flags_1.Feature.OverlayAnalysis, codeql))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let enableForCodeScanningOnly = false;
|
||||||
|
for (const language of languages) {
|
||||||
|
const feature = OVERLAY_ANALYSIS_FEATURES[language];
|
||||||
|
if (feature && (await features.getValue(feature, codeql))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const codeScanningFeature = OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES[language];
|
||||||
|
if (codeScanningFeature &&
|
||||||
|
(await features.getValue(codeScanningFeature, codeql))) {
|
||||||
|
enableForCodeScanningOnly = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (enableForCodeScanningOnly) {
|
||||||
|
// A code-scanning configuration runs only the (default) code-scanning suite
|
||||||
|
// if the default queries are not disabled, and no packs, queries, or
|
||||||
|
// query-filters are specified.
|
||||||
|
return (codeScanningConfig["disable-default-queries"] !== true &&
|
||||||
|
codeScanningConfig.packs === undefined &&
|
||||||
|
codeScanningConfig.queries === undefined &&
|
||||||
|
codeScanningConfig["query-filters"] === undefined);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Calculate and validate the overlay database mode and caching to use.
|
* Calculate and validate the overlay database mode and caching to use.
|
||||||
*
|
*
|
||||||
@@ -389,7 +409,7 @@ function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
|||||||
* @returns An object containing the overlay database mode and whether the
|
* @returns An object containing the overlay database mode and whether the
|
||||||
* action should perform overlay-base database caching.
|
* action should perform overlay-base database caching.
|
||||||
*/
|
*/
|
||||||
async function getOverlayDatabaseMode(codeql, repository, features, languages, sourceRoot, buildMode, logger) {
|
async function getOverlayDatabaseMode(codeql, repository, features, languages, sourceRoot, buildMode, codeScanningConfig, logger) {
|
||||||
let overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.None;
|
let overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.None;
|
||||||
let useOverlayDatabaseCaching = false;
|
let useOverlayDatabaseCaching = false;
|
||||||
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
|
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
|
||||||
@@ -402,11 +422,7 @@ async function getOverlayDatabaseMode(codeql, repository, features, languages, s
|
|||||||
logger.info(`Setting overlay database mode to ${overlayDatabaseMode} ` +
|
logger.info(`Setting overlay database mode to ${overlayDatabaseMode} ` +
|
||||||
"from the CODEQL_OVERLAY_DATABASE_MODE environment variable.");
|
"from the CODEQL_OVERLAY_DATABASE_MODE environment variable.");
|
||||||
}
|
}
|
||||||
else if (
|
else if (await isOverlayAnalysisFeatureEnabled(repository, features, codeql, languages, codeScanningConfig)) {
|
||||||
// TODO: Remove the repository owner check once support for overlay analysis
|
|
||||||
// stabilizes, and no more backward-incompatible changes are expected.
|
|
||||||
["github", "dsp-testing"].includes(repository.owner) &&
|
|
||||||
(await features.getValue(feature_flags_1.Feature.OverlayAnalysis, codeql))) {
|
|
||||||
if ((0, actions_util_1.isAnalyzingPullRequest)()) {
|
if ((0, actions_util_1.isAnalyzingPullRequest)()) {
|
||||||
overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.Overlay;
|
overlayDatabaseMode = overlay_database_utils_1.OverlayDatabaseMode.Overlay;
|
||||||
useOverlayDatabaseCaching = true;
|
useOverlayDatabaseCaching = true;
|
||||||
@@ -586,7 +602,6 @@ function userConfigFromActionPath(tempDir) {
|
|||||||
* 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(inputs) {
|
async function initConfig(inputs) {
|
||||||
let config;
|
|
||||||
const { logger, tempDir } = inputs;
|
const { logger, tempDir } = inputs;
|
||||||
// if configInput is set, it takes precedence over configFile
|
// if configInput is set, it takes precedence over configFile
|
||||||
if (inputs.configInput) {
|
if (inputs.configInput) {
|
||||||
@@ -597,14 +612,31 @@ async function initConfig(inputs) {
|
|||||||
fs.writeFileSync(inputs.configFile, inputs.configInput);
|
fs.writeFileSync(inputs.configFile, inputs.configInput);
|
||||||
logger.debug(`Using config from action input: ${inputs.configFile}`);
|
logger.debug(`Using config from action input: ${inputs.configFile}`);
|
||||||
}
|
}
|
||||||
// If no config file was provided create an empty one
|
let userConfig = {};
|
||||||
if (!inputs.configFile) {
|
if (!inputs.configFile) {
|
||||||
logger.debug("No configuration file was provided");
|
logger.debug("No configuration file was provided");
|
||||||
config = await getDefaultConfig(inputs);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Convince the type checker that inputs.configFile is defined.
|
logger.debug(`Using configuration file: ${inputs.configFile}`);
|
||||||
config = await loadConfig({ ...inputs, configFile: inputs.configFile });
|
userConfig = await loadUserConfig(inputs.configFile, inputs.workspacePath, inputs.apiDetails, tempDir);
|
||||||
|
}
|
||||||
|
const config = await getDefaultConfig(inputs);
|
||||||
|
const augmentationProperties = config.augmentationProperties;
|
||||||
|
config.originalUserInput = userConfig;
|
||||||
|
// The choice of overlay database mode depends on the selection of languages
|
||||||
|
// and queries, which in turn depends on the user config and the augmentation
|
||||||
|
// properties. So we need to calculate the overlay database mode after the
|
||||||
|
// rest of the config has been populated.
|
||||||
|
const { overlayDatabaseMode, useOverlayDatabaseCaching } = await getOverlayDatabaseMode(inputs.codeql, inputs.repository, inputs.features, config.languages, inputs.sourceRoot, config.buildMode, generateCodeScanningConfig(userConfig, augmentationProperties), logger);
|
||||||
|
logger.info(`Using overlay database mode: ${overlayDatabaseMode} ` +
|
||||||
|
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`);
|
||||||
|
augmentationProperties.overlayDatabaseMode = overlayDatabaseMode;
|
||||||
|
augmentationProperties.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
|
||||||
|
if (overlayDatabaseMode === overlay_database_utils_1.OverlayDatabaseMode.Overlay ||
|
||||||
|
(await (0, diff_informed_analysis_utils_1.shouldPerformDiffInformedAnalysis)(inputs.codeql, inputs.features, logger))) {
|
||||||
|
augmentationProperties.extraQueryExclusions.push({
|
||||||
|
exclude: { tags: "exclude-from-incremental" },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Save the config so we can easily access it again in the future
|
// Save the config so we can easily access it again in the future
|
||||||
await saveConfig(config, logger);
|
await saveConfig(config, logger);
|
||||||
@@ -807,4 +839,56 @@ async function parseBuildModeInput(input, languages, features, logger) {
|
|||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
function generateCodeScanningConfig(originalUserInput, augmentationProperties) {
|
||||||
|
// make a copy so we can modify it
|
||||||
|
const augmentedConfig = (0, util_1.cloneObject)(originalUserInput);
|
||||||
|
// Inject the queries from the input
|
||||||
|
if (augmentationProperties.queriesInput) {
|
||||||
|
if (augmentationProperties.queriesInputCombines) {
|
||||||
|
augmentedConfig.queries = (augmentedConfig.queries || []).concat(augmentationProperties.queriesInput);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
augmentedConfig.queries = augmentationProperties.queriesInput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (augmentedConfig.queries?.length === 0) {
|
||||||
|
delete augmentedConfig.queries;
|
||||||
|
}
|
||||||
|
// Inject the packs from the input
|
||||||
|
if (augmentationProperties.packsInput) {
|
||||||
|
if (augmentationProperties.packsInputCombines) {
|
||||||
|
// At this point, we already know that this is a single-language analysis
|
||||||
|
if (Array.isArray(augmentedConfig.packs)) {
|
||||||
|
augmentedConfig.packs = (augmentedConfig.packs || []).concat(augmentationProperties.packsInput);
|
||||||
|
}
|
||||||
|
else if (!augmentedConfig.packs) {
|
||||||
|
augmentedConfig.packs = augmentationProperties.packsInput;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// At this point, we know there is only one language.
|
||||||
|
// If there were more than one language, an error would already have been thrown.
|
||||||
|
const language = Object.keys(augmentedConfig.packs)[0];
|
||||||
|
augmentedConfig.packs[language] = augmentedConfig.packs[language].concat(augmentationProperties.packsInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
augmentedConfig.packs = augmentationProperties.packsInput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(augmentedConfig.packs) && !augmentedConfig.packs.length) {
|
||||||
|
delete augmentedConfig.packs;
|
||||||
|
}
|
||||||
|
augmentedConfig["query-filters"] = [
|
||||||
|
// Ordering matters. If the first filter is an inclusion, it implicitly
|
||||||
|
// excludes all queries that are not included. If it is an exclusion,
|
||||||
|
// it implicitly includes all queries that are not excluded. So user
|
||||||
|
// filters (if any) should always be first to preserve intent.
|
||||||
|
...(augmentedConfig["query-filters"] || []),
|
||||||
|
...augmentationProperties.extraQueryExclusions,
|
||||||
|
];
|
||||||
|
if (augmentedConfig["query-filters"]?.length === 0) {
|
||||||
|
delete augmentedConfig["query-filters"];
|
||||||
|
}
|
||||||
|
return augmentedConfig;
|
||||||
|
}
|
||||||
//# sourceMappingURL=config-utils.js.map
|
//# sourceMappingURL=config-utils.js.map
|
||||||
File diff suppressed because one or more lines are too long
237
lib/config-utils.test.js
generated
237
lib/config-utils.test.js
generated
@@ -629,9 +629,7 @@ const packSpecPrettyPrintingMacro = ava_1.default.macro({
|
|||||||
const mockLogger = (0, logging_1.getRunnerLogger)(true);
|
const mockLogger = (0, logging_1.getRunnerLogger)(true);
|
||||||
const calculateAugmentationMacro = ava_1.default.macro({
|
const calculateAugmentationMacro = ava_1.default.macro({
|
||||||
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedAugmentationProperties) => {
|
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedAugmentationProperties) => {
|
||||||
const actualAugmentationProperties = await configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), { owner: "github", repo: "repo" }, (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, "", // sourceRoot
|
const actualAugmentationProperties = await configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages);
|
||||||
undefined, // buildMode
|
|
||||||
mockLogger);
|
|
||||||
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
|
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
|
||||||
},
|
},
|
||||||
title: (_, title) => `Calculate Augmentation: ${title}`,
|
title: (_, title) => `Calculate Augmentation: ${title}`,
|
||||||
@@ -678,9 +676,7 @@ const calculateAugmentationMacro = ava_1.default.macro({
|
|||||||
});
|
});
|
||||||
const calculateAugmentationErrorMacro = ava_1.default.macro({
|
const calculateAugmentationErrorMacro = ava_1.default.macro({
|
||||||
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedError) => {
|
exec: async (t, _title, rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, expectedError) => {
|
||||||
await t.throwsAsync(() => configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), { owner: "github", repo: "repo" }, (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages, "", // sourceRoot
|
await t.throwsAsync(() => configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, rawQualityQueriesInput, languages), { message: expectedError });
|
||||||
undefined, // buildMode
|
|
||||||
mockLogger), { message: expectedError });
|
|
||||||
},
|
},
|
||||||
title: (_, title) => `Calculate Augmentation Error: ${title}`,
|
title: (_, title) => `Calculate Augmentation Error: ${title}`,
|
||||||
});
|
});
|
||||||
@@ -834,7 +830,7 @@ for (const { displayName, language, feature } of [
|
|||||||
}
|
}
|
||||||
const defaultOverlayDatabaseModeTestSetup = {
|
const defaultOverlayDatabaseModeTestSetup = {
|
||||||
overlayDatabaseEnvVar: undefined,
|
overlayDatabaseEnvVar: undefined,
|
||||||
isFeatureEnabled: false,
|
features: [],
|
||||||
isPullRequest: false,
|
isPullRequest: false,
|
||||||
isDefaultBranch: false,
|
isDefaultBranch: false,
|
||||||
repositoryOwner: "github",
|
repositoryOwner: "github",
|
||||||
@@ -842,6 +838,7 @@ const defaultOverlayDatabaseModeTestSetup = {
|
|||||||
languages: [languages_1.Language.javascript],
|
languages: [languages_1.Language.javascript],
|
||||||
codeqlVersion: "2.21.0",
|
codeqlVersion: "2.21.0",
|
||||||
gitRoot: "/some/git/root",
|
gitRoot: "/some/git/root",
|
||||||
|
codeScanningConfig: {},
|
||||||
};
|
};
|
||||||
const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
||||||
exec: async (t, _title, setupOverrides, expected) => {
|
exec: async (t, _title, setupOverrides, expected) => {
|
||||||
@@ -862,7 +859,7 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
setup.overlayDatabaseEnvVar;
|
setup.overlayDatabaseEnvVar;
|
||||||
}
|
}
|
||||||
// Mock feature flags
|
// Mock feature flags
|
||||||
const features = (0, testing_utils_1.createFeatures)(setup.isFeatureEnabled ? [feature_flags_1.Feature.OverlayAnalysis] : []);
|
const features = (0, testing_utils_1.createFeatures)(setup.features);
|
||||||
// Mock isAnalyzingPullRequest function
|
// Mock isAnalyzingPullRequest function
|
||||||
sinon
|
sinon
|
||||||
.stub(actionsUtil, "isAnalyzingPullRequest")
|
.stub(actionsUtil, "isAnalyzingPullRequest")
|
||||||
@@ -883,7 +880,7 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
.stub(gitUtils, "isAnalyzingDefaultBranch")
|
.stub(gitUtils, "isAnalyzingDefaultBranch")
|
||||||
.resolves(setup.isDefaultBranch);
|
.resolves(setup.isDefaultBranch);
|
||||||
const result = await configUtils.getOverlayDatabaseMode(codeql, repository, features, setup.languages, tempDir, // sourceRoot
|
const result = await configUtils.getOverlayDatabaseMode(codeql, repository, features, setup.languages, tempDir, // sourceRoot
|
||||||
setup.buildMode, logger);
|
setup.buildMode, setup.codeScanningConfig, logger);
|
||||||
t.deepEqual(result, expected);
|
t.deepEqual(result, expected);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -919,32 +916,227 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
useOverlayDatabaseCaching: false,
|
useOverlayDatabaseCaching: false,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Ignore feature flag when analyzing non-default branch", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Ignore feature flag when analyzing non-default branch", {
|
||||||
isFeatureEnabled: true,
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
}, {
|
}, {
|
||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
useOverlayDatabaseCaching: false,
|
useOverlayDatabaseCaching: false,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay-base database on default branch when feature enabled", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay-base database on default branch when feature enabled", {
|
||||||
isFeatureEnabled: true,
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
}, {
|
}, {
|
||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
|
||||||
useOverlayDatabaseCaching: true,
|
useOverlayDatabaseCaching: true,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when feature disabled", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay-base database on default branch when feature enabled with custom analysis", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
|
codeScanningConfig: {
|
||||||
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
|
},
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
|
||||||
|
useOverlayDatabaseCaching: true,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay-base database on default branch when code-scanning feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.OverlayBase,
|
||||||
|
useOverlayDatabaseCaching: true,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
"disable-default-queries": true,
|
||||||
|
},
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when code-scanning feature enabled with packs", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
|
},
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when code-scanning feature enabled with queries", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
queries: [{ uses: "some-query.ql" }],
|
||||||
|
},
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when code-scanning feature enabled with query-filters", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
"query-filters": [{ include: { "security-severity": "high" } }],
|
||||||
|
},
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when only language-specific feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when only code-scanning feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript],
|
||||||
|
isDefaultBranch: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay-base database on default branch when language-specific feature disabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis],
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
}, {
|
}, {
|
||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
useOverlayDatabaseCaching: false,
|
useOverlayDatabaseCaching: false,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay analysis on PR when feature enabled", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay analysis on PR when feature enabled", {
|
||||||
isFeatureEnabled: true,
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
}, {
|
}, {
|
||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
|
||||||
useOverlayDatabaseCaching: true,
|
useOverlayDatabaseCaching: true,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when feature disabled", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay analysis on PR when feature enabled with custom analysis", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
|
codeScanningConfig: {
|
||||||
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
|
},
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
|
||||||
|
useOverlayDatabaseCaching: true,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay analysis on PR when code-scanning feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.Overlay,
|
||||||
|
useOverlayDatabaseCaching: true,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when code-scanning feature enabled with disable-default-queries", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
"disable-default-queries": true,
|
||||||
|
},
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when code-scanning feature enabled with packs", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
|
},
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when code-scanning feature enabled with queries", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
queries: [{ uses: "some-query.ql" }],
|
||||||
|
},
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when code-scanning feature enabled with query-filters", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [
|
||||||
|
feature_flags_1.Feature.OverlayAnalysis,
|
||||||
|
feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript,
|
||||||
|
],
|
||||||
|
codeScanningConfig: {
|
||||||
|
"query-filters": [{ include: { "security-severity": "high" } }],
|
||||||
|
},
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when only language-specific feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when only code-scanning feature enabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysisCodeScanningJavascript],
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay analysis on PR when language-specific feature disabled", {
|
||||||
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis],
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
}, {
|
}, {
|
||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
@@ -965,7 +1157,8 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
useOverlayDatabaseCaching: false,
|
useOverlayDatabaseCaching: false,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay PR analysis by feature flag for dsp-testing", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "Overlay PR analysis by feature flag for dsp-testing", {
|
||||||
isFeatureEnabled: true,
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
repositoryOwner: "dsp-testing",
|
repositoryOwner: "dsp-testing",
|
||||||
}, {
|
}, {
|
||||||
@@ -973,7 +1166,8 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
useOverlayDatabaseCaching: true,
|
useOverlayDatabaseCaching: true,
|
||||||
});
|
});
|
||||||
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay PR analysis by feature flag for other-org", {
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, "No overlay PR analysis by feature flag for other-org", {
|
||||||
isFeatureEnabled: true,
|
languages: [languages_1.Language.javascript],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis, feature_flags_1.Feature.OverlayAnalysisJavascript],
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
repositoryOwner: "other-org",
|
repositoryOwner: "other-org",
|
||||||
}, {
|
}, {
|
||||||
@@ -1010,4 +1204,15 @@ const getOverlayDatabaseModeMacro = ava_1.default.macro({
|
|||||||
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
useOverlayDatabaseCaching: false,
|
useOverlayDatabaseCaching: false,
|
||||||
});
|
});
|
||||||
|
// Exercise language-specific overlay analysis features code paths
|
||||||
|
for (const language in languages_1.Language) {
|
||||||
|
(0, ava_1.default)(getOverlayDatabaseModeMacro, `Check default overlay analysis feature for ${language}`, {
|
||||||
|
languages: [language],
|
||||||
|
features: [feature_flags_1.Feature.OverlayAnalysis],
|
||||||
|
isPullRequest: true,
|
||||||
|
}, {
|
||||||
|
overlayDatabaseMode: overlay_database_utils_1.OverlayDatabaseMode.None,
|
||||||
|
useOverlayDatabaseCaching: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
//# sourceMappingURL=config-utils.test.js.map
|
//# sourceMappingURL=config-utils.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
144
lib/feature-flags.js
generated
144
lib/feature-flags.js
generated
@@ -69,6 +69,26 @@ var Feature;
|
|||||||
Feature["ExportDiagnosticsEnabled"] = "export_diagnostics_enabled";
|
Feature["ExportDiagnosticsEnabled"] = "export_diagnostics_enabled";
|
||||||
Feature["ExtractToToolcache"] = "extract_to_toolcache";
|
Feature["ExtractToToolcache"] = "extract_to_toolcache";
|
||||||
Feature["OverlayAnalysis"] = "overlay_analysis";
|
Feature["OverlayAnalysis"] = "overlay_analysis";
|
||||||
|
Feature["OverlayAnalysisActions"] = "overlay_analysis_actions";
|
||||||
|
Feature["OverlayAnalysisCodeScanningActions"] = "overlay_analysis_code_scanning_actions";
|
||||||
|
Feature["OverlayAnalysisCodeScanningCpp"] = "overlay_analysis_code_scanning_cpp";
|
||||||
|
Feature["OverlayAnalysisCodeScanningCsharp"] = "overlay_analysis_code_scanning_csharp";
|
||||||
|
Feature["OverlayAnalysisCodeScanningGo"] = "overlay_analysis_code_scanning_go";
|
||||||
|
Feature["OverlayAnalysisCodeScanningJava"] = "overlay_analysis_code_scanning_java";
|
||||||
|
Feature["OverlayAnalysisCodeScanningJavascript"] = "overlay_analysis_code_scanning_javascript";
|
||||||
|
Feature["OverlayAnalysisCodeScanningPython"] = "overlay_analysis_code_scanning_python";
|
||||||
|
Feature["OverlayAnalysisCodeScanningRuby"] = "overlay_analysis_code_scanning_ruby";
|
||||||
|
Feature["OverlayAnalysisCodeScanningRust"] = "overlay_analysis_code_scanning_rust";
|
||||||
|
Feature["OverlayAnalysisCodeScanningSwift"] = "overlay_analysis_code_scanning_swift";
|
||||||
|
Feature["OverlayAnalysisCpp"] = "overlay_analysis_cpp";
|
||||||
|
Feature["OverlayAnalysisCsharp"] = "overlay_analysis_csharp";
|
||||||
|
Feature["OverlayAnalysisGo"] = "overlay_analysis_go";
|
||||||
|
Feature["OverlayAnalysisJava"] = "overlay_analysis_java";
|
||||||
|
Feature["OverlayAnalysisJavascript"] = "overlay_analysis_javascript";
|
||||||
|
Feature["OverlayAnalysisPython"] = "overlay_analysis_python";
|
||||||
|
Feature["OverlayAnalysisRuby"] = "overlay_analysis_ruby";
|
||||||
|
Feature["OverlayAnalysisRust"] = "overlay_analysis_rust";
|
||||||
|
Feature["OverlayAnalysisSwift"] = "overlay_analysis_swift";
|
||||||
Feature["PythonDefaultIsToNotExtractStdlib"] = "python_default_is_to_not_extract_stdlib";
|
Feature["PythonDefaultIsToNotExtractStdlib"] = "python_default_is_to_not_extract_stdlib";
|
||||||
Feature["QaTelemetryEnabled"] = "qa_telemetry_enabled";
|
Feature["QaTelemetryEnabled"] = "qa_telemetry_enabled";
|
||||||
Feature["RustAnalysis"] = "rust_analysis";
|
Feature["RustAnalysis"] = "rust_analysis";
|
||||||
@@ -139,6 +159,106 @@ exports.featureConfig = {
|
|||||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS",
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS",
|
||||||
minimumVersion: overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION,
|
minimumVersion: overlay_database_utils_1.CODEQL_OVERLAY_MINIMUM_VERSION,
|
||||||
},
|
},
|
||||||
|
[Feature.OverlayAnalysisActions]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_ACTIONS",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningActions]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_ACTIONS",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningCpp]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_CPP",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningCsharp]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_CSHARP",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningGo]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_GO",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningJava]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_JAVA",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningJavascript]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_JAVASCRIPT",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningPython]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_PYTHON",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningRuby]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_RUBY",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningRust]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_RUST",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCodeScanningSwift]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_SWIFT",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCpp]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CPP",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisCsharp]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisGo]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisJava]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_JAVA",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisJavascript]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_JAVASCRIPT",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisPython]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisRuby]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisRust]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUST",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[Feature.OverlayAnalysisSwift]: {
|
||||||
|
defaultValue: false,
|
||||||
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_SWIFT",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
[Feature.PythonDefaultIsToNotExtractStdlib]: {
|
[Feature.PythonDefaultIsToNotExtractStdlib]: {
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",
|
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",
|
||||||
@@ -370,14 +490,22 @@ class GitHubFeatureFlags {
|
|||||||
try {
|
try {
|
||||||
const featuresToRequest = Object.entries(exports.featureConfig)
|
const featuresToRequest = Object.entries(exports.featureConfig)
|
||||||
.filter(([, config]) => !config.legacyApi)
|
.filter(([, config]) => !config.legacyApi)
|
||||||
.map(([f]) => f)
|
.map(([f]) => f);
|
||||||
.join(",");
|
const FEATURES_PER_REQUEST = 25;
|
||||||
const response = await (0, api_client_1.getApiClient)().request("GET /repos/:owner/:repo/code-scanning/codeql-action/features", {
|
const featureChunks = [];
|
||||||
owner: this.repositoryNwo.owner,
|
while (featuresToRequest.length > 0) {
|
||||||
repo: this.repositoryNwo.repo,
|
featureChunks.push(featuresToRequest.splice(0, FEATURES_PER_REQUEST));
|
||||||
features: featuresToRequest,
|
}
|
||||||
});
|
let remoteFlags = {};
|
||||||
const remoteFlags = response.data;
|
for (const chunk of featureChunks) {
|
||||||
|
const response = await (0, api_client_1.getApiClient)().request("GET /repos/:owner/:repo/code-scanning/codeql-action/features", {
|
||||||
|
owner: this.repositoryNwo.owner,
|
||||||
|
repo: this.repositoryNwo.repo,
|
||||||
|
features: chunk.join(","),
|
||||||
|
});
|
||||||
|
const chunkFlags = response.data;
|
||||||
|
remoteFlags = { ...remoteFlags, ...chunkFlags };
|
||||||
|
}
|
||||||
this.logger.debug("Loaded the following default values for the feature flags from the Code Scanning API:");
|
this.logger.debug("Loaded the following default values for the feature flags from the Code Scanning API:");
|
||||||
for (const [feature, value] of Object.entries(remoteFlags).sort(([nameA], [nameB]) => nameA.localeCompare(nameB))) {
|
for (const [feature, value] of Object.entries(remoteFlags).sort(([nameA], [nameB]) => nameA.localeCompare(nameB))) {
|
||||||
this.logger.debug(` ${feature}: ${value}`);
|
this.logger.debug(` ${feature}: ${value}`);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
49
lib/feature-flags.test.js
generated
49
lib/feature-flags.test.js
generated
@@ -36,7 +36,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.initializeFeatures = initializeFeatures;
|
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
@@ -68,7 +67,7 @@ const testRepositoryNwo = (0, repository_1.parseRepositoryNwo)("github/example")
|
|||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), { type: util_1.GitHubVariant.GHE_DOTCOM });
|
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), { type: util_1.GitHubVariant.GHE_DOTCOM });
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, initializeFeatures(true));
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, (0, testing_utils_1.initializeFeatures)(true));
|
||||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||||
// Ensure we have gotten a response value back from the Mock API
|
// Ensure we have gotten a response value back from the Mock API
|
||||||
t.assert(await features.getValue(feature, includeCodeQlIfRequired(feature)));
|
t.assert(await features.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||||
@@ -103,6 +102,24 @@ const testRepositoryNwo = (0, repository_1.parseRepositoryNwo)("github/example")
|
|||||||
assertAllFeaturesUndefinedInApi(t, loggedMessages);
|
assertAllFeaturesUndefinedInApi(t, loggedMessages);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
(0, ava_1.default)("Include no more than 25 features in each API request", async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
|
(0, testing_utils_1.stubFeatureFlagApiEndpoint)((request) => {
|
||||||
|
const requestedFeatures = request.features.split(",");
|
||||||
|
return {
|
||||||
|
status: requestedFeatures.length <= 25 ? 200 : 400,
|
||||||
|
messageIfError: "Can request a maximum of 25 features.",
|
||||||
|
data: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// We only need to call getValue once, and it does not matter which feature
|
||||||
|
// we ask for. Under the hood, the features library will request all features
|
||||||
|
// from the API.
|
||||||
|
const feature = Object.values(feature_flags_1.Feature)[0];
|
||||||
|
await t.notThrowsAsync(async () => features.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||||
|
});
|
||||||
|
});
|
||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
@@ -135,7 +152,7 @@ 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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(false);
|
const expectedFeatureEnablement = (0, testing_utils_1.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 features.getValue(feature, includeCodeQlIfRequired(feature))));
|
t.assert(!(await features.getValue(feature, includeCodeQlIfRequired(feature))));
|
||||||
@@ -147,7 +164,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.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 features.getValue(feature, includeCodeQlIfRequired(feature)));
|
t.assert(await features.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||||
@@ -161,7 +178,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
await t.throwsAsync(async () => features.getValue(feature), {
|
await t.throwsAsync(async () => features.getValue(feature), {
|
||||||
message: `Internal error: A ${feature_flags_1.featureConfig[feature].minimumVersion !== undefined
|
message: `Internal error: A ${feature_flags_1.featureConfig[feature].minimumVersion !== undefined
|
||||||
@@ -175,7 +192,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.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");
|
||||||
@@ -199,7 +216,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(0, ava_1.default)(`Feature '${feature}' is disabled if the required tools feature is not enabled`, async (t) => {
|
(0, ava_1.default)(`Feature '${feature}' is disabled if the required tools feature is not enabled`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
// feature should be disabled when the required tools feature is not enabled
|
// feature should be disabled when the required tools feature is not enabled
|
||||||
let codeql = (0, testing_utils_1.mockCodeQLVersion)("2.0.0");
|
let codeql = (0, testing_utils_1.mockCodeQLVersion)("2.0.0");
|
||||||
@@ -225,7 +242,7 @@ 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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.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");
|
||||||
@@ -244,7 +261,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.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 features.getValue(feature_flags_1.Feature.QaTelemetryEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.QaTelemetryEnabled)), "Feature flag should be enabled initially");
|
t.true(await features.getValue(feature_flags_1.Feature.QaTelemetryEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.QaTelemetryEnabled)), "Feature flag should be enabled initially");
|
||||||
@@ -266,7 +283,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(0, ava_1.default)("selects CLI v2.20.1 on Dotcom when feature flags enable v2.20.0 and v2.20.1", async (t) => {
|
(0, ava_1.default)("selects CLI v2.20.1 on Dotcom when feature flags enable v2.20.0 and v2.20.1", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
|
expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_2_enabled"] = false;
|
expectedFeatureEnablement["default_codeql_version_2_20_2_enabled"] = false;
|
||||||
@@ -285,7 +302,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(0, ava_1.default)("includes tag name", async (t) => {
|
(0, ava_1.default)("includes tag name", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
|
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
|
||||||
@@ -299,7 +316,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
(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 features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
|
const defaultCliVersion = await features.getDefaultCliVersion(util_1.GitHubVariant.DOTCOM);
|
||||||
t.deepEqual(defaultCliVersion, {
|
t.deepEqual(defaultCliVersion, {
|
||||||
@@ -313,7 +330,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
expectedFeatureEnablement["default_codeql_version_2_20_0_enabled"] = true;
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
|
expectedFeatureEnablement["default_codeql_version_2_20_1_enabled"] = true;
|
||||||
expectedFeatureEnablement["default_codeql_version_2_20_invalid_enabled"] =
|
expectedFeatureEnablement["default_codeql_version_2_20_invalid_enabled"] =
|
||||||
@@ -358,12 +375,6 @@ function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
|||||||
v.message.includes("undefined in API response")) !== undefined);
|
v.message.includes("undefined in API response")) !== undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function initializeFeatures(initialValue) {
|
|
||||||
return Object.keys(feature_flags_1.featureConfig).reduce((features, key) => {
|
|
||||||
features[key] = initialValue;
|
|
||||||
return features;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
function setUpFeatureFlagTests(tmpDir, logger = (0, logging_1.getRunnerLogger)(true), gitHubVersion = { type: util_1.GitHubVariant.DOTCOM }) {
|
function setUpFeatureFlagTests(tmpDir, logger = (0, logging_1.getRunnerLogger)(true), gitHubVersion = { type: util_1.GitHubVariant.DOTCOM }) {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
return new feature_flags_1.Features(gitHubVersion, testRepositoryNwo, tmpDir, logger);
|
return new feature_flags_1.Features(gitHubVersion, testRepositoryNwo, tmpDir, logger);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
3
lib/setup-codeql.test.js
generated
3
lib/setup-codeql.test.js
generated
@@ -40,14 +40,13 @@ const path = __importStar(require("path"));
|
|||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const sinon = __importStar(require("sinon"));
|
const sinon = __importStar(require("sinon"));
|
||||||
const actionsUtil = __importStar(require("./actions-util"));
|
const actionsUtil = __importStar(require("./actions-util"));
|
||||||
const feature_flags_test_1 = require("./feature-flags.test");
|
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
const setupCodeql = __importStar(require("./setup-codeql"));
|
const setupCodeql = __importStar(require("./setup-codeql"));
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const util_1 = require("./util");
|
const util_1 = require("./util");
|
||||||
(0, testing_utils_1.setupTests)(ava_1.default);
|
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||||
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
|
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
|
||||||
const expectedFeatureEnablement = (0, feature_flags_test_1.initializeFeatures)(true);
|
const expectedFeatureEnablement = (0, testing_utils_1.initializeFeatures)(true);
|
||||||
expectedFeatureEnablement.getValue = function (feature) {
|
expectedFeatureEnablement.getValue = function (feature) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return expectedFeatureEnablement[feature];
|
return expectedFeatureEnablement[feature];
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
43
lib/testing-utils.js
generated
43
lib/testing-utils.js
generated
@@ -41,9 +41,11 @@ exports.setupTests = setupTests;
|
|||||||
exports.setupActionsVars = setupActionsVars;
|
exports.setupActionsVars = setupActionsVars;
|
||||||
exports.getRecordingLogger = getRecordingLogger;
|
exports.getRecordingLogger = getRecordingLogger;
|
||||||
exports.mockFeatureFlagApiEndpoint = mockFeatureFlagApiEndpoint;
|
exports.mockFeatureFlagApiEndpoint = mockFeatureFlagApiEndpoint;
|
||||||
|
exports.stubFeatureFlagApiEndpoint = stubFeatureFlagApiEndpoint;
|
||||||
exports.mockLanguagesInRepo = mockLanguagesInRepo;
|
exports.mockLanguagesInRepo = mockLanguagesInRepo;
|
||||||
exports.mockCodeQLVersion = mockCodeQLVersion;
|
exports.mockCodeQLVersion = mockCodeQLVersion;
|
||||||
exports.createFeatures = createFeatures;
|
exports.createFeatures = createFeatures;
|
||||||
|
exports.initializeFeatures = initializeFeatures;
|
||||||
exports.mockBundleDownloadApi = mockBundleDownloadApi;
|
exports.mockBundleDownloadApi = mockBundleDownloadApi;
|
||||||
exports.createTestConfig = createTestConfig;
|
exports.createTestConfig = createTestConfig;
|
||||||
const node_util_1 = require("node:util");
|
const node_util_1 = require("node:util");
|
||||||
@@ -54,6 +56,7 @@ const sinon = __importStar(require("sinon"));
|
|||||||
const apiClient = __importStar(require("./api-client"));
|
const apiClient = __importStar(require("./api-client"));
|
||||||
const codeql = __importStar(require("./codeql"));
|
const codeql = __importStar(require("./codeql"));
|
||||||
const defaults = __importStar(require("./defaults.json"));
|
const defaults = __importStar(require("./defaults.json"));
|
||||||
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const util_1 = require("./util");
|
const util_1 = require("./util");
|
||||||
exports.SAMPLE_DOTCOM_API_DETAILS = {
|
exports.SAMPLE_DOTCOM_API_DETAILS = {
|
||||||
auth: "token",
|
auth: "token",
|
||||||
@@ -172,21 +175,32 @@ function getRecordingLogger(messages) {
|
|||||||
}
|
}
|
||||||
/** Mock the HTTP request to the feature flags enablement API endpoint. */
|
/** Mock the HTTP request to the feature flags enablement API endpoint. */
|
||||||
function mockFeatureFlagApiEndpoint(responseStatusCode, response) {
|
function mockFeatureFlagApiEndpoint(responseStatusCode, response) {
|
||||||
|
stubFeatureFlagApiEndpoint(() => ({
|
||||||
|
status: responseStatusCode,
|
||||||
|
messageIfError: "some error message",
|
||||||
|
data: response,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
/** Stub the HTTP request to the feature flags enablement API endpoint. */
|
||||||
|
function stubFeatureFlagApiEndpoint(responseFunction) {
|
||||||
// Passing an auth token is required, so we just use a dummy value
|
// Passing an auth token is required, so we just use a dummy value
|
||||||
const client = github.getOctokit("123");
|
const client = github.getOctokit("123");
|
||||||
const requestSpy = sinon.stub(client, "request");
|
const requestSpy = sinon.stub(client, "request");
|
||||||
const optInSpy = requestSpy.withArgs("GET /repos/:owner/:repo/code-scanning/codeql-action/features");
|
const optInSpy = requestSpy.withArgs("GET /repos/:owner/:repo/code-scanning/codeql-action/features");
|
||||||
if (responseStatusCode < 300) {
|
optInSpy.callsFake((_route, params) => {
|
||||||
optInSpy.resolves({
|
const response = responseFunction(params);
|
||||||
status: responseStatusCode,
|
if (response.status < 300) {
|
||||||
data: response,
|
return Promise.resolve({
|
||||||
headers: {},
|
status: response.status,
|
||||||
url: "GET /repos/:owner/:repo/code-scanning/codeql-action/features",
|
data: response.data,
|
||||||
});
|
headers: {},
|
||||||
}
|
url: "GET /repos/:owner/:repo/code-scanning/codeql-action/features",
|
||||||
else {
|
});
|
||||||
optInSpy.throws(new util_1.HTTPError("some error message", responseStatusCode));
|
}
|
||||||
}
|
else {
|
||||||
|
throw new util_1.HTTPError(response.messageIfError || "default stub error message", response.status);
|
||||||
|
}
|
||||||
|
});
|
||||||
sinon.stub(apiClient, "getApiClient").value(() => client);
|
sinon.stub(apiClient, "getApiClient").value(() => client);
|
||||||
}
|
}
|
||||||
function mockLanguagesInRepo(languages) {
|
function mockLanguagesInRepo(languages) {
|
||||||
@@ -240,6 +254,12 @@ function createFeatures(enabledFeatures) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function initializeFeatures(initialValue) {
|
||||||
|
return Object.keys(feature_flags_1.featureConfig).reduce((features, key) => {
|
||||||
|
features[key] = initialValue;
|
||||||
|
return features;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Mocks the API for downloading the bundle tagged `tagName`.
|
* Mocks the API for downloading the bundle tagged `tagName`.
|
||||||
*
|
*
|
||||||
@@ -282,6 +302,7 @@ function createTestConfig(overrides) {
|
|||||||
augmentationProperties: {
|
augmentationProperties: {
|
||||||
packsInputCombines: false,
|
packsInputCombines: false,
|
||||||
queriesInputCombines: false,
|
queriesInputCombines: false,
|
||||||
|
extraQueryExclusions: [],
|
||||||
},
|
},
|
||||||
trapCaches: {},
|
trapCaches: {},
|
||||||
trapCacheDownloadTime: 0,
|
trapCacheDownloadTime: 0,
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user