Merge branch 'main' into henrymercer/diagnostics-code-scanning-config
This commit is contained in:
commit
53f80edaf6
10 changed files with 53 additions and 41 deletions
1
.github/codeql/codeql-config.yml
vendored
1
.github/codeql/codeql-config.yml
vendored
|
|
@ -7,6 +7,7 @@ queries:
|
|||
# we include both even though one is a superset of the
|
||||
# other, because we're testing the parsing logic and
|
||||
# that the suites exist in the codeql bundle.
|
||||
- uses: security-experimental
|
||||
- uses: security-extended
|
||||
- uses: security-and-quality
|
||||
paths-ignore:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## [UNRELEASED]
|
||||
|
||||
No user facing changes.
|
||||
- Update default CodeQL bundle version to 2.12.4.
|
||||
|
||||
## 2.2.5 - 24 Feb 2023
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"bundleVersion": "codeql-bundle-20230217",
|
||||
"cliVersion": "2.12.3",
|
||||
"priorBundleVersion": "codeql-bundle-20230207",
|
||||
"priorCliVersion": "2.12.2"
|
||||
"bundleVersion": "codeql-bundle-20230304",
|
||||
"cliVersion": "2.12.4",
|
||||
"priorBundleVersion": "codeql-bundle-20230217",
|
||||
"priorCliVersion": "2.12.3"
|
||||
}
|
||||
|
|
|
|||
16
lib/feature-flags.js
generated
16
lib/feature-flags.js
generated
|
|
@ -45,22 +45,27 @@ exports.featureConfig = {
|
|||
[Feature.DisableKotlinAnalysisEnabled]: {
|
||||
envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS",
|
||||
minimumVersion: undefined,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.CliConfigFileEnabled]: {
|
||||
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||
minimumVersion: "2.11.6",
|
||||
defaultValue: true,
|
||||
},
|
||||
[Feature.ExportCodeScanningConfigEnabled]: {
|
||||
envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG",
|
||||
minimumVersion: codeql_1.CODEQL_VERSION_EXPORT_CODE_SCANNING_CONFIG,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.MlPoweredQueriesEnabled]: {
|
||||
envVar: "CODEQL_ML_POWERED_QUERIES",
|
||||
minimumVersion: "2.7.5",
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.UploadFailedSarifEnabled]: {
|
||||
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
|
||||
minimumVersion: "2.11.3",
|
||||
defaultValue: false,
|
||||
},
|
||||
};
|
||||
exports.FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
|
||||
|
|
@ -109,7 +114,8 @@ class Features {
|
|||
return true;
|
||||
}
|
||||
// Ask the GitHub API if the feature is enabled.
|
||||
return await this.gitHubFeatureFlags.getValue(feature);
|
||||
return ((await this.gitHubFeatureFlags.getValue(feature)) ??
|
||||
exports.featureConfig[feature].defaultValue);
|
||||
}
|
||||
}
|
||||
exports.Features = Features;
|
||||
|
|
@ -185,13 +191,13 @@ class GitHubFeatureFlags {
|
|||
async getValue(feature) {
|
||||
const response = await this.getAllFeatures();
|
||||
if (response === undefined) {
|
||||
this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`);
|
||||
return false;
|
||||
this.logger.debug(`No feature flags API response for ${feature}.`);
|
||||
return undefined;
|
||||
}
|
||||
const features = response[feature];
|
||||
if (features === undefined) {
|
||||
this.logger.debug(`Feature '${feature}' undefined in API response, considering it disabled.`);
|
||||
return false;
|
||||
this.logger.debug(`Feature '${feature}' undefined in API response.`);
|
||||
return undefined;
|
||||
}
|
||||
return !!features;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
12
lib/feature-flags.test.js
generated
12
lib/feature-flags.test.js
generated
|
|
@ -53,7 +53,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
const loggedMessages = [];
|
||||
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion);
|
||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||
t.false(await features.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||
t.deepEqual(await features.getValue(feature, includeCodeQlIfRequired(feature)), feature_flags_1.featureConfig[feature].defaultValue);
|
||||
}
|
||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||
v.message ===
|
||||
|
|
@ -61,26 +61,26 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
});
|
||||
});
|
||||
}
|
||||
(0, ava_1.default)("API response missing", async (t) => {
|
||||
(0, ava_1.default)("API response missing and features use default value", async (t) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const loggedMessages = [];
|
||||
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
|
||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||
t.assert((await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
|
||||
false);
|
||||
feature_flags_1.featureConfig[feature].defaultValue);
|
||||
}
|
||||
assertAllFeaturesUndefinedInApi(t, loggedMessages);
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("Features are disabled if they're not returned in API response", async (t) => {
|
||||
(0, ava_1.default)("Features use default value if they're not returned in API response", async (t) => {
|
||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const loggedMessages = [];
|
||||
const features = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
|
||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||
t.assert((await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
|
||||
false);
|
||||
feature_flags_1.featureConfig[feature].defaultValue);
|
||||
}
|
||||
assertAllFeaturesUndefinedInApi(t, loggedMessages);
|
||||
});
|
||||
|
|
@ -285,7 +285,7 @@ function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
|||
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||
v.message.includes(feature) &&
|
||||
v.message.includes("considering it disabled")) !== undefined);
|
||||
v.message.includes("undefined in API response")) !== undefined);
|
||||
}
|
||||
}
|
||||
function initializeFeatures(initialValue) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"bundleVersion": "codeql-bundle-20230217",
|
||||
"cliVersion": "2.12.3",
|
||||
"priorBundleVersion": "codeql-bundle-20230207",
|
||||
"priorCliVersion": "2.12.2"
|
||||
"bundleVersion": "codeql-bundle-20230304",
|
||||
"cliVersion": "2.12.4",
|
||||
"priorBundleVersion": "codeql-bundle-20230217",
|
||||
"priorCliVersion": "2.12.3"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,8 +54,9 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
);
|
||||
|
||||
for (const feature of Object.values(Feature)) {
|
||||
t.false(
|
||||
await features.getValue(feature, includeCodeQlIfRequired(feature))
|
||||
t.deepEqual(
|
||||
await features.getValue(feature, includeCodeQlIfRequired(feature)),
|
||||
featureConfig[feature].defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||
});
|
||||
}
|
||||
|
||||
test("API response missing", async (t) => {
|
||||
test("API response missing and features use default value", async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages: LoggedMessage[] = [];
|
||||
const features = setUpFeatureFlagTests(
|
||||
|
|
@ -84,14 +85,14 @@ test("API response missing", async (t) => {
|
|||
for (const feature of Object.values(Feature)) {
|
||||
t.assert(
|
||||
(await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
|
||||
false
|
||||
featureConfig[feature].defaultValue
|
||||
);
|
||||
}
|
||||
assertAllFeaturesUndefinedInApi(t, loggedMessages);
|
||||
});
|
||||
});
|
||||
|
||||
test("Features are disabled if they're not returned in API response", async (t) => {
|
||||
test("Features use default value if they're not returned in API response", async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
const loggedMessages: LoggedMessage[] = [];
|
||||
const features = setUpFeatureFlagTests(
|
||||
|
|
@ -104,7 +105,7 @@ test("Features are disabled if they're not returned in API response", async (t)
|
|||
for (const feature of Object.values(Feature)) {
|
||||
t.assert(
|
||||
(await features.getValue(feature, includeCodeQlIfRequired(feature))) ===
|
||||
false
|
||||
featureConfig[feature].defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +456,7 @@ function assertAllFeaturesUndefinedInApi(
|
|||
(v) =>
|
||||
v.type === "debug" &&
|
||||
(v.message as string).includes(feature) &&
|
||||
(v.message as string).includes("considering it disabled")
|
||||
(v.message as string).includes("undefined in API response")
|
||||
) !== undefined
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,27 +43,32 @@ export enum Feature {
|
|||
|
||||
export const featureConfig: Record<
|
||||
Feature,
|
||||
{ envVar: string; minimumVersion: string | undefined }
|
||||
{ envVar: string; minimumVersion: string | undefined; defaultValue: boolean }
|
||||
> = {
|
||||
[Feature.DisableKotlinAnalysisEnabled]: {
|
||||
envVar: "CODEQL_DISABLE_KOTLIN_ANALYSIS",
|
||||
minimumVersion: undefined,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.CliConfigFileEnabled]: {
|
||||
envVar: "CODEQL_PASS_CONFIG_TO_CLI",
|
||||
minimumVersion: "2.11.6",
|
||||
defaultValue: true,
|
||||
},
|
||||
[Feature.ExportCodeScanningConfigEnabled]: {
|
||||
envVar: "CODEQL_ACTION_EXPORT_CODE_SCANNING_CONFIG",
|
||||
minimumVersion: CODEQL_VERSION_EXPORT_CODE_SCANNING_CONFIG,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.MlPoweredQueriesEnabled]: {
|
||||
envVar: "CODEQL_ML_POWERED_QUERIES",
|
||||
minimumVersion: "2.7.5",
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.UploadFailedSarifEnabled]: {
|
||||
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
|
||||
minimumVersion: "2.11.3",
|
||||
defaultValue: false,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -146,11 +151,14 @@ export class Features implements FeatureEnablement {
|
|||
return true;
|
||||
}
|
||||
// Ask the GitHub API if the feature is enabled.
|
||||
return await this.gitHubFeatureFlags.getValue(feature);
|
||||
return (
|
||||
(await this.gitHubFeatureFlags.getValue(feature)) ??
|
||||
featureConfig[feature].defaultValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GitHubFeatureFlags implements FeatureEnablement {
|
||||
class GitHubFeatureFlags {
|
||||
private cachedApiResponse: GitHubFeatureFlagsApiResponse | undefined;
|
||||
|
||||
// We cache whether the feature flags were accessed or not in order to accurately report whether flags were
|
||||
|
|
@ -256,20 +264,16 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||
return { version: maxCliVersion, toolsFeatureFlagsValid: true };
|
||||
}
|
||||
|
||||
async getValue(feature: Feature): Promise<boolean> {
|
||||
async getValue(feature: Feature): Promise<boolean | undefined> {
|
||||
const response = await this.getAllFeatures();
|
||||
if (response === undefined) {
|
||||
this.logger.debug(
|
||||
`No feature flags API response for ${feature}, considering it disabled.`
|
||||
);
|
||||
return false;
|
||||
this.logger.debug(`No feature flags API response for ${feature}.`);
|
||||
return undefined;
|
||||
}
|
||||
const features = response[feature];
|
||||
if (features === undefined) {
|
||||
this.logger.debug(
|
||||
`Feature '${feature}' undefined in API response, considering it disabled.`
|
||||
);
|
||||
return false;
|
||||
this.logger.debug(`Feature '${feature}' undefined in API response.`);
|
||||
return undefined;
|
||||
}
|
||||
return !!features;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue