From 17ccb1afbc150f1ebbde48f640f4cca64bd424ee Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 18 Jun 2026 09:43:20 -0500 Subject: [PATCH] feat: Add .NET OpenFeature server provider examples Migrates the example from launchdarkly/hello-openfeature-dotnet-server into the openfeature-server-provider/ partition following the EXAM layout: getting-started Flag Retrieval example, partition README index, per-example NOTICE (2022), and the root README SDK row. Modernized to target net8.0 only (dropped net471/net6.0) to align with the other examples. Sourced from hello-openfeature-dotnet-server (SDK-2562). --- .../workflows/openfeature-server-provider.yml | 41 +++++++++++++++ README.md | 9 ++-- openfeature-server-provider/README.md | 11 ++++ .../getting-started/Hello.cs | 51 +++++++++++++++++++ .../HelloOpenFeatureDotnet.csproj | 14 +++++ .../getting-started/NOTICE | 4 ++ .../getting-started/README.md | 20 ++++++++ 7 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/openfeature-server-provider.yml create mode 100644 openfeature-server-provider/README.md create mode 100644 openfeature-server-provider/getting-started/Hello.cs create mode 100644 openfeature-server-provider/getting-started/HelloOpenFeatureDotnet.csproj create mode 100644 openfeature-server-provider/getting-started/NOTICE create mode 100644 openfeature-server-provider/getting-started/README.md diff --git a/.github/workflows/openfeature-server-provider.yml b/.github/workflows/openfeature-server-provider.yml new file mode 100644 index 0000000..ef67c93 --- /dev/null +++ b/.github/workflows/openfeature-server-provider.yml @@ -0,0 +1,41 @@ +name: openfeature-server-provider +on: + schedule: + # * is a special character in YAML so you have to quote this string + - cron: '0 9 * * *' + push: + branches: [ main, 'feat/**' ] + paths: + - 'openfeature-server-provider/**' + - '.github/workflows/openfeature-server-provider.yml' + pull_request: + branches: [ main, 'feat/**' ] + paths: + - 'openfeature-server-provider/**' + - '.github/workflows/openfeature-server-provider.yml' + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + fail-fast: false + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Setup dotnet build tools + uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0 + with: + dotnet-version: 8.0 + + - name: Build openfeature-server-provider examples + shell: bash + run: | + set -e + for proj in $(find openfeature-server-provider -name '*.csproj' | sort); do + echo "::group::Building $proj" + dotnet build "$proj" + echo "::endgroup::" + done diff --git a/README.md b/README.md index 2cdc8bc..ead9134 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,11 @@ or the [.NET SDK reference guide](https://docs.launchdarkly.com/sdk/server-side/ ## SDKs -| SDK | Package | Examples | -|--------------------|-----------------------------|------------------------------------------| -| .NET Server SDK | `LaunchDarkly.ServerSdk` | [`server-sdk/`](./server-sdk/) | -| .NET Server AI SDK | `LaunchDarkly.ServerSdk.Ai` | [`server-sdk-ai/`](./server-sdk-ai/) | +| SDK | Package | Examples | +|----------------------------------|-------------------------------------------|-----------------------------------------------------------------| +| .NET Server SDK | `LaunchDarkly.ServerSdk` | [`server-sdk/`](./server-sdk/) | +| .NET Server AI SDK | `LaunchDarkly.ServerSdk.Ai` | [`server-sdk-ai/`](./server-sdk-ai/) | +| .NET OpenFeature server provider | `LaunchDarkly.OpenFeature.ServerProvider` | [`openfeature-server-provider/`](./openfeature-server-provider/) | ## Requirements diff --git a/openfeature-server-provider/README.md b/openfeature-server-provider/README.md new file mode 100644 index 0000000..3f07810 --- /dev/null +++ b/openfeature-server-provider/README.md @@ -0,0 +1,11 @@ +# LaunchDarkly .NET OpenFeature server provider examples + +Examples for the [`LaunchDarkly.OpenFeature.ServerProvider`](https://www.nuget.org/packages/LaunchDarkly.OpenFeature.ServerProvider) package. + +For more comprehensive instructions, you can visit your [Quickstart page](https://app.launchdarkly.com/quickstart#/) or the [.NET SDK reference guide](https://docs.launchdarkly.com/sdk/server-side/dotnet). + +## Getting Started + +| Example | Description | +|--------------------------------------|-------------------------------------------------------------| +| [Flag Retrieval](./getting-started/) | Initialize the OpenFeature provider and evaluate a feature flag | diff --git a/openfeature-server-provider/getting-started/Hello.cs b/openfeature-server-provider/getting-started/Hello.cs new file mode 100644 index 0000000..44b305d --- /dev/null +++ b/openfeature-server-provider/getting-started/Hello.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading.Tasks; +using LaunchDarkly.OpenFeature.ServerProvider; +using LaunchDarkly.Sdk.Server; +using OpenFeature.Model; + +namespace HelloOpenFeatureDotnetServer +{ + internal static class Hello + { + public static async Task Main(string[] args) + { + var sdkKey = Environment.GetEnvironmentVariable("LAUNCHDARKLY_SDK_KEY"); + var featureFlagKey = Environment.GetEnvironmentVariable("LAUNCHDARKLY_FLAG_KEY") ?? "sample-feature"; + + if (string.IsNullOrEmpty(sdkKey)) + { + Console.WriteLine("Please set an SDK key using the LAUNCHDARKLY_SDK_KEY environment variable."); + Environment.Exit(1); + } + + var config = Configuration.Builder(sdkKey).Build(); + + var provider = new Provider(config); + + await OpenFeature.Api.Instance.SetProviderAsync(provider); + + var client = OpenFeature.Api.Instance.GetClient(); + + // Set up the user properties. This user should appear on your LaunchDarkly users dashboard + // soon after you run the demo. + // Remember when using OpenFeature to use `targetingKey` instead of `key`. + var context = EvaluationContext.Builder() + .Set("kind", "user") + .Set("targetingKey", "example-user-key") + .Set("name", "Sandy") + .Build(); + + var flagValue = await client.GetBooleanValueAsync(featureFlagKey, false, context); + + Console.WriteLine($"The {featureFlagKey} feature flag evaluates to {(flagValue ? "true" : "false")}"); + + // Here we ensure that the SDK shuts down cleanly and has a chance to deliver analytics + // events to LaunchDarkly before the program exits. If analytics events are not delivered, + // the user properties and flag usage statistics will not appear on your dashboard. In a + // normal long-running application, the SDK would continue running and events would be + // delivered automatically in the background. + await OpenFeature.Api.Instance.ShutdownAsync(); + } + } +} diff --git a/openfeature-server-provider/getting-started/HelloOpenFeatureDotnet.csproj b/openfeature-server-provider/getting-started/HelloOpenFeatureDotnet.csproj new file mode 100644 index 0000000..2683d9b --- /dev/null +++ b/openfeature-server-provider/getting-started/HelloOpenFeatureDotnet.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + + + + + + + + + diff --git a/openfeature-server-provider/getting-started/NOTICE b/openfeature-server-provider/getting-started/NOTICE new file mode 100644 index 0000000..012deff --- /dev/null +++ b/openfeature-server-provider/getting-started/NOTICE @@ -0,0 +1,4 @@ +LaunchDarkly .NET OpenFeature server provider getting-started example +Copyright 2022 Catamorphic, Co. + +This product includes software developed at LaunchDarkly (https://launchdarkly.com/). diff --git a/openfeature-server-provider/getting-started/README.md b/openfeature-server-provider/getting-started/README.md new file mode 100644 index 0000000..a57aafa --- /dev/null +++ b/openfeature-server-provider/getting-started/README.md @@ -0,0 +1,20 @@ +# LaunchDarkly sample OpenFeature .NET server application + +We've built a simple console application that demonstrates how LaunchDarkly's OpenFeature server-side provider works. + +## Build instructions + +1. Set the environment variable `LAUNCHDARKLY_SDK_KEY` to your LaunchDarkly SDK key. If there is an existing boolean feature flag in your LaunchDarkly project that you want to evaluate, set `LAUNCHDARKLY_FLAG_KEY` to the flag key; otherwise, a boolean flag of `sample-feature` will be assumed. + + ```bash + export LAUNCHDARKLY_SDK_KEY="1234567890abcdef" + export LAUNCHDARKLY_FLAG_KEY="my-boolean-flag" + ``` + +2. Run the application from the command line: + + ```bash + dotnet run + ``` + +You should see the message `"The feature flag evaluates to "`.