Skip to content

Conversation

@DHowett
Copy link
Member

@DHowett DHowett commented Jun 8, 2021

This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).

It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.

It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.

Features are added to src\features.xml and marked with a "stage". For
now, the only stages available are AlwaysDisabled and AlwaysEnabled.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.

For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:

  1. A preprocessor define TIL_FEATURE_XYZ_ENABLED (usable from MIDL,
    C++ and C)
  2. A feature class type Feature_XYZ with a static constexpr member
    IsEnabled() (usable from C++, designed for if constexpr()).

Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to if constexpr (false). :)

Michael suggested that we could use WindowsInbox as a branding to
determine when we were being built inside Windows to supplant our use of
the __INSIDE_WINDOWS preprocessor token. It was brilliant.

Design Decisions

  • Emitting the header as part of an MSBuild project
    • WHY: This allows the MSBuild engine to ensure that the build is
      only run once, even in a parallel build situation.
  • Only having one feature flag document for the entire project
    • WHY: Ease.
  • Forcibly including TilFeatureStaging with /FI for all CL compiler
    invocations.
    • WHY: If this is a project-wide feature system, we should make it as
      easy as possible to use.
  • Emitting preprocessor definitions instead of constexpr/consteval
    • WHY: Removing entire functions/includes is impossible with if constexpr.
    • WHY: MIDL cannot use a static constexpr bool, but it can rely on
      the C preprocessor to remove text.
  • Using MSBuild to emit the text instead of PowerShell
    • WHY: This allows us to leverage MSBuild's WriteOnlyWhenDifferent
      task parameter to avoid changing the file's modification time when
      it would have resulted in the same contents. This lets us use the
      same FeatureStaging header across multiple builds and multiple
      branches and brandings assuming that they do not result in a
      feature flag change
      .
    • The risk in using a force-include is always that it, for some
      reason, determines that the entire project is out of date. We've
      gone to great lengths to make sure that it only does so if the
      features actually materially changed.

@DHowett

This comment has been minimized.

@DHowett

This comment has been minimized.

2. Enabled branches
3. Disabled branches
* The longest branch token that matches your branch will win.
3. Enabled brandings
Copy link
Member

Choose a reason for hiding this comment

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

weird numbering

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks.

<WriteLinesToFile File="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
Lines="@(_FeatureFlagFileLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
Copy link
Member

Choose a reason for hiding this comment

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

This is some straight up wizardry.

// True so propsheet will show configuration options but be sure that
// the open one won't attempt handoff from double click of OpenConsole.exe
isEnabled = true;
isEnabled = Feature_AttemptHandoff::IsEnabled();
Copy link
Member Author

Choose a reason for hiding this comment

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

this actually breaks @miniksa's intent here, so NTS to fix it

Copy link
Member

@miniksa miniksa 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 to me, including the conversions from __INSIDE_WINDOWS. Now they actually have intent. If you've rid us of them all, though, you may want to remove that def completely so someone doesn't accidentally use it going forward and migrates to the feature flagging.

@DHowett DHowett force-pushed the dev/duhowett/jerk branch from 81ead62 to 8a10a63 Compare June 10, 2021 00:05
@github-actions

This comment has been minimized.

@microsoft microsoft deleted a comment from github-actions bot Jun 10, 2021
@microsoft microsoft deleted a comment from github-actions bot Jun 10, 2021
@DHowett DHowett changed the title [DRAFT] homebrew Velocity-like feature flagging Add support for branch and branding-based feature flagging Jun 10, 2021
@DHowett
Copy link
Member Author

DHowett commented Jun 10, 2021

@DHowett DHowett changed the title Add support for branch and branding-based feature flagging Add support for branch- and branding-based feature flagging Jun 10, 2021
@DHowett DHowett marked this pull request as ready for review June 10, 2021 16:03
@DHowett DHowett requested review from carlos-zamora and lhecker June 10, 2021 16:03
@microsoft microsoft deleted a comment from github-actions bot Jun 10, 2021
Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

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

This is fantastic! So excited for this to land :)

@carlos-zamora carlos-zamora added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jun 10, 2021
@ghost
Copy link

ghost commented Jun 10, 2021

Hello @carlos-zamora!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 31a39b3 into main Jun 10, 2021
@ghost ghost deleted the dev/duhowett/jerk branch June 10, 2021 23:09
DHowett added a commit that referenced this pull request Jul 7, 2021
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).

It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.

It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.

Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.

For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:

1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
   C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
   `IsEnabled()` (usable from C++, designed for `if constexpr()`).

Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)

Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.

Design Decisions
----------------

* Emitting the header as part of an MSBuild project
   * WHY: This allows the MSBuild engine to ensure that the build is
     only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
   * WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
  invocations.
   * WHY: If this is a project-wide feature system, we should make it as
     easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
   * WHY: Removing entire functions/includes is impossible with `if
     constexpr`.
   * WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
     the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
   * WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
     task parameter to avoid changing the file's modification time when
     it would have resulted in the same contents. This lets us use the
     same FeatureStaging header across multiple builds and multiple
     branches and brandings _assuming that they do not result in a
     feature flag change_.
   * The risk in using a force-include is always that it, for some
     reason, determines that the entire project is out of date. We've
     gone to great lengths to make sure that it only does so if the
     features _actually materially changed_.

(cherry picked from commit 31a39b3)
DHowett added a commit that referenced this pull request Jul 7, 2021
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).

It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.

It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.

Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.

For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:

1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
   C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
   `IsEnabled()` (usable from C++, designed for `if constexpr()`).

Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)

Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.

Design Decisions
----------------

* Emitting the header as part of an MSBuild project
   * WHY: This allows the MSBuild engine to ensure that the build is
     only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
   * WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
  invocations.
   * WHY: If this is a project-wide feature system, we should make it as
     easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
   * WHY: Removing entire functions/includes is impossible with `if
     constexpr`.
   * WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
     the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
   * WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
     task parameter to avoid changing the file's modification time when
     it would have resulted in the same contents. This lets us use the
     same FeatureStaging header across multiple builds and multiple
     branches and brandings _assuming that they do not result in a
     feature flag change_.
   * The risk in using a force-include is always that it, for some
     reason, determines that the entire project is out of date. We've
     gone to great lengths to make sure that it only does so if the
     features _actually materially changed_.

(cherry picked from commit 31a39b3)
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AutoMerge Marked for automatic merge by the bot when requirements are met

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants