RepoMicrosoftMicrosoftpublished May 21, 2019seen 1w

microsoft/PowerShell-FeatureFlags

PowerShell

Open original ↗

Captured source

source ↗

microsoft/PowerShell-FeatureFlags

Description: PowerShell module containing a Feature Flags implementation based on a local config file.

Language: PowerShell

License: MIT

Stars: 24

Forks: 11

Open issues: 11

Created: 2019-05-21T09:49:59Z

Pushed: 2026-06-19T06:22:39Z

Default branch: main

Fork: no

Archived: no

README:

PowerShell Feature Flags

This package contains a simple, low-dependencies implementation of feature flags for PowerShell, which relies on a local configuration file to verify if a given feature should be enabled or not.

The configuration file contains two sections:

  • stages: a section where roll-out stages are defined;
  • features: a section where each feature can be associated to a roll-out stage.

A roll-out *stage* is defined by a name and an array of *conditions* that the predicate must match in the order they are presented for the feature associated to the given stage to be enabled.

Stage names and feature names must be non-empty and must consist of non-space characters.

A feature can be assigned an array of stages that it applies to. In addition, it can also accept an environment variable array, and can optionally output an environment configuration file.

For more general information about feature flags, please visit featureflags.io.

Installation

This module is available from the PowerShell Gallery. Therefore, to install it for all users on the machine type the following from an administrator PowerShell prompt:

PS > Install-Module FeatureFlags

To install as an unprivileged user, type the following from any PowerShell prompt:

PS > Install-Module FeatureFlags -Scope CurrentUser

Simple example

Imagine to have a feature flag configuration file called features.json:

{
"stages": {
"test": [
{"allowlist": ["test.*", "dev.*"]}
],
"canary": [
{"allowlist": ["prod-canary"]}
],
"prod": [
{"allowlist": ["prod.*"]},
{"denylist": ["prod-canary"]}
]
},
"features": {
"experimental-feature": {
"stages": ["test"]
},
"well-tested-feature": {
"stages": ["test", "canary", "prod"]
}
}
}

This file defines 3 stages: test, canary and prod, and 2 features: experimental-feature and well-tested-feature.

The intent of the configuration is to enable experimental-feature in test only (all predicates starting with test or dev), and to enable well-tested-feature in all stages.

Let's first read the configuration:

$cfg = Get-FeatureFlagConfigFromFile features.json

This step would fail if there is any I/O error (e.g., file doesn't exist), if the file is not valid JSON or if the file does not conform with the [feature flags schema](featureflags.schema.json).

Let's now test a couple of predicates to verify that the configuration does what we expect:

PS > Test-FeatureFlag -config $cfg -Feature "well-tested-feature" -predicate "test1"
True
PS > Test-FeatureFlag -config $cfg -Feature "well-tested-feature" -predicate "test2"
True
PS > Test-FeatureFlag -config $cfg -Feature "well-tested-feature" -predicate "dev1"
True
PS > Test-FeatureFlag -config $cfg -Feature "well-tested-feature" -predicate "prod-canary1"
True
PS > Test-FeatureFlag -config $cfg -Feature "experimental-feature" -predicate "prod-canary1"
False
PS > Test-FeatureFlag -config $cfg -Feature "experimental-feature" -predicate "test1"
True
PS > Test-FeatureFlag -config $cfg -Feature "experimental-feature" -predicate "prod1"
False

For more complex examples, please look at test cases. More examples will be added in the future (Issue #6).

Life of a feature flag

Feature flags are expected to be in use while a feature is rolled out to production, or in case there is a need to conditionally enable or disable features.

An example lifecycle of a feature flag might be the following:

1. A new feature is checked in production after testing, in a disabled state; 2. The feature is enabled for a particular customer; 3. The feature is enabled for a small set of customers; 4. The feature is gradually rolled out to increasingly large percentages of customers (e.g., 5%, 10%, 30%, 50%); 5. The feature is rolled out to all customers (100%) 6. The test for the feature flag is removed from the code, and the feature flag configuration is removed as well.

Here is how these example stages could be implemented:

  • Stage 1 can be implemented with a denylist condition with value .*.
  • Stages 2 and 3 can be implemented with allowlist conditions.
  • Stages 4 and 5 can be implemented with probability conditions.

Conditions

There are two types of conditions: *deterministic* (allowlist and denylist, regex-based) and *probabilistic* (probability, expressed as a number between 0 and 1). Conditions can be repeated if multiple instances are required.

All conditions in each stage must be satisfied, in the order they are listed in the configuration file, for the feature to be considered enabled.

If any condition is not met, evaluation of conditions stops and the feature is considered disabled.

Allow list

The allowlist condition allows to specify a list of regular expressions; if the predicate matches any of the expressions, then the condition is met and the evaluation moves to the next condition, if there is any.

The regular expression is not anchored. This means that a regex of "storage" will match both the predicate "storage" and the predicate "storage1". To prevent unintended matches, it's recommended to always anchor the regex.

So, for example, "^storage$" will only match "storage" and not "storage1".

Deny list

The denylist condition is analogous to the allowlist condition, except that if the predicate matches any of the expressions the condition is considered not met and the evaluation stops.

Probability

The probability condition allows the user to specify a percentage of invocations that will lead to the condition to be met, expressed as a floating point number between 0 and 1.

So, if the user specifies a value of 0.3, roughly 30% of times the condition is checked it will be considered met, while for the remaining 70% of times it will be considered unmet.

The position of the probability condition is very important. Let's look at the following example:

{
"stages": {
"allowlist-first": [
{"allowlist": ["storage.*"]},
{"probability": 0.1}
],
"probability-first": [
{"probability": 0.1}
{"allowlist": ["storage.*"]},
]
}
}...

Excerpt shown — open the source for the full document.

Notability

notability 3.0/10

Routine PowerShell module with low traction.