Skip to content

Commit 3496d1c

Browse files
Merge pull request #541 from microsoft/main
Merge main to release/v4
2 parents 99b1bef + 139296d commit 3496d1c

38 files changed

Lines changed: 1459 additions & 366 deletions

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# If there are abnormal line endings in any file, run "git add --renormalize <file_name>",
2+
# review the changes, and commit them to fix the line endings.
3+
* text=auto

.github/workflows/codeql.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# For most projects, this workflow file will not need changing; you simply need
2+
# to commit it to your repository.
3+
#
4+
# You may wish to alter this file to override the set of languages analyzed,
5+
# or to provide custom queries or build logic.
6+
#
7+
# ******** NOTE ********
8+
# We have attempted to detect the languages in your repository. Please check
9+
# the `language` matrix defined below to confirm you have the correct set of
10+
# supported CodeQL languages.
11+
#
12+
name: "CodeQL Advanced"
13+
14+
on:
15+
push:
16+
branches: [ "main", "preview", "release/*" ]
17+
pull_request:
18+
branches: [ "main", "preview", "release/*" ]
19+
schedule:
20+
- cron: '21 11 * * 3'
21+
22+
jobs:
23+
analyze:
24+
name: Analyze (${{ matrix.language }})
25+
# Runner size impacts CodeQL analysis time. To learn more, please see:
26+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
27+
# - https://gh.io/supported-runners-and-hardware-resources
28+
# - https://gh.io/using-larger-runners (GitHub.com only)
29+
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
30+
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
31+
permissions:
32+
# required for all workflows
33+
security-events: write
34+
35+
# required to fetch internal or private CodeQL packs
36+
packages: read
37+
38+
# only required for workflows in private repositories
39+
actions: read
40+
contents: read
41+
42+
strategy:
43+
fail-fast: false
44+
matrix:
45+
include:
46+
- language: csharp
47+
build-mode: none
48+
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
49+
# Use `c-cpp` to analyze code written in C, C++ or both
50+
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
51+
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
52+
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
53+
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
54+
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
55+
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
56+
steps:
57+
- name: Checkout repository
58+
uses: actions/checkout@v4
59+
60+
# Initializes the CodeQL tools for scanning.
61+
- name: Initialize CodeQL
62+
uses: github/codeql-action/init@v3
63+
with:
64+
languages: ${{ matrix.language }}
65+
build-mode: ${{ matrix.build-mode }}
66+
# If you wish to specify custom queries, you can do so here or in a config file.
67+
# By default, queries listed here will override any specified in a config file.
68+
# Prefix the list here with "+" to use these queries and those in the config file.
69+
70+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
71+
# queries: security-extended,security-and-quality
72+
73+
# If the analyze step fails for one of the languages you are analyzing with
74+
# "We were unable to automatically build your code", modify the matrix above
75+
# to set the build mode to "manual" for that language. Then modify this step
76+
# to build your code.
77+
# ℹ️ Command-line programs to run using the OS shell.
78+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
79+
- if: matrix.build-mode == 'manual'
80+
shell: bash
81+
run: |
82+
echo 'If you are using a "manual" build mode for one or more of the' \
83+
'languages you are analyzing, replace this with the commands to build' \
84+
'your code, for example:'
85+
echo ' make bootstrap'
86+
echo ' make release'
87+
exit 1
88+
89+
- name: Perform CodeQL Analysis
90+
uses: github/codeql-action/analyze@v3
91+
with:
92+
category: "/language:${{matrix.language}}"

LICENSE

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
MIT License
2-
3-
Copyright (c) Microsoft Corporation. All rights reserved.
4-
5-
Permission is hereby granted, free of charge, to any person obtaining a copy
6-
of this software and associated documentation files (the "Software"), to deal
7-
in the Software without restriction, including without limitation the rights
8-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-
copies of the Software, and to permit persons to whom the Software is
10-
furnished to do so, subject to the following conditions:
11-
12-
The above copyright notice and this permission notice shall be included in all
13-
copies or substantial portions of the Software.
14-
15-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21-
SOFTWARE
1+
MIT License
2+
3+
Copyright (c) Microsoft Corporation. All rights reserved.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE

