Refactor handling of feature flags
This commit centralizes how feature flags are handled. All feature flags must now add an entry in the `featureFlagConfig` dictionary. This dictionary associates the flag with an environment variable name and optionally a minimum version for CodeQL. The new logic is: - if the environment variable is set to false: disabled - if the minimum version requirement specified and met: disabled - if the environment variable is set to true: enable - Otherwise check feature flag enablement from the server
This commit is contained in:
parent
24c8de16fa
commit
e5c3375225
27 changed files with 400 additions and 368 deletions
3
lib/codeql.js
generated
3
lib/codeql.js
generated
|
|
@ -22,7 +22,7 @@ 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.getExtraOptions = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.convertToSemVer = exports.getCodeQLURLVersion = exports.setupCodeQL = exports.getCodeQLActionRepository = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CODEQL_VERSION_CONFIG_FILES = exports.CODEQL_VERSION_ML_POWERED_QUERIES = exports.CODEQL_VERSION_COUNTS_LINES = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = exports.CommandInvocationError = void 0;
|
exports.getExtraOptions = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.convertToSemVer = exports.getCodeQLURLVersion = exports.setupCodeQL = exports.getCodeQLActionRepository = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CODEQL_VERSION_CONFIG_FILES = exports.CODEQL_VERSION_COUNTS_LINES = exports.CODEQL_DEFAULT_ACTION_REPOSITORY = exports.CommandInvocationError = void 0;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
||||||
|
|
@ -79,7 +79,6 @@ const CODEQL_VERSION_GROUP_RULES = "2.5.5";
|
||||||
const CODEQL_VERSION_SARIF_GROUP = "2.5.3";
|
const CODEQL_VERSION_SARIF_GROUP = "2.5.3";
|
||||||
exports.CODEQL_VERSION_COUNTS_LINES = "2.6.2";
|
exports.CODEQL_VERSION_COUNTS_LINES = "2.6.2";
|
||||||
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
||||||
exports.CODEQL_VERSION_ML_POWERED_QUERIES = "2.7.5";
|
|
||||||
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
||||||
exports.CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
exports.CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
||||||
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
51
lib/codeql.test.js
generated
51
lib/codeql.test.js
generated
|
|
@ -342,35 +342,28 @@ for (const [isFeatureFlagEnabled, toolsInput, shouldToolcacheBeBypassed,] of TOO
|
||||||
// Test macro for ensuring different variants of injected augmented configurations
|
// Test macro for ensuring different variants of injected augmented configurations
|
||||||
const injectedConfigMacro = ava_1.default.macro({
|
const injectedConfigMacro = ava_1.default.macro({
|
||||||
exec: async (t, augmentationProperties, configOverride, expectedConfig) => {
|
exec: async (t, augmentationProperties, configOverride, expectedConfig) => {
|
||||||
const origCODEQL_PASS_CONFIG_TO_CLI = process.env.CODEQL_PASS_CONFIG_TO_CLI;
|
await util.withTmpDir(async (tempDir) => {
|
||||||
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = "true";
|
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||||
try {
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
await util.withTmpDir(async (tempDir) => {
|
sinon
|
||||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
.stub(codeqlObject, "getVersion")
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
||||||
sinon
|
const thisStubConfig = {
|
||||||
.stub(codeqlObject, "getVersion")
|
...stubConfig,
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
...configOverride,
|
||||||
const thisStubConfig = {
|
tempDir,
|
||||||
...stubConfig,
|
augmentationProperties,
|
||||||
...configOverride,
|
};
|
||||||
tempDir,
|
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, undefined, (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled]), (0, logging_1.getRunnerLogger)(true));
|
||||||
augmentationProperties,
|
const args = runnerConstructorStub.firstCall.args[1];
|
||||||
};
|
// should have used an config file
|
||||||
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, undefined, (0, feature_flags_1.createFeatureFlags)([]), (0, logging_1.getRunnerLogger)(true));
|
const configArg = args.find((arg) => arg.startsWith("--codescanning-config="));
|
||||||
const args = runnerConstructorStub.firstCall.args[1];
|
t.truthy(configArg, "Should have injected a codescanning config");
|
||||||
// should have used an config file
|
const configFile = configArg.split("=")[1];
|
||||||
const configArg = args.find((arg) => arg.startsWith("--codescanning-config="));
|
const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8"));
|
||||||
t.truthy(configArg, "Should have injected a codescanning config");
|
t.deepEqual(augmentedConfig, expectedConfig);
|
||||||
const configFile = configArg.split("=")[1];
|
await (0, del_1.default)(configFile, { force: true });
|
||||||
const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8"));
|
});
|
||||||
t.deepEqual(augmentedConfig, expectedConfig);
|
|
||||||
await (0, del_1.default)(configFile, { force: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = origCODEQL_PASS_CONFIG_TO_CLI;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
title: (providedTitle = "") => `databaseInitCluster() injected config: ${providedTitle}`,
|
title: (providedTitle = "") => `databaseInitCluster() injected config: ${providedTitle}`,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
3
lib/config-utils.js
generated
3
lib/config-utils.js
generated
|
|
@ -151,8 +151,7 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
|
||||||
languages.includes("javascript") &&
|
languages.includes("javascript") &&
|
||||||
(found === "security-extended" || found === "security-and-quality") &&
|
(found === "security-extended" || found === "security-and-quality") &&
|
||||||
!((_a = packs.javascript) === null || _a === void 0 ? void 0 : _a.some(isMlPoweredJsQueriesPack)) &&
|
!((_a = packs.javascript) === null || _a === void 0 ? void 0 : _a.some(isMlPoweredJsQueriesPack)) &&
|
||||||
(await featureFlags.getValue(feature_flags_1.FeatureFlag.MlPoweredQueriesEnabled)) &&
|
(await featureFlags.getValue(feature_flags_1.FeatureFlag.MlPoweredQueriesEnabled, codeQL))) {
|
||||||
(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_ML_POWERED_QUERIES))) {
|
|
||||||
if (!packs.javascript) {
|
if (!packs.javascript) {
|
||||||
packs.javascript = [];
|
packs.javascript = [];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
43
lib/feature-flags.js
generated
43
lib/feature-flags.js
generated
|
|
@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.createFeatureFlags = exports.GitHubFeatureFlags = exports.FeatureFlag = void 0;
|
exports.createFeatureFlags = exports.GitHubFeatureFlags = exports.featureFlagConfig = exports.FeatureFlag = void 0;
|
||||||
const api_client_1 = require("./api-client");
|
const api_client_1 = require("./api-client");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
var FeatureFlag;
|
var FeatureFlag;
|
||||||
|
|
@ -30,6 +30,28 @@ var FeatureFlag;
|
||||||
FeatureFlag["GolangExtractionReconciliationEnabled"] = "golang_extraction_reconciliation_enabled";
|
FeatureFlag["GolangExtractionReconciliationEnabled"] = "golang_extraction_reconciliation_enabled";
|
||||||
FeatureFlag["CliConfigFileEnabled"] = "cli_config_file_enabled";
|
FeatureFlag["CliConfigFileEnabled"] = "cli_config_file_enabled";
|
||||||
})(FeatureFlag = exports.FeatureFlag || (exports.FeatureFlag = {}));
|
})(FeatureFlag = exports.FeatureFlag || (exports.FeatureFlag = {}));
|
||||||
|
exports.featureFlagConfig = {
|
||||||
|
[FeatureFlag.BypassToolcacheEnabled]: {
|
||||||
|
envVar: "CODEQL_BYPASS_TOOLCACHE",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.MlPoweredQueriesEnabled]: {
|
||||||
|
envVar: "CODEQL_VERSION_ML_POWERED_QUERIES",
|
||||||
|
minimumVersion: "2.7.5",
|
||||||
|
},
|
||||||
|
[FeatureFlag.TrapCachingEnabled]: {
|
||||||
|
envVar: "CODEQL_TRAP_CACHING",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.GolangExtractionReconciliationEnabled]: {
|
||||||
|
envVar: "CODEQL_GOLANG_EXTRACTION_RECONCILIATION",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.CliConfigFileEnabled]: {
|
||||||
|
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||||
|
minimumVersion: "2.10.1",
|
||||||
|
},
|
||||||
|
};
|
||||||
class GitHubFeatureFlags {
|
class GitHubFeatureFlags {
|
||||||
constructor(gitHubVersion, apiDetails, repositoryNwo, logger) {
|
constructor(gitHubVersion, apiDetails, repositoryNwo, logger) {
|
||||||
this.gitHubVersion = gitHubVersion;
|
this.gitHubVersion = gitHubVersion;
|
||||||
|
|
@ -37,11 +59,28 @@ class GitHubFeatureFlags {
|
||||||
this.repositoryNwo = repositoryNwo;
|
this.repositoryNwo = repositoryNwo;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
async getValue(flag) {
|
async getValue(flag, codeql) {
|
||||||
// Bypassing the toolcache is disabled in test mode.
|
// Bypassing the toolcache is disabled in test mode.
|
||||||
if (flag === FeatureFlag.BypassToolcacheEnabled && util.isInTestMode()) {
|
if (flag === FeatureFlag.BypassToolcacheEnabled && util.isInTestMode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const envVar = (process.env[exports.featureFlagConfig[flag].envVar] || "").toLocaleLowerCase();
|
||||||
|
// Do not use this feature if user explicitly disables it via an environment variable.
|
||||||
|
if (envVar === "false") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Never use this feature if the CLI version explicitly can't support it.
|
||||||
|
const minimumVersion = exports.featureFlagConfig[flag].minimumVersion;
|
||||||
|
if (codeql && minimumVersion) {
|
||||||
|
if (!(await util.codeQlVersionAbove(codeql, minimumVersion))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use this feature if user explicitly enables it via an environment variable.
|
||||||
|
if (envVar === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Ask the GitHub API if the feature is enabled.
|
||||||
const response = await this.getApiResponse();
|
const response = await this.getApiResponse();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
this.logger.debug(`No feature flags API response for ${flag}, considering it disabled.`);
|
this.logger.debug(`No feature flags API response for ${flag}, considering it disabled.`);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"feature-flags.js","sourceRoot":"","sources":["../src/feature-flags.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"feature-flags.js","sourceRoot":"","sources":["../src/feature-flags.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA8D;AAI9D,6CAA+B;AAM/B,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,kEAAmD,CAAA;IACnD,qEAAsD,CAAA;IACtD,0DAA2C,CAAA;IAC3C,iGAAkF,CAAA;IAClF,+DAAgD,CAAA;AAClD,CAAC,EANW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAMtB;AAEY,QAAA,iBAAiB,GAG1B;IACF,CAAC,WAAW,CAAC,sBAAsB,CAAC,EAAE;QACpC,MAAM,EAAE,yBAAyB;QACjC,cAAc,EAAE,SAAS;KAC1B;IACD,CAAC,WAAW,CAAC,uBAAuB,CAAC,EAAE;QACrC,MAAM,EAAE,mCAAmC;QAC3C,cAAc,EAAE,OAAO;KACxB;IACD,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE;QAChC,MAAM,EAAE,qBAAqB;QAC7B,cAAc,EAAE,SAAS;KAC1B;IACD,CAAC,WAAW,CAAC,qCAAqC,CAAC,EAAE;QACnD,MAAM,EAAE,yCAAyC;QACjD,cAAc,EAAE,SAAS;KAC1B;IACD,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE;QAClC,MAAM,EAAE,2BAA2B;QACnC,cAAc,EAAE,QAAQ;KACzB;CACF,CAAC;AAUF,MAAa,kBAAkB;IAG7B,YACU,aAAiC,EACjC,UAA4B,EAC5B,aAA4B,EAC5B,MAAc;QAHd,kBAAa,GAAb,aAAa,CAAoB;QACjC,eAAU,GAAV,UAAU,CAAkB;QAC5B,kBAAa,GAAb,aAAa,CAAe;QAC5B,WAAM,GAAN,MAAM,CAAQ;IACrB,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,IAAiB,EAAE,MAAe;QAC/C,oDAAoD;QACpD,IAAI,IAAI,KAAK,WAAW,CAAC,sBAAsB,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YACtE,OAAO,KAAK,CAAC;SACd;QAED,MAAM,MAAM,GAAG,CACb,OAAO,CAAC,GAAG,CAAC,yBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAClD,CAAC,iBAAiB,EAAE,CAAC;QAEtB,sFAAsF;QACtF,IAAI,MAAM,KAAK,OAAO,EAAE;YACtB,OAAO,KAAK,CAAC;SACd;QAED,yEAAyE;QACzE,MAAM,cAAc,GAAG,yBAAiB,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC;QAC9D,IAAI,MAAM,IAAI,cAAc,EAAE;YAC5B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE;gBAC5D,OAAO,KAAK,CAAC;aACd;SACF;QAED,8EAA8E;QAC9E,IAAI,MAAM,KAAK,MAAM,EAAE;YACrB,OAAO,IAAI,CAAC;SACb;QAED,gDAAgD;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,IAAI,QAAQ,KAAK,SAAS,EAAE;YAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,qCAAqC,IAAI,4BAA4B,CACtE,CAAC;YACF,OAAO,KAAK,CAAC;SACd;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,SAAS,KAAK,SAAS,EAAE;YAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,iBAAiB,IAAI,uDAAuD,CAC7E,CAAC;YACF,OAAO,KAAK,CAAC;SACd;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;YACjC,iDAAiD;YACjD,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;gBACzD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,8DAA8D,CAC/D,CAAC;gBACF,OAAO,EAAE,CAAC;aACX;YACD,MAAM,MAAM,GAAG,IAAA,yBAAY,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI;gBACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,8DAA8D,EAC9D;oBACE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK;oBAC/B,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;iBAC9B,CACF,CAAC;gBACF,OAAO,QAAQ,CAAC,IAAI,CAAC;aACtB;YAAC,OAAO,CAAC,EAAE;gBACV,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE;oBAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CACjB,gGAAgG;wBAC9F,oEAAoE;wBACpE,qFAAqF;wBACrF,kFAAkF,CAAC,EAAE,CACxF,CAAC;iBACH;qBAAM;oBACL,uFAAuF;oBACvF,mFAAmF;oBACnF,2FAA2F;oBAC3F,qBAAqB;oBACrB,MAAM,IAAI,KAAK,CACb,4DAA4D,CAAC,EAAE,CAChE,CAAC;iBACH;aACF;QACH,CAAC,CAAC;QAEF,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC;QACrC,OAAO,WAAW,CAAC;IACrB,CAAC;CACF;AAnGD,gDAmGC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,YAA2B;IAC5D,OAAO;QACL,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAND,gDAMC"}
|
||||||
103
lib/feature-flags.test.js
generated
103
lib/feature-flags.test.js
generated
|
|
@ -29,9 +29,8 @@ const ALL_FEATURE_FLAGS_DISABLED_VARIANTS = [
|
||||||
for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
(0, ava_1.default)(`All feature flags are disabled if running against ${variant.description}`, async (t) => {
|
(0, ava_1.default)(`All feature flags are disabled if running against ${variant.description}`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new feature_flags_1.GitHubFeatureFlags(variant.gitHubVersion, testApiDetails, testRepositoryNwo, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const featureFlags = setUpTmpDir(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion);
|
||||||
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
||||||
t.assert((await featureFlags.getValue(flag)) === false);
|
t.assert((await featureFlags.getValue(flag)) === false);
|
||||||
}
|
}
|
||||||
|
|
@ -43,14 +42,13 @@ for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
}
|
}
|
||||||
(0, ava_1.default)("API response missing", async (t) => {
|
(0, ava_1.default)("API response missing", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new feature_flags_1.GitHubFeatureFlags({ type: util_1.GitHubVariant.DOTCOM }, testApiDetails, testRepositoryNwo, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const featureFlags = setUpTmpDir(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
|
||||||
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
||||||
t.assert((await featureFlags.getValue(flag)) === false);
|
t.assert((await featureFlags.getValue(flag)) === false);
|
||||||
}
|
}
|
||||||
for (const featureFlag of ["ml_powered_queries_enabled"]) {
|
for (const featureFlag of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||||
v.message ===
|
v.message ===
|
||||||
`No feature flags API response for ${featureFlag}, considering it disabled.`) !== undefined);
|
`No feature flags API response for ${featureFlag}, considering it disabled.`) !== undefined);
|
||||||
|
|
@ -59,14 +57,13 @@ for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("Feature flags are disabled if they're not returned in API response", async (t) => {
|
(0, ava_1.default)("Feature flags are disabled if they're not returned in API response", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new feature_flags_1.GitHubFeatureFlags({ type: util_1.GitHubVariant.DOTCOM }, testApiDetails, testRepositoryNwo, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const featureFlags = setUpTmpDir(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
|
||||||
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
for (const flag of Object.values(feature_flags_1.FeatureFlag)) {
|
||||||
t.assert((await featureFlags.getValue(flag)) === false);
|
t.assert((await featureFlags.getValue(flag)) === false);
|
||||||
}
|
}
|
||||||
for (const featureFlag of ["ml_powered_queries_enabled"]) {
|
for (const featureFlag of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||||
v.message ===
|
v.message ===
|
||||||
`Feature flag '${featureFlag}' undefined in API response, considering it disabled.`) !== undefined);
|
`Feature flag '${featureFlag}' undefined in API response, considering it disabled.`) !== undefined);
|
||||||
|
|
@ -75,31 +72,97 @@ for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
});
|
});
|
||||||
(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) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
const featureFlags = new feature_flags_1.GitHubFeatureFlags({ type: util_1.GitHubVariant.DOTCOM }, testApiDetails, testRepositoryNwo, (0, logging_1.getRunnerLogger)(true));
|
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {});
|
||||||
await t.throwsAsync(async () => featureFlags.getValue(feature_flags_1.FeatureFlag.MlPoweredQueriesEnabled), {
|
await t.throwsAsync(async () => featureFlags.getValue(feature_flags_1.FeatureFlag.MlPoweredQueriesEnabled), {
|
||||||
message: "Encountered an error while trying to load feature flags: Error: some error message",
|
message: "Encountered an error while trying to load feature flags: Error: some error message",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const FEATURE_FLAGS = ["ml_powered_queries_enabled"];
|
for (const featureFlag of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
for (const featureFlag of FEATURE_FLAGS) {
|
|
||||||
(0, ava_1.default)(`Feature flag '${featureFlag}' is enabled if enabled in the API response`, async (t) => {
|
(0, ava_1.default)(`Feature flag '${featureFlag}' is enabled if enabled in the API response`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
const featureFlags = new feature_flags_1.GitHubFeatureFlags({ type: util_1.GitHubVariant.DOTCOM }, testApiDetails, testRepositoryNwo, (0, logging_1.getRunnerLogger)(true));
|
// set all feature flags to false except the one we're testing
|
||||||
const expectedFeatureFlags = {};
|
const expectedFeatureFlags = {};
|
||||||
for (const f of FEATURE_FLAGS) {
|
for (const f of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
expectedFeatureFlags[f] = false;
|
expectedFeatureFlags[f] = f === featureFlag;
|
||||||
}
|
}
|
||||||
expectedFeatureFlags[featureFlag] = true;
|
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureFlags);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureFlags);
|
||||||
const actualFeatureFlags = {
|
// retrieve the values of the actual feature flags
|
||||||
ml_powered_queries_enabled: await featureFlags.getValue(feature_flags_1.FeatureFlag.MlPoweredQueriesEnabled),
|
const actualFeatureFlags = {};
|
||||||
};
|
for (const f of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
|
actualFeatureFlags[f] = await featureFlags.getValue(f);
|
||||||
|
}
|
||||||
|
// Alls flags should be false except the one we're testing
|
||||||
t.deepEqual(actualFeatureFlags, expectedFeatureFlags);
|
t.deepEqual(actualFeatureFlags, expectedFeatureFlags);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
(0, ava_1.default)(`Feature flag '${featureFlag}' is enabled if the associated environment variable is true`, async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
// set all feature flags to false
|
||||||
|
const expectedFeatureFlags = {};
|
||||||
|
for (const f of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = false;
|
||||||
|
}
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureFlags);
|
||||||
|
// feature flag should be disabled initially
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag)));
|
||||||
|
// set env var to true and check that the feature flag is now enabled
|
||||||
|
process.env[feature_flags_1.featureFlagConfig[featureFlag].envVar] = "true";
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)(`Feature flag '${featureFlag}' is disabled if the associated environment variable is false`, async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
// set all feature flags to true
|
||||||
|
const expectedFeatureFlags = {};
|
||||||
|
for (const f of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = true;
|
||||||
|
}
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureFlags);
|
||||||
|
// feature flag should be enabled initially
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag));
|
||||||
|
// set env var to false and check that the feature flag is now disabled
|
||||||
|
process.env[feature_flags_1.featureFlagConfig[featureFlag].envVar] = "false";
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (feature_flags_1.featureFlagConfig[featureFlag].minimumVersion !== undefined) {
|
||||||
|
(0, ava_1.default)(`Feature flag '${featureFlag}' is disabled if the minimum CLI version is below ${feature_flags_1.featureFlagConfig[featureFlag].minimumVersion}`, async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
// set all feature flags to true
|
||||||
|
const expectedFeatureFlags = {};
|
||||||
|
for (const f of Object.keys(feature_flags_1.featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = true;
|
||||||
|
}
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureFlags);
|
||||||
|
// feature flag should be enabled initially (ignoring the minimum CLI version)
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag));
|
||||||
|
// feature flag should be disabled when an old CLI version is set
|
||||||
|
let codeql = (0, testing_utils_1.mockCodeQLVersion)("2.0.0");
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag, codeql)));
|
||||||
|
// even setting the env var to true should not enable the feature flag if
|
||||||
|
// the minimum CLI version is not met
|
||||||
|
process.env[feature_flags_1.featureFlagConfig[featureFlag].envVar] = "true";
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag, codeql)));
|
||||||
|
// feature flag should be enabled when a new CLI version is set
|
||||||
|
// and env var is not set
|
||||||
|
process.env[feature_flags_1.featureFlagConfig[featureFlag].envVar] = "";
|
||||||
|
codeql = (0, testing_utils_1.mockCodeQLVersion)(feature_flags_1.featureFlagConfig[featureFlag].minimumVersion);
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag, codeql));
|
||||||
|
// set env var to false and check that the feature flag is now disabled
|
||||||
|
process.env[feature_flags_1.featureFlagConfig[featureFlag].envVar] = "false";
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag, codeql)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setUpTmpDir(tmpDir, logger = (0, logging_1.getRunnerLogger)(true), gitHubVersion = { type: util_1.GitHubVariant.DOTCOM }) {
|
||||||
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
|
return new feature_flags_1.GitHubFeatureFlags(gitHubVersion, testApiDetails, testRepositoryNwo, logger);
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=feature-flags.test.js.map
|
//# sourceMappingURL=feature-flags.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
3
lib/init-action.js
generated
3
lib/init-action.js
generated
|
|
@ -160,8 +160,9 @@ async function run() {
|
||||||
}
|
}
|
||||||
async function getTrapCachingEnabled(featureFlags) {
|
async function getTrapCachingEnabled(featureFlags) {
|
||||||
const trapCaching = (0, actions_util_1.getOptionalInput)("trap-caching");
|
const trapCaching = (0, actions_util_1.getOptionalInput)("trap-caching");
|
||||||
if (trapCaching !== undefined)
|
if (trapCaching !== undefined) {
|
||||||
return trapCaching === "true";
|
return trapCaching === "true";
|
||||||
|
}
|
||||||
return await featureFlags.getValue(feature_flags_1.FeatureFlag.TrapCachingEnabled);
|
return await featureFlags.getValue(feature_flags_1.FeatureFlag.TrapCachingEnabled);
|
||||||
}
|
}
|
||||||
async function runWrapper() {
|
async function runWrapper() {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
10
lib/testing-utils.js
generated
10
lib/testing-utils.js
generated
|
|
@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.mockFeatureFlagApiEndpoint = exports.getRecordingLogger = exports.setupActionsVars = exports.setupTests = void 0;
|
exports.mockCodeQLVersion = exports.mockFeatureFlagApiEndpoint = exports.getRecordingLogger = exports.setupActionsVars = exports.setupTests = void 0;
|
||||||
const github = __importStar(require("@actions/github"));
|
const github = __importStar(require("@actions/github"));
|
||||||
const sinon = __importStar(require("sinon"));
|
const sinon = __importStar(require("sinon"));
|
||||||
const apiClient = __importStar(require("./api-client"));
|
const apiClient = __importStar(require("./api-client"));
|
||||||
|
|
@ -144,4 +144,12 @@ function mockFeatureFlagApiEndpoint(responseStatusCode, response) {
|
||||||
sinon.stub(apiClient, "getApiClient").value(() => client);
|
sinon.stub(apiClient, "getApiClient").value(() => client);
|
||||||
}
|
}
|
||||||
exports.mockFeatureFlagApiEndpoint = mockFeatureFlagApiEndpoint;
|
exports.mockFeatureFlagApiEndpoint = mockFeatureFlagApiEndpoint;
|
||||||
|
function mockCodeQLVersion(version) {
|
||||||
|
return {
|
||||||
|
async getVersion() {
|
||||||
|
return version;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
exports.mockCodeQLVersion = mockCodeQLVersion;
|
||||||
//# sourceMappingURL=testing-utils.js.map
|
//# sourceMappingURL=testing-utils.js.map
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"testing-utils.js","sourceRoot":"","sources":["../src/testing-utils.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"testing-utils.js","sourceRoot":"","sources":["../src/testing-utils.ts"],"names":[],"mappings":"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"}
|
||||||
27
lib/util.js
generated
27
lib/util.js
generated
|
|
@ -424,12 +424,6 @@ var EnvVar;
|
||||||
* own sandwiched workflow mechanism
|
* own sandwiched workflow mechanism
|
||||||
*/
|
*/
|
||||||
EnvVar["FEATURE_SANDWICH"] = "CODEQL_ACTION_FEATURE_SANDWICH";
|
EnvVar["FEATURE_SANDWICH"] = "CODEQL_ACTION_FEATURE_SANDWICH";
|
||||||
/**
|
|
||||||
* If set to the "true" string and the codeql CLI version is greater than
|
|
||||||
* `CODEQL_VERSION_CONFIG_FILES`, then the codeql-action will pass the
|
|
||||||
* the codeql-config file to the codeql CLI to be processed there.
|
|
||||||
*/
|
|
||||||
EnvVar["CODEQL_PASS_CONFIG_TO_CLI"] = "CODEQL_PASS_CONFIG_TO_CLI";
|
|
||||||
})(EnvVar = exports.EnvVar || (exports.EnvVar = {}));
|
})(EnvVar = exports.EnvVar || (exports.EnvVar = {}));
|
||||||
const exportVar = (mode, name, value) => {
|
const exportVar = (mode, name, value) => {
|
||||||
if (mode === Mode.actions) {
|
if (mode === Mode.actions) {
|
||||||
|
|
@ -491,9 +485,6 @@ function getRequiredEnvParam(paramName) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
exports.getRequiredEnvParam = getRequiredEnvParam;
|
exports.getRequiredEnvParam = getRequiredEnvParam;
|
||||||
function getOptionalEnvParam(paramName) {
|
|
||||||
return process.env[paramName] || "";
|
|
||||||
}
|
|
||||||
class HTTPError extends Error {
|
class HTTPError extends Error {
|
||||||
constructor(message, status) {
|
constructor(message, status) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
@ -663,20 +654,7 @@ exports.isInTestMode = isInTestMode;
|
||||||
* that gets passed to the CLI.
|
* that gets passed to the CLI.
|
||||||
*/
|
*/
|
||||||
async function useCodeScanningConfigInCli(codeql, featureFlags) {
|
async function useCodeScanningConfigInCli(codeql, featureFlags) {
|
||||||
const envVarIsEnabled = getOptionalEnvParam(EnvVar.CODEQL_PASS_CONFIG_TO_CLI);
|
return await featureFlags.getValue(feature_flags_1.FeatureFlag.CliConfigFileEnabled, codeql);
|
||||||
// If the user has explicitly turned off the feature, then don't use it.
|
|
||||||
if (envVarIsEnabled.toLocaleLowerCase() === "false") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// If the user has explicitly turned on the feature, then use it.
|
|
||||||
// Or if the feature flag is enabled, then use it.
|
|
||||||
const isEnabled = envVarIsEnabled.toLocaleLowerCase() === "true" ||
|
|
||||||
(await featureFlags.getValue(feature_flags_1.FeatureFlag.CliConfigFileEnabled));
|
|
||||||
if (!isEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// If the CLI version is too old, then don't use it.
|
|
||||||
return await codeQlVersionAbove(codeql, codeql_1.CODEQL_VERSION_CONFIG_FILES);
|
|
||||||
}
|
}
|
||||||
exports.useCodeScanningConfigInCli = useCodeScanningConfigInCli;
|
exports.useCodeScanningConfigInCli = useCodeScanningConfigInCli;
|
||||||
async function logCodeScanningConfigInCli(codeql, featureFlags, logger) {
|
async function logCodeScanningConfigInCli(codeql, featureFlags, logger) {
|
||||||
|
|
@ -722,8 +700,7 @@ function listFolder(dir) {
|
||||||
}
|
}
|
||||||
exports.listFolder = listFolder;
|
exports.listFolder = listFolder;
|
||||||
async function isGoExtractionReconciliationEnabled(featureFlags) {
|
async function isGoExtractionReconciliationEnabled(featureFlags) {
|
||||||
return (process.env["CODEQL_ACTION_RECONCILE_GO_EXTRACTION"] === "true" ||
|
return await featureFlags.getValue(feature_flags_1.FeatureFlag.GolangExtractionReconciliationEnabled);
|
||||||
(await featureFlags.getValue(feature_flags_1.FeatureFlag.GolangExtractionReconciliationEnabled)));
|
|
||||||
}
|
}
|
||||||
exports.isGoExtractionReconciliationEnabled = isGoExtractionReconciliationEnabled;
|
exports.isGoExtractionReconciliationEnabled = isGoExtractionReconciliationEnabled;
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
35
lib/util.test.js
generated
35
lib/util.test.js
generated
|
|
@ -31,7 +31,6 @@ const github = __importStar(require("@actions/github"));
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const sinon = __importStar(require("sinon"));
|
const sinon = __importStar(require("sinon"));
|
||||||
const api = __importStar(require("./api-client"));
|
const api = __importStar(require("./api-client"));
|
||||||
const feature_flags_1 = require("./feature-flags");
|
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
const testing_utils_1 = require("./testing-utils");
|
const testing_utils_1 = require("./testing-utils");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
|
|
@ -362,40 +361,6 @@ for (const [version, githubVersion, shouldReportWarning,] of CHECK_ACTION_VERSIO
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("useCodeScanningConfigInCli with no env var", async (t) => {
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled]))));
|
|
||||||
// Yay! It works!
|
|
||||||
t.assert(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled])));
|
|
||||||
});
|
|
||||||
for (const val of ["TRUE", "true", "True"]) {
|
|
||||||
(0, ava_1.default)(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
|
|
||||||
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled]))));
|
|
||||||
// Yay! It works!
|
|
||||||
t.assert(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled])));
|
|
||||||
t.assert(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([])));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (const val of ["FALSE", "false", "False"]) {
|
|
||||||
(0, ava_1.default)(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
|
|
||||||
// Never turned on when env var is false
|
|
||||||
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.0"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([feature_flags_1.FeatureFlag.CliConfigFileEnabled]))));
|
|
||||||
t.assert(!(await util.useCodeScanningConfigInCli(mockVersion("2.10.1"), (0, feature_flags_1.createFeatureFlags)([]))));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function mockVersion(version) {
|
|
||||||
return {
|
|
||||||
async getVersion() {
|
|
||||||
return version;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const longTime = 999999;
|
const longTime = 999999;
|
||||||
const shortTime = 10;
|
const shortTime = 10;
|
||||||
(0, ava_1.default)("withTimeout on long task", async (t) => {
|
(0, ava_1.default)("withTimeout on long task", async (t) => {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -505,47 +505,41 @@ const injectedConfigMacro = test.macro({
|
||||||
configOverride: Partial<Config>,
|
configOverride: Partial<Config>,
|
||||||
expectedConfig: any
|
expectedConfig: any
|
||||||
) => {
|
) => {
|
||||||
const origCODEQL_PASS_CONFIG_TO_CLI = process.env.CODEQL_PASS_CONFIG_TO_CLI;
|
await util.withTmpDir(async (tempDir) => {
|
||||||
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = "true";
|
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||||
try {
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
await util.withTmpDir(async (tempDir) => {
|
sinon
|
||||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
.stub(codeqlObject, "getVersion")
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
||||||
sinon
|
|
||||||
.stub(codeqlObject, "getVersion")
|
|
||||||
.resolves(codeql.CODEQL_VERSION_CONFIG_FILES);
|
|
||||||
|
|
||||||
const thisStubConfig: Config = {
|
const thisStubConfig: Config = {
|
||||||
...stubConfig,
|
...stubConfig,
|
||||||
...configOverride,
|
...configOverride,
|
||||||
tempDir,
|
tempDir,
|
||||||
augmentationProperties,
|
augmentationProperties,
|
||||||
};
|
};
|
||||||
|
|
||||||
await codeqlObject.databaseInitCluster(
|
await codeqlObject.databaseInitCluster(
|
||||||
thisStubConfig,
|
thisStubConfig,
|
||||||
"",
|
"",
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
createFeatureFlags([]),
|
createFeatureFlags([FeatureFlag.CliConfigFileEnabled]),
|
||||||
getRunnerLogger(true)
|
getRunnerLogger(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
const args = runnerConstructorStub.firstCall.args[1];
|
const args = runnerConstructorStub.firstCall.args[1];
|
||||||
// should have used an config file
|
// should have used an config file
|
||||||
const configArg = args.find((arg: string) =>
|
const configArg = args.find((arg: string) =>
|
||||||
arg.startsWith("--codescanning-config=")
|
arg.startsWith("--codescanning-config=")
|
||||||
);
|
);
|
||||||
t.truthy(configArg, "Should have injected a codescanning config");
|
t.truthy(configArg, "Should have injected a codescanning config");
|
||||||
const configFile = configArg.split("=")[1];
|
const configFile = configArg.split("=")[1];
|
||||||
const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8"));
|
const augmentedConfig = yaml.load(fs.readFileSync(configFile, "utf8"));
|
||||||
t.deepEqual(augmentedConfig, expectedConfig);
|
t.deepEqual(augmentedConfig, expectedConfig);
|
||||||
|
|
||||||
await del(configFile, { force: true });
|
await del(configFile, { force: true });
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = origCODEQL_PASS_CONFIG_TO_CLI;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
title: (providedTitle = "") =>
|
title: (providedTitle = "") =>
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,6 @@ const CODEQL_VERSION_GROUP_RULES = "2.5.5";
|
||||||
const CODEQL_VERSION_SARIF_GROUP = "2.5.3";
|
const CODEQL_VERSION_SARIF_GROUP = "2.5.3";
|
||||||
export const CODEQL_VERSION_COUNTS_LINES = "2.6.2";
|
export const CODEQL_VERSION_COUNTS_LINES = "2.6.2";
|
||||||
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
const CODEQL_VERSION_CUSTOM_QUERY_HELP = "2.7.1";
|
||||||
export const CODEQL_VERSION_ML_POWERED_QUERIES = "2.7.5";
|
|
||||||
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
const CODEQL_VERSION_LUA_TRACER_CONFIG = "2.10.0";
|
||||||
export const CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
export const CODEQL_VERSION_CONFIG_FILES = "2.10.1";
|
||||||
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
const CODEQL_VERSION_LUA_TRACING_GO_WINDOWS_FIXED = "2.10.4";
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import * as api from "./api-client";
|
||||||
import {
|
import {
|
||||||
CodeQL,
|
CodeQL,
|
||||||
CODEQL_VERSION_GHES_PACK_DOWNLOAD,
|
CODEQL_VERSION_GHES_PACK_DOWNLOAD,
|
||||||
CODEQL_VERSION_ML_POWERED_QUERIES,
|
|
||||||
CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS,
|
CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS,
|
||||||
ResolveQueriesOutput,
|
ResolveQueriesOutput,
|
||||||
} from "./codeql";
|
} from "./codeql";
|
||||||
|
|
@ -412,8 +411,7 @@ async function addBuiltinSuiteQueries(
|
||||||
languages.includes("javascript") &&
|
languages.includes("javascript") &&
|
||||||
(found === "security-extended" || found === "security-and-quality") &&
|
(found === "security-extended" || found === "security-and-quality") &&
|
||||||
!packs.javascript?.some(isMlPoweredJsQueriesPack) &&
|
!packs.javascript?.some(isMlPoweredJsQueriesPack) &&
|
||||||
(await featureFlags.getValue(FeatureFlag.MlPoweredQueriesEnabled)) &&
|
(await featureFlags.getValue(FeatureFlag.MlPoweredQueriesEnabled, codeQL))
|
||||||
(await codeQlVersionAbove(codeQL, CODEQL_VERSION_ML_POWERED_QUERIES))
|
|
||||||
) {
|
) {
|
||||||
if (!packs.javascript) {
|
if (!packs.javascript) {
|
||||||
packs.javascript = [];
|
packs.javascript = [];
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
|
|
||||||
import { GitHubApiDetails } from "./api-client";
|
import { GitHubApiDetails } from "./api-client";
|
||||||
import { FeatureFlag, GitHubFeatureFlags } from "./feature-flags";
|
import {
|
||||||
|
FeatureFlag,
|
||||||
|
featureFlagConfig,
|
||||||
|
FeatureFlags,
|
||||||
|
GitHubFeatureFlags,
|
||||||
|
} from "./feature-flags";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import {
|
import {
|
||||||
getRecordingLogger,
|
getRecordingLogger,
|
||||||
LoggedMessage,
|
LoggedMessage,
|
||||||
|
mockCodeQLVersion,
|
||||||
mockFeatureFlagApiEndpoint,
|
mockFeatureFlagApiEndpoint,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
setupTests,
|
setupTests,
|
||||||
|
|
@ -42,14 +48,11 @@ const ALL_FEATURE_FLAGS_DISABLED_VARIANTS: Array<{
|
||||||
for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
test(`All feature flags are disabled if running against ${variant.description}`, async (t) => {
|
test(`All feature flags are disabled if running against ${variant.description}`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new GitHubFeatureFlags(
|
const featureFlags = setUpTmpDir(
|
||||||
variant.gitHubVersion,
|
tmpDir,
|
||||||
testApiDetails,
|
getRecordingLogger(loggedMessages),
|
||||||
testRepositoryNwo,
|
variant.gitHubVersion
|
||||||
getRecordingLogger(loggedMessages)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const flag of Object.values(FeatureFlag)) {
|
for (const flag of Object.values(FeatureFlag)) {
|
||||||
|
|
@ -70,13 +73,9 @@ for (const variant of ALL_FEATURE_FLAGS_DISABLED_VARIANTS) {
|
||||||
|
|
||||||
test("API response missing", async (t) => {
|
test("API response missing", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new GitHubFeatureFlags(
|
const featureFlags = setUpTmpDir(
|
||||||
{ type: GitHubVariant.DOTCOM },
|
tmpDir,
|
||||||
testApiDetails,
|
|
||||||
testRepositoryNwo,
|
|
||||||
getRecordingLogger(loggedMessages)
|
getRecordingLogger(loggedMessages)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -86,7 +85,7 @@ test("API response missing", async (t) => {
|
||||||
t.assert((await featureFlags.getValue(flag)) === false);
|
t.assert((await featureFlags.getValue(flag)) === false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const featureFlag of ["ml_powered_queries_enabled"]) {
|
for (const featureFlag of Object.keys(featureFlagConfig)) {
|
||||||
t.assert(
|
t.assert(
|
||||||
loggedMessages.find(
|
loggedMessages.find(
|
||||||
(v: LoggedMessage) =>
|
(v: LoggedMessage) =>
|
||||||
|
|
@ -101,13 +100,9 @@ test("API response missing", async (t) => {
|
||||||
|
|
||||||
test("Feature flags are disabled if they're not returned in API response", async (t) => {
|
test("Feature flags are disabled if they're not returned in API response", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
|
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureFlags = new GitHubFeatureFlags(
|
const featureFlags = setUpTmpDir(
|
||||||
{ type: GitHubVariant.DOTCOM },
|
tmpDir,
|
||||||
testApiDetails,
|
|
||||||
testRepositoryNwo,
|
|
||||||
getRecordingLogger(loggedMessages)
|
getRecordingLogger(loggedMessages)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -117,7 +112,7 @@ test("Feature flags are disabled if they're not returned in API response", async
|
||||||
t.assert((await featureFlags.getValue(flag)) === false);
|
t.assert((await featureFlags.getValue(flag)) === false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const featureFlag of ["ml_powered_queries_enabled"]) {
|
for (const featureFlag of Object.keys(featureFlagConfig)) {
|
||||||
t.assert(
|
t.assert(
|
||||||
loggedMessages.find(
|
loggedMessages.find(
|
||||||
(v: LoggedMessage) =>
|
(v: LoggedMessage) =>
|
||||||
|
|
@ -132,14 +127,7 @@ test("Feature flags are disabled if they're not returned in API response", async
|
||||||
|
|
||||||
test("Feature flags exception is propagated if the API request errors", async (t) => {
|
test("Feature flags exception is propagated if the API request errors", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
|
||||||
const featureFlags = new GitHubFeatureFlags(
|
|
||||||
{ type: GitHubVariant.DOTCOM },
|
|
||||||
testApiDetails,
|
|
||||||
testRepositoryNwo,
|
|
||||||
getRunnerLogger(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
mockFeatureFlagApiEndpoint(500, {});
|
mockFeatureFlagApiEndpoint(500, {});
|
||||||
|
|
||||||
|
|
@ -153,34 +141,128 @@ test("Feature flags exception is propagated if the API request errors", async (t
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const FEATURE_FLAGS = ["ml_powered_queries_enabled"];
|
for (const featureFlag of Object.keys(featureFlagConfig)) {
|
||||||
|
|
||||||
for (const featureFlag of FEATURE_FLAGS) {
|
|
||||||
test(`Feature flag '${featureFlag}' is enabled if enabled in the API response`, async (t) => {
|
test(`Feature flag '${featureFlag}' is enabled if enabled in the API response`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
|
||||||
const featureFlags = new GitHubFeatureFlags(
|
|
||||||
{ type: GitHubVariant.DOTCOM },
|
|
||||||
testApiDetails,
|
|
||||||
testRepositoryNwo,
|
|
||||||
getRunnerLogger(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
// set all feature flags to false except the one we're testing
|
||||||
const expectedFeatureFlags: { [flag: string]: boolean } = {};
|
const expectedFeatureFlags: { [flag: string]: boolean } = {};
|
||||||
for (const f of FEATURE_FLAGS) {
|
for (const f of Object.keys(featureFlagConfig)) {
|
||||||
expectedFeatureFlags[f] = false;
|
expectedFeatureFlags[f] = f === featureFlag;
|
||||||
}
|
}
|
||||||
expectedFeatureFlags[featureFlag] = true;
|
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureFlags);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureFlags);
|
||||||
|
|
||||||
const actualFeatureFlags: { [flag: string]: boolean } = {
|
// retrieve the values of the actual feature flags
|
||||||
ml_powered_queries_enabled: await featureFlags.getValue(
|
const actualFeatureFlags: { [flag: string]: boolean } = {};
|
||||||
FeatureFlag.MlPoweredQueriesEnabled
|
for (const f of Object.keys(featureFlagConfig)) {
|
||||||
),
|
actualFeatureFlags[f] = await featureFlags.getValue(f as FeatureFlag);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// Alls flags should be false except the one we're testing
|
||||||
t.deepEqual(actualFeatureFlags, expectedFeatureFlags);
|
t.deepEqual(actualFeatureFlags, expectedFeatureFlags);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(`Feature flag '${featureFlag}' is enabled if the associated environment variable is true`, async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
|
||||||
|
// set all feature flags to false
|
||||||
|
const expectedFeatureFlags: { [flag: string]: boolean } = {};
|
||||||
|
for (const f of Object.keys(featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = false;
|
||||||
|
}
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureFlags);
|
||||||
|
|
||||||
|
// feature flag should be disabled initially
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag as FeatureFlag)));
|
||||||
|
|
||||||
|
// set env var to true and check that the feature flag is now enabled
|
||||||
|
process.env[featureFlagConfig[featureFlag].envVar] = "true";
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag as FeatureFlag));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Feature flag '${featureFlag}' is disabled if the associated environment variable is false`, async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
|
||||||
|
// set all feature flags to true
|
||||||
|
const expectedFeatureFlags: { [flag: string]: boolean } = {};
|
||||||
|
for (const f of Object.keys(featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = true;
|
||||||
|
}
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureFlags);
|
||||||
|
|
||||||
|
// feature flag should be enabled initially
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag as FeatureFlag));
|
||||||
|
|
||||||
|
// set env var to false and check that the feature flag is now disabled
|
||||||
|
process.env[featureFlagConfig[featureFlag].envVar] = "false";
|
||||||
|
t.assert(!(await featureFlags.getValue(featureFlag as FeatureFlag)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (featureFlagConfig[featureFlag].minimumVersion !== undefined) {
|
||||||
|
test(`Feature flag '${featureFlag}' is disabled if the minimum CLI version is below ${featureFlagConfig[featureFlag].minimumVersion}`, async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureFlags = setUpTmpDir(tmpDir);
|
||||||
|
|
||||||
|
// set all feature flags to true
|
||||||
|
const expectedFeatureFlags: { [flag: string]: boolean } = {};
|
||||||
|
for (const f of Object.keys(featureFlagConfig)) {
|
||||||
|
expectedFeatureFlags[f] = true;
|
||||||
|
}
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureFlags);
|
||||||
|
|
||||||
|
// feature flag should be enabled initially (ignoring the minimum CLI version)
|
||||||
|
t.assert(await featureFlags.getValue(featureFlag as FeatureFlag));
|
||||||
|
|
||||||
|
// feature flag should be disabled when an old CLI version is set
|
||||||
|
let codeql = mockCodeQLVersion("2.0.0");
|
||||||
|
t.assert(
|
||||||
|
!(await featureFlags.getValue(featureFlag as FeatureFlag, codeql))
|
||||||
|
);
|
||||||
|
|
||||||
|
// even setting the env var to true should not enable the feature flag if
|
||||||
|
// the minimum CLI version is not met
|
||||||
|
process.env[featureFlagConfig[featureFlag].envVar] = "true";
|
||||||
|
t.assert(
|
||||||
|
!(await featureFlags.getValue(featureFlag as FeatureFlag, codeql))
|
||||||
|
);
|
||||||
|
|
||||||
|
// feature flag should be enabled when a new CLI version is set
|
||||||
|
// and env var is not set
|
||||||
|
process.env[featureFlagConfig[featureFlag].envVar] = "";
|
||||||
|
codeql = mockCodeQLVersion(
|
||||||
|
featureFlagConfig[featureFlag].minimumVersion
|
||||||
|
);
|
||||||
|
t.assert(
|
||||||
|
await featureFlags.getValue(featureFlag as FeatureFlag, codeql)
|
||||||
|
);
|
||||||
|
|
||||||
|
// set env var to false and check that the feature flag is now disabled
|
||||||
|
process.env[featureFlagConfig[featureFlag].envVar] = "false";
|
||||||
|
t.assert(
|
||||||
|
!(await featureFlags.getValue(featureFlag as FeatureFlag, codeql))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUpTmpDir(
|
||||||
|
tmpDir: string,
|
||||||
|
logger = getRunnerLogger(true),
|
||||||
|
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion
|
||||||
|
): FeatureFlags {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
|
return new GitHubFeatureFlags(
|
||||||
|
gitHubVersion,
|
||||||
|
testApiDetails,
|
||||||
|
testRepositoryNwo,
|
||||||
|
logger
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { getApiClient, GitHubApiDetails } from "./api-client";
|
import { getApiClient, GitHubApiDetails } from "./api-client";
|
||||||
|
import { CodeQL } from "./codeql";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { RepositoryNwo } from "./repository";
|
import { RepositoryNwo } from "./repository";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
|
||||||
export interface FeatureFlags {
|
export interface FeatureFlags {
|
||||||
getValue(flag: FeatureFlag): Promise<boolean>;
|
getValue(flag: FeatureFlag, codeql?: CodeQL): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FeatureFlag {
|
export enum FeatureFlag {
|
||||||
|
|
@ -15,6 +16,32 @@ export enum FeatureFlag {
|
||||||
CliConfigFileEnabled = "cli_config_file_enabled",
|
CliConfigFileEnabled = "cli_config_file_enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const featureFlagConfig: Record<
|
||||||
|
FeatureFlag,
|
||||||
|
{ envVar: string; minimumVersion: string | undefined }
|
||||||
|
> = {
|
||||||
|
[FeatureFlag.BypassToolcacheEnabled]: {
|
||||||
|
envVar: "CODEQL_BYPASS_TOOLCACHE",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.MlPoweredQueriesEnabled]: {
|
||||||
|
envVar: "CODEQL_VERSION_ML_POWERED_QUERIES",
|
||||||
|
minimumVersion: "2.7.5",
|
||||||
|
},
|
||||||
|
[FeatureFlag.TrapCachingEnabled]: {
|
||||||
|
envVar: "CODEQL_TRAP_CACHING",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.GolangExtractionReconciliationEnabled]: {
|
||||||
|
envVar: "CODEQL_GOLANG_EXTRACTION_RECONCILIATION",
|
||||||
|
minimumVersion: undefined,
|
||||||
|
},
|
||||||
|
[FeatureFlag.CliConfigFileEnabled]: {
|
||||||
|
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||||
|
minimumVersion: "2.10.1",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A response from the GitHub API that contains feature flag enablement information for the CodeQL
|
* A response from the GitHub API that contains feature flag enablement information for the CodeQL
|
||||||
* Action.
|
* Action.
|
||||||
|
|
@ -33,12 +60,35 @@ export class GitHubFeatureFlags implements FeatureFlags {
|
||||||
private logger: Logger
|
private logger: Logger
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getValue(flag: FeatureFlag): Promise<boolean> {
|
async getValue(flag: FeatureFlag, codeql?: CodeQL): Promise<boolean> {
|
||||||
// Bypassing the toolcache is disabled in test mode.
|
// Bypassing the toolcache is disabled in test mode.
|
||||||
if (flag === FeatureFlag.BypassToolcacheEnabled && util.isInTestMode()) {
|
if (flag === FeatureFlag.BypassToolcacheEnabled && util.isInTestMode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const envVar = (
|
||||||
|
process.env[featureFlagConfig[flag].envVar] || ""
|
||||||
|
).toLocaleLowerCase();
|
||||||
|
|
||||||
|
// Do not use this feature if user explicitly disables it via an environment variable.
|
||||||
|
if (envVar === "false") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never use this feature if the CLI version explicitly can't support it.
|
||||||
|
const minimumVersion = featureFlagConfig[flag].minimumVersion;
|
||||||
|
if (codeql && minimumVersion) {
|
||||||
|
if (!(await util.codeQlVersionAbove(codeql, minimumVersion))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this feature if user explicitly enables it via an environment variable.
|
||||||
|
if (envVar === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask the GitHub API if the feature is enabled.
|
||||||
const response = await this.getApiResponse();
|
const response = await this.getApiResponse();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,9 @@ async function getTrapCachingEnabled(
|
||||||
featureFlags: FeatureFlags
|
featureFlags: FeatureFlags
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const trapCaching = getOptionalInput("trap-caching");
|
const trapCaching = getOptionalInput("trap-caching");
|
||||||
if (trapCaching !== undefined) return trapCaching === "true";
|
if (trapCaching !== undefined) {
|
||||||
|
return trapCaching === "true";
|
||||||
|
}
|
||||||
return await featureFlags.getValue(FeatureFlag.TrapCachingEnabled);
|
return await featureFlags.getValue(FeatureFlag.TrapCachingEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,3 +160,11 @@ export function mockFeatureFlagApiEndpoint(
|
||||||
|
|
||||||
sinon.stub(apiClient, "getApiClient").value(() => client);
|
sinon.stub(apiClient, "getApiClient").value(() => client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mockCodeQLVersion(version) {
|
||||||
|
return {
|
||||||
|
async getVersion() {
|
||||||
|
return version;
|
||||||
|
},
|
||||||
|
} as CodeQL.CodeQL;
|
||||||
|
}
|
||||||
|
|
|
||||||
109
src/util.test.ts
109
src/util.test.ts
|
|
@ -9,9 +9,7 @@ import test, { ExecutionContext } from "ava";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import * as api from "./api-client";
|
import * as api from "./api-client";
|
||||||
import { CodeQL } from "./codeql";
|
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
import { createFeatureFlags, FeatureFlag } from "./feature-flags";
|
|
||||||
import { getRunnerLogger, Logger } from "./logging";
|
import { getRunnerLogger, Logger } from "./logging";
|
||||||
import { setupTests } from "./testing-utils";
|
import { setupTests } from "./testing-utils";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
|
@ -495,113 +493,6 @@ test("listFolder", async (t) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("useCodeScanningConfigInCli with no env var", async (t) => {
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Yay! It works!
|
|
||||||
t.assert(
|
|
||||||
await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const val of ["TRUE", "true", "True"]) {
|
|
||||||
test(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
|
|
||||||
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Yay! It works!
|
|
||||||
t.assert(
|
|
||||||
await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const val of ["FALSE", "false", "False"]) {
|
|
||||||
test(`useCodeScanningConfigInCli with env var ${val}`, async (t) => {
|
|
||||||
// Never turned on when env var is false
|
|
||||||
process.env[util.EnvVar.CODEQL_PASS_CONFIG_TO_CLI] = val;
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.0"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([FeatureFlag.CliConfigFileEnabled])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
!(await util.useCodeScanningConfigInCli(
|
|
||||||
mockVersion("2.10.1"),
|
|
||||||
createFeatureFlags([])
|
|
||||||
))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockVersion(version) {
|
|
||||||
return {
|
|
||||||
async getVersion() {
|
|
||||||
return version;
|
|
||||||
},
|
|
||||||
} as CodeQL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const longTime = 999_999;
|
const longTime = 999_999;
|
||||||
const shortTime = 10;
|
const shortTime = 10;
|
||||||
|
|
||||||
|
|
|
||||||
44
src/util.ts
44
src/util.ts
|
|
@ -12,11 +12,7 @@ import * as semver from "semver";
|
||||||
import * as api from "./api-client";
|
import * as api from "./api-client";
|
||||||
import { getApiClient, GitHubApiDetails } from "./api-client";
|
import { getApiClient, GitHubApiDetails } from "./api-client";
|
||||||
import * as apiCompatibility from "./api-compatibility.json";
|
import * as apiCompatibility from "./api-compatibility.json";
|
||||||
import {
|
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql";
|
||||||
CodeQL,
|
|
||||||
CODEQL_VERSION_CONFIG_FILES,
|
|
||||||
CODEQL_VERSION_NEW_TRACING,
|
|
||||||
} from "./codeql";
|
|
||||||
import {
|
import {
|
||||||
Config,
|
Config,
|
||||||
parsePacksSpecification,
|
parsePacksSpecification,
|
||||||
|
|
@ -524,13 +520,6 @@ export enum EnvVar {
|
||||||
* own sandwiched workflow mechanism
|
* own sandwiched workflow mechanism
|
||||||
*/
|
*/
|
||||||
FEATURE_SANDWICH = "CODEQL_ACTION_FEATURE_SANDWICH",
|
FEATURE_SANDWICH = "CODEQL_ACTION_FEATURE_SANDWICH",
|
||||||
|
|
||||||
/**
|
|
||||||
* If set to the "true" string and the codeql CLI version is greater than
|
|
||||||
* `CODEQL_VERSION_CONFIG_FILES`, then the codeql-action will pass the
|
|
||||||
* the codeql-config file to the codeql CLI to be processed there.
|
|
||||||
*/
|
|
||||||
CODEQL_PASS_CONFIG_TO_CLI = "CODEQL_PASS_CONFIG_TO_CLI",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportVar = (mode: Mode, name: string, value: string) => {
|
const exportVar = (mode: Mode, name: string, value: string) => {
|
||||||
|
|
@ -593,10 +582,6 @@ export function getRequiredEnvParam(paramName: string): string {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOptionalEnvParam(paramName: string): string {
|
|
||||||
return process.env[paramName] || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HTTPError extends Error {
|
export class HTTPError extends Error {
|
||||||
public status: number;
|
public status: number;
|
||||||
|
|
||||||
|
|
@ -796,25 +781,7 @@ export async function useCodeScanningConfigInCli(
|
||||||
codeql: CodeQL,
|
codeql: CodeQL,
|
||||||
featureFlags: FeatureFlags
|
featureFlags: FeatureFlags
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const envVarIsEnabled = getOptionalEnvParam(EnvVar.CODEQL_PASS_CONFIG_TO_CLI);
|
return await featureFlags.getValue(FeatureFlag.CliConfigFileEnabled, codeql);
|
||||||
|
|
||||||
// If the user has explicitly turned off the feature, then don't use it.
|
|
||||||
if (envVarIsEnabled.toLocaleLowerCase() === "false") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user has explicitly turned on the feature, then use it.
|
|
||||||
// Or if the feature flag is enabled, then use it.
|
|
||||||
const isEnabled =
|
|
||||||
envVarIsEnabled.toLocaleLowerCase() === "true" ||
|
|
||||||
(await featureFlags.getValue(FeatureFlag.CliConfigFileEnabled));
|
|
||||||
|
|
||||||
if (!isEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the CLI version is too old, then don't use it.
|
|
||||||
return await codeQlVersionAbove(codeql, CODEQL_VERSION_CONFIG_FILES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logCodeScanningConfigInCli(
|
export async function logCodeScanningConfigInCli(
|
||||||
|
|
@ -867,11 +834,8 @@ export function listFolder(dir: string): string[] {
|
||||||
export async function isGoExtractionReconciliationEnabled(
|
export async function isGoExtractionReconciliationEnabled(
|
||||||
featureFlags: FeatureFlags
|
featureFlags: FeatureFlags
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return (
|
return await featureFlags.getValue(
|
||||||
process.env["CODEQL_ACTION_RECONCILE_GO_EXTRACTION"] === "true" ||
|
FeatureFlag.GolangExtractionReconciliationEnabled
|
||||||
(await featureFlags.getValue(
|
|
||||||
FeatureFlag.GolangExtractionReconciliationEnabled
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue