@@ -10,6 +10,8 @@ import {
1010 FeatureEnablement ,
1111 Features ,
1212 FEATURE_FLAGS_FILE_NAME ,
13+ FeatureConfig ,
14+ FeatureWithoutCLI ,
1315} from "./feature-flags" ;
1416import { getRunnerLogger } from "./logging" ;
1517import { parseRepositoryNwo } from "./repository" ;
@@ -46,7 +48,7 @@ test(`All features are disabled if running against GHES`, async (t) => {
4648
4749 for ( const feature of Object . values ( Feature ) ) {
4850 t . deepEqual (
49- await features . getValue ( feature , includeCodeQlIfRequired ( feature ) ) ,
51+ await getFeatureIncludingCodeQlIfRequired ( features , feature ) ,
5052 featureConfig [ feature ] . defaultValue ,
5153 ) ;
5254 }
@@ -75,9 +77,7 @@ test(`Feature flags are requested in GHEC-DR`, async (t) => {
7577
7678 for ( const feature of Object . values ( Feature ) ) {
7779 // Ensure we have gotten a response value back from the Mock API
78- t . assert (
79- await features . getValue ( feature , includeCodeQlIfRequired ( feature ) ) ,
80- ) ;
80+ t . assert ( await getFeatureIncludingCodeQlIfRequired ( features , feature ) ) ;
8181 }
8282
8383 // And that we haven't bailed preemptively.
@@ -104,7 +104,7 @@ test("API response missing and features use default value", async (t) => {
104104
105105 for ( const feature of Object . values ( Feature ) ) {
106106 t . assert (
107- ( await features . getValue ( feature , includeCodeQlIfRequired ( feature ) ) ) ===
107+ ( await getFeatureIncludingCodeQlIfRequired ( features , feature ) ) ===
108108 featureConfig [ feature ] . defaultValue ,
109109 ) ;
110110 }
@@ -124,7 +124,7 @@ test("Features use default value if they're not returned in API response", async
124124
125125 for ( const feature of Object . values ( Feature ) ) {
126126 t . assert (
127- ( await features . getValue ( feature , includeCodeQlIfRequired ( feature ) ) ) ===
127+ ( await getFeatureIncludingCodeQlIfRequired ( features , feature ) ) ===
128128 featureConfig [ feature ] . defaultValue ,
129129 ) ;
130130 }
@@ -151,7 +151,7 @@ test("Include no more than 25 features in each API request", async (t) => {
151151 // from the API.
152152 const feature = Object . values ( Feature ) [ 0 ] ;
153153 await t . notThrowsAsync ( async ( ) =>
154- features . getValue ( feature , includeCodeQlIfRequired ( feature ) ) ,
154+ getFeatureIncludingCodeQlIfRequired ( features , feature ) ,
155155 ) ;
156156 } ) ;
157157} ) ;
@@ -165,8 +165,7 @@ test("Feature flags exception is propagated if the API request errors", async (t
165165 const someFeature = Object . values ( Feature ) [ 0 ] ;
166166
167167 await t . throwsAsync (
168- async ( ) =>
169- features . getValue ( someFeature , includeCodeQlIfRequired ( someFeature ) ) ,
168+ async ( ) => getFeatureIncludingCodeQlIfRequired ( features , someFeature ) ,
170169 {
171170 message :
172171 "Encountered an error while trying to determine feature enablement: Error: some error message" ,
@@ -190,9 +189,9 @@ for (const feature of Object.keys(featureConfig)) {
190189 // retrieve the values of the actual features
191190 const actualFeatureEnablement : { [ feature : string ] : boolean } = { } ;
192191 for ( const f of Object . keys ( featureConfig ) ) {
193- actualFeatureEnablement [ f ] = await features . getValue (
192+ actualFeatureEnablement [ f ] = await getFeatureIncludingCodeQlIfRequired (
193+ features ,
194194 f as Feature ,
195- includeCodeQlIfRequired ( f ) ,
196195 ) ;
197196 }
198197
@@ -210,19 +209,16 @@ for (const feature of Object.keys(featureConfig)) {
210209
211210 // feature should be disabled initially
212211 t . assert (
213- ! ( await features . getValue (
212+ ! ( await getFeatureIncludingCodeQlIfRequired (
213+ features ,
214214 feature as Feature ,
215- includeCodeQlIfRequired ( feature ) ,
216215 ) ) ,
217216 ) ;
218217
219218 // set env var to true and check that the feature is now enabled
220219 process . env [ featureConfig [ feature ] . envVar ] = "true" ;
221220 t . assert (
222- await features . getValue (
223- feature as Feature ,
224- includeCodeQlIfRequired ( feature ) ,
225- ) ,
221+ await getFeatureIncludingCodeQlIfRequired ( features , feature as Feature ) ,
226222 ) ;
227223 } ) ;
228224 } ) ;
@@ -236,18 +232,15 @@ for (const feature of Object.keys(featureConfig)) {
236232
237233 // feature should be enabled initially
238234 t . assert (
239- await features . getValue (
240- feature as Feature ,
241- includeCodeQlIfRequired ( feature ) ,
242- ) ,
235+ await getFeatureIncludingCodeQlIfRequired ( features , feature as Feature ) ,
243236 ) ;
244237
245238 // set env var to false and check that the feature is now disabled
246239 process . env [ featureConfig [ feature ] . envVar ] = "false" ;
247240 t . assert (
248- ! ( await features . getValue (
241+ ! ( await getFeatureIncludingCodeQlIfRequired (
242+ features ,
249243 feature as Feature ,
250- includeCodeQlIfRequired ( feature ) ,
251244 ) ) ,
252245 ) ;
253246 } ) ;
@@ -264,13 +257,16 @@ for (const feature of Object.keys(featureConfig)) {
264257 const expectedFeatureEnablement = initializeFeatures ( true ) ;
265258 mockFeatureFlagApiEndpoint ( 200 , expectedFeatureEnablement ) ;
266259
267- await t . throwsAsync ( async ( ) => features . getValue ( feature as Feature ) , {
268- message : `Internal error: A ${
269- featureConfig [ feature ] . minimumVersion !== undefined
270- ? "minimum version"
271- : "required tools feature"
272- } is specified for feature ${ feature } , but no instance of CodeQL was provided.`,
273- } ) ;
260+ await t . throwsAsync (
261+ async ( ) => features . getValue ( feature as FeatureWithoutCLI ) ,
262+ {
263+ message : `Internal error: A ${
264+ featureConfig [ feature ] . minimumVersion !== undefined
265+ ? "minimum version"
266+ : "required tools feature"
267+ } is specified for feature ${ feature } , but no instance of CodeQL was provided.`,
268+ } ,
269+ ) ;
274270 } ) ;
275271 } ) ;
276272 }
@@ -354,9 +350,9 @@ test("Feature flags are saved to disk", async (t) => {
354350 ) ;
355351
356352 t . true (
357- await features . getValue (
353+ await getFeatureIncludingCodeQlIfRequired (
354+ features ,
358355 Feature . QaTelemetryEnabled ,
359- includeCodeQlIfRequired ( Feature . QaTelemetryEnabled ) ,
360356 ) ,
361357 "Feature flag should be enabled initially" ,
362358 ) ;
@@ -382,9 +378,9 @@ test("Feature flags are saved to disk", async (t) => {
382378 ( features as any ) . gitHubFeatureFlags . cachedApiResponse = undefined ;
383379
384380 t . false (
385- await features . getValue (
381+ await getFeatureIncludingCodeQlIfRequired (
382+ features ,
386383 Feature . QaTelemetryEnabled ,
387- includeCodeQlIfRequired ( Feature . QaTelemetryEnabled ) ,
388384 ) ,
389385 "Feature flag should be enabled after reading from cached file" ,
390386 ) ;
@@ -399,9 +395,9 @@ test("Environment variable can override feature flag cache", async (t) => {
399395
400396 const cachedFeatureFlags = path . join ( tmpDir , FEATURE_FLAGS_FILE_NAME ) ;
401397 t . true (
402- await features . getValue (
398+ await getFeatureIncludingCodeQlIfRequired (
399+ features ,
403400 Feature . QaTelemetryEnabled ,
404- includeCodeQlIfRequired ( Feature . QaTelemetryEnabled ) ,
405401 ) ,
406402 "Feature flag should be enabled initially" ,
407403 ) ;
@@ -413,9 +409,9 @@ test("Environment variable can override feature flag cache", async (t) => {
413409 process . env . CODEQL_ACTION_QA_TELEMETRY = "false" ;
414410
415411 t . false (
416- await features . getValue (
412+ await getFeatureIncludingCodeQlIfRequired (
413+ features ,
417414 Feature . QaTelemetryEnabled ,
418- includeCodeQlIfRequired ( Feature . QaTelemetryEnabled ) ,
419415 ) ,
420416 "Feature flag should be disabled after setting env var" ,
421417 ) ;
@@ -512,7 +508,7 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
512508
513509test ( "legacy feature flags should end with _enabled" , async ( t ) => {
514510 for ( const [ feature , config ] of Object . entries ( featureConfig ) ) {
515- if ( config . legacyApi ) {
511+ if ( ( config satisfies FeatureConfig as FeatureConfig ) . legacyApi ) {
516512 t . assert (
517513 feature . endsWith ( "_enabled" ) ,
518514 `legacy feature ${ feature } should end with '_enabled'` ,
@@ -523,7 +519,7 @@ test("legacy feature flags should end with _enabled", async (t) => {
523519
524520test ( "non-legacy feature flags should not end with _enabled" , async ( t ) => {
525521 for ( const [ feature , config ] of Object . entries ( featureConfig ) ) {
526- if ( ! config . legacyApi ) {
522+ if ( ! ( config satisfies FeatureConfig as FeatureConfig ) . legacyApi ) {
527523 t . false (
528524 feature . endsWith ( "_enabled" ) ,
529525 `non-legacy feature ${ feature } should not end with '_enabled'` ,
@@ -534,7 +530,7 @@ test("non-legacy feature flags should not end with _enabled", async (t) => {
534530
535531test ( "non-legacy feature flags should not start with codeql_action_" , async ( t ) => {
536532 for ( const [ feature , config ] of Object . entries ( featureConfig ) ) {
537- if ( ! config . legacyApi ) {
533+ if ( ! ( config satisfies FeatureConfig as FeatureConfig ) . legacyApi ) {
538534 t . false (
539535 feature . startsWith ( "codeql_action_" ) ,
540536 `non-legacy feature ${ feature } should not start with 'codeql_action_'` ,
@@ -573,12 +569,25 @@ function setUpFeatureFlagTests(
573569 * Returns an argument to pass to `getValue` that if required includes a CodeQL object meeting the
574570 * minimum version or tool feature requirements specified by the feature.
575571 */
576- function includeCodeQlIfRequired ( feature : string ) {
577- return featureConfig [ feature ] . minimumVersion !== undefined ||
578- featureConfig [ feature ] . toolsFeature !== undefined
579- ? mockCodeQLVersion (
580- "9.9.9" ,
581- Object . fromEntries ( Object . values ( ToolsFeature ) . map ( ( v ) => [ v , true ] ) ) ,
582- )
583- : undefined ;
572+ function getFeatureIncludingCodeQlIfRequired (
573+ features : FeatureEnablement ,
574+ feature : Feature ,
575+ ) {
576+ const config = featureConfig [
577+ feature
578+ ] satisfies FeatureConfig as FeatureConfig ;
579+ if (
580+ config . minimumVersion === undefined &&
581+ config . toolsFeature === undefined
582+ ) {
583+ return features . getValue ( feature as FeatureWithoutCLI ) ;
584+ }
585+
586+ return features . getValue (
587+ feature ,
588+ mockCodeQLVersion (
589+ "9.9.9" ,
590+ Object . fromEntries ( Object . values ( ToolsFeature ) . map ( ( v ) => [ v , true ] ) ) ,
591+ ) ,
592+ ) ;
584593}
0 commit comments