README.md

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
1-
# .NET Feature Management
2-
3-
[![Microsoft.FeatureManagement](https://img.shields.io/nuget/v/Microsoft.FeatureManagement?label=Microsoft.FeatureManagement)](https://www.nuget.org/packages/Microsoft.FeatureManagement)
4-
[![Microsoft.FeatureManagement.AspNetCore](https://img.shields.io/nuget/v/Microsoft.FeatureManagement.AspNetCore?label=Microsoft.FeatureManagement.AspNetCore)](https://www.nuget.org/packages/Microsoft.FeatureManagement.AspNetCore)
5-
6-
Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible.
7-
8-
## Get started
9-
10-
[**Quickstart**](https://learn.microsoft.com/azure/azure-app-configuration/quickstart-feature-flag-dotnet): A quickstart guide is available to learn how to integrate feature flags from *Azure App Configuration* into your .NET applications.
11-
12-
[**Feature Reference**](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-dotnet-reference): This document provides a full feature rundown.
13-
14-
[**API reference**](https://go.microsoft.com/fwlink/?linkid=2091700): This API reference details the API surface of the libraries contained within this repository.
15-
16-
## Examples
17-
18-
* [.NET Console App](./examples/ConsoleApp)
19-
* [.NET Console App with Targeting](./examples/TargetingConsoleApp)
20-
* [ASP.NET Core Web App (Razor Page)](./examples/RazorPages)
21-
* [ASP.NET Core Web App (MVC)](./examples/FeatureFlagDemo)
22-
* [Blazor Server App](./examples/BlazorServerApp)
23-
* [ASP.NET Core Web App with Variants and Telemetry](./examples/VariantAndTelemetryDemo)
24-
* [ASP.NET Core Web App with Variant Service](./examples/VariantServiceDemo)
25-
26-
## Contributing
27-
28-
This project welcomes contributions and suggestions. Most contributions require you to agree to a
29-
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
30-
the rights to use your contribution. For details, visit https://cla.microsoft.com.
31-
32-
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
33-
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
34-
provided by the bot. You will only need to do this once across all repos using our CLA.
35-
36-
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
37-
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
38-
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
1+
# .NET Feature Management
2+
3+
[![Microsoft.FeatureManagement](https://img.shields.io/nuget/v/Microsoft.FeatureManagement?label=Microsoft.FeatureManagement)](https://www.nuget.org/packages/Microsoft.FeatureManagement)
4+
[![Microsoft.FeatureManagement.AspNetCore](https://img.shields.io/nuget/v/Microsoft.FeatureManagement.AspNetCore?label=Microsoft.FeatureManagement.AspNetCore)](https://www.nuget.org/packages/Microsoft.FeatureManagement.AspNetCore)
5+
6+
Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common .NET code patterns to make exposing these features possible.
7+
8+
## Get started
9+
10+
[**Quickstart**](https://learn.microsoft.com/azure/azure-app-configuration/quickstart-feature-flag-dotnet): A quickstart guide is available to learn how to integrate feature flags from *Azure App Configuration* into your .NET applications.
11+
12+
[**Feature Reference**](https://learn.microsoft.com/azure/azure-app-configuration/feature-management-dotnet-reference): This document provides a full feature rundown.
13+
14+
[**API reference**](https://go.microsoft.com/fwlink/?linkid=2091700): This API reference details the API surface of the libraries contained within this repository.
15+
16+
## Examples
17+
18+
* [.NET Console App](./examples/ConsoleApp)
19+
* [.NET Console App with Targeting](./examples/TargetingConsoleApp)
20+
* [ASP.NET Core Web App (Razor Page)](./examples/RazorPages)
21+
* [ASP.NET Core Web App (MVC)](./examples/FeatureFlagDemo)
22+
* [Blazor Server App](./examples/BlazorServerApp)
23+
* [ASP.NET Core Web App with Variants and Telemetry](./examples/VariantAndTelemetryDemo)
24+
* [ASP.NET Core Web App with Variant Service](./examples/VariantServiceDemo)
25+
26+
## Contributing
27+
28+
This project welcomes contributions and suggestions. Most contributions require you to agree to a
29+
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
30+
the rights to use your contribution. For details, visit https://cla.microsoft.com.
31+
32+
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
33+
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
34+
provided by the bot. You will only need to do this once across all repos using our CLA.
35+
36+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
37+
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
38+
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

build/install-dotnet.ps1

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
# Installs .NET 6, .NET 7 and .NET 8 for CI/CD environment
1+
# Installs .NET 8 and .NET 9 for CI/CD environment
22
# see: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#examples
33

44
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
55

6-
&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 6.0
7-
8-
&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0
9-
106
&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 8.0
117

128
&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 9.0

examples/ConsoleApp/Program.cs

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the MIT license.
33
//
44
using Microsoft.Extensions.Configuration;
5-
using Microsoft.Extensions.DependencyInjection;
65
using Microsoft.FeatureManagement;
76

87
//
@@ -11,45 +10,35 @@
1110
.AddJsonFile("appsettings.json")
1211
.Build();
1312

14-
//
15-
// Setup application services + feature management
16-
IServiceCollection services = new ServiceCollection();
13+
var featureManager = new FeatureManager(new ConfigurationFeatureDefinitionProvider(configuration))
14+
{
15+
FeatureFilters = new List<IFeatureFilterMetadata> { new AccountIdFilter() }
16+
};
1717

18-
services.AddSingleton(configuration)
19-
.AddFeatureManagement()
20-
.AddFeatureFilter<AccountIdFilter>();
18+
var accounts = new List<string>()
19+
{
20+
"abc",
21+
"adef",
22+
"abcdefghijklmnopqrstuvwxyz"
23+
};
2124

2225
//
23-
// Get the feature manager from application services
24-
using (ServiceProvider serviceProvider = services.BuildServiceProvider())
26+
// Mimic work items in a task-driven console application
27+
foreach (var account in accounts)
2528
{
26-
IFeatureManager featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
27-
28-
var accounts = new List<string>()
29-
{
30-
"abc",
31-
"adef",
32-
"abcdefghijklmnopqrstuvwxyz"
33-
};
29+
const string FeatureName = "Beta";
3430

3531
//
36-
// Mimic work items in a task-driven console application
37-
foreach (var account in accounts)
32+
// Check if feature enabled
33+
//
34+
var accountServiceContext = new AccountServiceContext
3835
{
39-
const string FeatureName = "Beta";
40-
41-
//
42-
// Check if feature enabled
43-
//
44-
var accountServiceContext = new AccountServiceContext
45-
{
46-
AccountId = account
47-
};
36+
AccountId = account
37+
};
4838

49-
bool enabled = await featureManager.IsEnabledAsync(FeatureName, accountServiceContext);
39+
bool enabled = await featureManager.IsEnabledAsync(FeatureName, accountServiceContext);
5040

51-
//
52-
// Output results
53-
Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the '{account}' account.");
54-
}
41+
//
42+
// Output results
43+
Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the '{account}' account.");
5544
}

examples/FeatureFlagDemo/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public async Task<IActionResult> About()
3131
if (await _featureManager.IsEnabledAsync(MyFeatureFlags.CustomViewData))
3232
{
3333
ViewData["Message"] = $"This is FANCY CONTENT you can see only if '{MyFeatureFlags.CustomViewData}' is enabled.";
34-
};
34+
}
3535

3636
return View();
3737
}
Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using Microsoft.Extensions.Configuration;
2-
using Microsoft.Extensions.DependencyInjection;
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
//
4+
using Microsoft.Extensions.Configuration;
35
using Microsoft.FeatureManagement;
46
using Microsoft.FeatureManagement.FeatureFilters;
57
using TargetingConsoleApp.Identity;
@@ -10,48 +12,39 @@
1012
.AddJsonFile("appsettings.json")
1113
.Build();
1214

13-
//
14-
// Setup application services + feature management
15-
IServiceCollection services = new ServiceCollection();
16-
17-
services.AddSingleton(configuration)
18-
.AddFeatureManagement();
15+
var featureManager = new FeatureManager(new ConfigurationFeatureDefinitionProvider(configuration))
16+
{
17+
FeatureFilters = new List<IFeatureFilterMetadata> { new ContextualTargetingFilter() }
18+
};
1919

2020
var userRepository = new InMemoryUserRepository();
2121

2222
//
23-
// Get the feature manager from application services
24-
using (ServiceProvider serviceProvider = services.BuildServiceProvider())
23+
// We'll simulate a task to run on behalf of each known user
24+
// To do this we enumerate all the users in our user repository
25+
IEnumerable<string> userIds = InMemoryUserRepository.Users.Select(u => u.Id);
26+
27+
//
28+
// Mimic work items in a task-driven console application
29+
foreach (string userId in userIds)
2530
{
26-
IFeatureManager featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
31+
const string FeatureName = "Beta";
2732

2833
//
29-
// We'll simulate a task to run on behalf of each known user
30-
// To do this we enumerate all the users in our user repository
31-
IEnumerable<string> userIds = InMemoryUserRepository.Users.Select(u => u.Id);
34+
// Get user
35+
User user = await userRepository.GetUser(userId);
3236

3337
//
34-
// Mimic work items in a task-driven console application
35-
foreach (string userId in userIds)
38+
// Check if feature enabled
39+
var targetingContext = new TargetingContext
3640
{
37-
const string FeatureName = "Beta";
38-
39-
//
40-
// Get user
41-
User user = await userRepository.GetUser(userId);
42-
43-
//
44-
// Check if feature enabled
45-
var targetingContext = new TargetingContext
46-
{
47-
UserId = user.Id,
48-
Groups = user.Groups
49-
};
50-
51-
bool enabled = await featureManager.IsEnabledAsync(FeatureName, targetingContext);
52-
53-
//
54-
// Output results
55-
Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the user '{userId}'.");
56-
}
41+
UserId = user.Id,
42+
Groups = user.Groups
43+
};
44+
45+
bool enabled = await featureManager.IsEnabledAsync(FeatureName, targetingContext);
46+
47+
//
48+
// Output results
49+
Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the user '{userId}'.");
5750
}

0 commit comments

Comments
 (0)