Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for sourcing feature flags from bicepconfig.json #8559

Merged
merged 9 commits into from
Oct 4, 2022

Conversation

jeskew
Copy link
Member

@jeskew jeskew commented Oct 3, 2022

Resolves #7955

This PR updates Bicep's feature flag façade to support multiple sources and adds two more: configuration via bicepconfig.json files and CLI arguments. The existing feature flag environment variables are still supported, but they may be overridden with a CLI argument, and if a feature is not explicitly enabled or disabled via CLI args or environment variables, the appropriate bicepconfig.json file for the template/module being compiled will be queried.

This PR updates IFeatureProvider to read from bicepconfig.json instead of the currently supported environment variables.

As a consequence of reading bicepconfig.json for feature flags, we can no longer associated an IFeatureProvider with a Compilation instance but must instead bind feature providers to the Compilation's constituent SemanticModel instances, as each bicep file may have different features enabled or disabled depending on its location on disk. The same is true of IApiVersionProvider, which takes an IFeatureProvider as a constructor argument.

Microsoft Reviewers: Open in CodeFlow

@jeskew jeskew requested a review from a team October 3, 2022 14:32
global.json Outdated Show resolved Hide resolved
@jeskew jeskew force-pushed the jeskew/source-feature-flags-from-config branch from 5b447a5 to fe8fd4d Compare October 3, 2022 23:19
@jeskew jeskew changed the title Add support for sourcing feature flags from bicepconfig.json and CLI args Add support for sourcing feature flags from bicepconfig.json Oct 3, 2022
@@ -17,14 +16,14 @@ public class InvocationContext
IAzResourceTypeLoader azResourceTypeLoader,
TextWriter outputWriter,
TextWriter errorWriter,
IFeatureProvider? features = null,
IFeatureProviderFactory? featureProviderFactory = null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be nullable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; this parameter is a backdoor for the integration tests to toggle various feature flags and set the assembly version to a static string. It is never set on contexts created in the Bicep.Cli package, which instead relies on the DI container to instantiate the factory.

jeskew added 2 commits October 4, 2022 02:29
Also emit a deprecation notice when a feature flag is sourced from an environment variable.
@jeskew jeskew force-pushed the jeskew/source-feature-flags-from-config branch from fe8fd4d to a7cd125 Compare October 4, 2022 12:56
Comment on lines +21 to +22
public bool RegistryEnabled => true;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove this? (feel free to create a follow-up issue)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. A fair number of tests explicitly disable the registry, so there may be something to address there.

bool? SourceMapping,
bool? ParamsFiles)
{
public static ExperimentalFeaturesEnabled Bind(JsonElement element, string? configurationPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to be difficult:

  1. What benefit do we get out of this being an object vs an array? e.g. "experimentalFeatures": ["foo", "bar"]
  2. What's the experience if the user opts-in to a feature which isn't supported by the compiler? Should we error/warning if that happens?

Copy link
Member Author

@jeskew jeskew Oct 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an object lets us turn on an experimental feature by default while still giving users a way to disable it if they run into any issues. We currently support this form of transition today (e.g., if we enabled symbolic name codegen by default, a user could turn it off with export BICEP_SYMBOLIC_NAME_CODEGEN_EXPERIMENTAL=false).

The behavior when a user tries to enable a non-existent feature flag is a config load error, which blocks compilation. This could be converted from an error to a warning, but I think that creates a confusing situation: with "symbolcNameCodegen": true, we would emit a non-blocking warning and then not use symbolic names.

Copy link
Member

@majastrz majastrz Oct 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to start strict and wait for feedback to relax it.

I can see a hypothetical situation where different users sharing the bicepconfig.json in a repo run different versions of bicep that have different sets of experimental features, which would force the enabled experimental features being a common denominator but I'm not terribly worried about that scenario... yet.

My preference is object as well for the same reasons. Disabling in an array requires removing the whole item from the array or comment out the item with block comments. With an object you can just change to false. (With completions that's as simple as selecting true, typing f and enter or tab.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as disabling features goes - my expectation is that we won't be shipping any "experimental" features that are true by default - instead we'll just remove the property from IFeatureProvider.

The scenarios for the object do feel a little hypothetical - but I also don't feel strongly about it being an array vs object.

@@ -61,5 +61,6 @@
}
}
}
}
},
"experimentalFeaturesEnabled": {}
Copy link
Member

@majastrz majastrz Oct 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimentalFeaturesEnabled

We have a JSON schema for the configuration. Should we add the new property and sub-properties to it? This way we'll get completions for the available experimental features.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to schema file but didn't document the sub-properties. We don't document the environment variables today, and it seemed like a lot of content to generate 😅

Copy link
Member

@anthony-c-martin anthony-c-martin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!


if (invocationContext.EmitterSettings.EnableSymbolicNames)
if (emitterSettings.EnableSymbolicNames)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a follow-up item, I think we should converge on a single message that covers enablement of all experimental features.

@jeskew jeskew enabled auto-merge (squash) October 4, 2022 21:02
@jeskew jeskew merged commit 6715860 into main Oct 4, 2022
@jeskew jeskew deleted the jeskew/source-feature-flags-from-config branch October 4, 2022 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add the ability to enable/disable preview features through Bicep config
3 participants