From 5efc8a603d1ad9d8887d75e38f95d5168a2319fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Kj=C3=A6r=20Henneberg?= Date: Wed, 17 Apr 2024 04:32:59 +1200 Subject: [PATCH 1/6] fix: Use new Statsig Api to return default value when flag is not defined (#177) Signed-off-by: Jens Henneberg --- .../README.md | 3 -- .../StatsigProvider.cs | 37 +++++++++++++++---- .../StatsigProviderTest.cs | 18 ++++++--- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/OpenFeature.Contrib.Providers.Statsig/README.md b/src/OpenFeature.Contrib.Providers.Statsig/README.md index 070c5571..91e679a3 100644 --- a/src/OpenFeature.Contrib.Providers.Statsig/README.md +++ b/src/OpenFeature.Contrib.Providers.Statsig/README.md @@ -94,6 +94,3 @@ The following parameters are mapped to the corresponding Statsig pre-defined par ## Known issues and limitations - Only `ResolveBooleanValue` implemented for now - -- Gate BooleanEvaluation with default value true cannot fallback to true. - https://github.com/statsig-io/dotnet-sdk/issues/33 diff --git a/src/OpenFeature.Contrib.Providers.Statsig/StatsigProvider.cs b/src/OpenFeature.Contrib.Providers.Statsig/StatsigProvider.cs index ee9287b7..b6bff9bc 100644 --- a/src/OpenFeature.Contrib.Providers.Statsig/StatsigProvider.cs +++ b/src/OpenFeature.Contrib.Providers.Statsig/StatsigProvider.cs @@ -1,8 +1,8 @@ using OpenFeature.Constant; -using OpenFeature.Error; using OpenFeature.Model; using Statsig; using Statsig.Server; +using Statsig.Server.Evaluation; using System; using System.Threading.Tasks; @@ -46,13 +46,34 @@ public StatsigProvider(string sdkKey = null, StatsigServerOptions statsigServerO /// public override Task> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null) { - //TODO: defaultvalue = true not yet supported due to https://github.com/statsig-io/dotnet-sdk/issues/33 - if (defaultValue == true) - throw new FeatureProviderException(ErrorType.General, "defaultvalue = true not supported (https://github.com/statsig-io/dotnet-sdk/issues/33)"); - if (GetStatus() != ProviderStatus.Ready) - return Task.FromResult(new ResolutionDetails(flagKey, defaultValue, ErrorType.ProviderNotReady)); - var result = ServerDriver.CheckGateSync(context.AsStatsigUser(), flagKey); - return Task.FromResult(new ResolutionDetails(flagKey, result)); + var result = ServerDriver.GetFeatureGate(context.AsStatsigUser(), flagKey); + var gateFound = false; + var responseType = ErrorType.None; + + switch (result.Reason) + { + case EvaluationReason.Network: + case EvaluationReason.LocalOverride: + case EvaluationReason.Bootstrap: + case EvaluationReason.DataAdapter: + gateFound = true; + break; + case EvaluationReason.Unrecognized: + responseType = ErrorType.FlagNotFound; + break; + case EvaluationReason.Uninitialized: + responseType = ErrorType.ProviderNotReady; + break; + case EvaluationReason.Unsupported: + responseType = ErrorType.InvalidContext; + break; + case EvaluationReason.Error: + responseType = ErrorType.General; + break; + case null: + break; + } + return Task.FromResult(new ResolutionDetails(flagKey, gateFound ? result.Value : defaultValue, responseType)); } /// diff --git a/test/OpenFeature.Contrib.Providers.Statsig.Test/StatsigProviderTest.cs b/test/OpenFeature.Contrib.Providers.Statsig.Test/StatsigProviderTest.cs index 73a09b5c..aaf1e23b 100644 --- a/test/OpenFeature.Contrib.Providers.Statsig.Test/StatsigProviderTest.cs +++ b/test/OpenFeature.Contrib.Providers.Statsig.Test/StatsigProviderTest.cs @@ -1,6 +1,5 @@ using AutoFixture.Xunit2; using OpenFeature.Constant; -using OpenFeature.Error; using OpenFeature.Model; using System.Threading.Tasks; using Xunit; @@ -41,25 +40,32 @@ public async Task GetBooleanValue_ForFeatureWithContext(bool flagValue, bool exp [Theory] [InlineAutoData(true, false)] [InlineAutoData(false, false)] - public async Task GetBooleanValue_ForFeatureWithNoContext_ReturnsFalse(bool flagValue, bool expectedValue, string flagName) + public async Task GetBooleanValue_ForFeatureWithNoContext_ReturnsDefaultValue(bool flagValue, bool defaultValue, string flagName) { // Arrange await statsigProvider.Initialize(null); statsigProvider.ServerDriver.OverrideGate(flagName, flagValue); // Act & Assert - Assert.Equal(expectedValue, statsigProvider.ResolveBooleanValue(flagName, false).Result.Value); + Assert.Equal(defaultValue, statsigProvider.ResolveBooleanValue(flagName, defaultValue).Result.Value); } [Theory] [AutoData] - public async Task GetBooleanValue_ForFeatureWithDefaultTrue_ThrowsException(string flagName) + [InlineAutoData(false)] + [InlineAutoData(true)] + public async Task GetBooleanValue_ForFeatureWithDefault(bool defaultValue, string flagName, string userId) { // Arrange await statsigProvider.Initialize(null); - // Act & Assert - Assert.ThrowsAny(() => statsigProvider.ResolveBooleanValue(flagName, true).Result.Value); + var ec = EvaluationContext.Builder().SetTargetingKey(userId).Build(); + + // Act + var result = await statsigProvider.ResolveBooleanValue(flagName, defaultValue, ec); + + //Assert + Assert.Equal(defaultValue, result.Value); } [Fact] From e45df09370e06307292596b4cbe1049586cad2a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:06:09 -0400 Subject: [PATCH 2/6] chore(main): release OpenFeature.Contrib.Providers.Statsig 0.0.4 (#174) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md | 8 ++++++++ .../OpenFeature.Contrib.Providers.Statsig.csproj | 2 +- src/OpenFeature.Contrib.Providers.Statsig/version.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e5be7bad..eba99ae3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -5,5 +5,5 @@ "src/OpenFeature.Contrib.Providers.Flagsmith": "0.1.6", "src/OpenFeature.Contrib.Providers.ConfigCat": "0.0.2", "src/OpenFeature.Contrib.Providers.FeatureManagement": "0.0.1", - "src/OpenFeature.Contrib.Providers.Statsig": "0.0.3" + "src/OpenFeature.Contrib.Providers.Statsig": "0.0.4" } \ No newline at end of file diff --git a/src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md b/src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md index b09d7174..0e77cd33 100644 --- a/src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md +++ b/src/OpenFeature.Contrib.Providers.Statsig/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.0.4](https://github.com/open-feature/dotnet-sdk-contrib/compare/OpenFeature.Contrib.Providers.Statsig-v0.0.3...OpenFeature.Contrib.Providers.Statsig-v0.0.4) (2024-04-16) + + +### 🐛 Bug Fixes + +* Fix Statsig nuget package name ([#172](https://github.com/open-feature/dotnet-sdk-contrib/issues/172)) ([3d089f5](https://github.com/open-feature/dotnet-sdk-contrib/commit/3d089f5c48478d7151fcf5964aa545471a0afe5c)) +* Use new Statsig Api to return default value when flag is not defined ([#177](https://github.com/open-feature/dotnet-sdk-contrib/issues/177)) ([5efc8a6](https://github.com/open-feature/dotnet-sdk-contrib/commit/5efc8a603d1ad9d8887d75e38f95d5168a2319fa)) + ## [0.0.3](https://github.com/open-feature/dotnet-sdk-contrib/compare/OpenFeature.Contrib.Providers.Statsig-v0.0.2...OpenFeature.Contrib.Providers.Statsig-v0.0.3) (2024-04-03) diff --git a/src/OpenFeature.Contrib.Providers.Statsig/OpenFeature.Contrib.Providers.Statsig.csproj b/src/OpenFeature.Contrib.Providers.Statsig/OpenFeature.Contrib.Providers.Statsig.csproj index d3e6084b..70ce34f2 100644 --- a/src/OpenFeature.Contrib.Providers.Statsig/OpenFeature.Contrib.Providers.Statsig.csproj +++ b/src/OpenFeature.Contrib.Providers.Statsig/OpenFeature.Contrib.Providers.Statsig.csproj @@ -2,7 +2,7 @@ OpenFeature.Contrib.Providers.Statsig - 0.0.3 + 0.0.4 $(VersionNumber) preview $(VersionNumber) diff --git a/src/OpenFeature.Contrib.Providers.Statsig/version.txt b/src/OpenFeature.Contrib.Providers.Statsig/version.txt index bcab45af..81340c7e 100644 --- a/src/OpenFeature.Contrib.Providers.Statsig/version.txt +++ b/src/OpenFeature.Contrib.Providers.Statsig/version.txt @@ -1 +1 @@ -0.0.3 +0.0.4 From 568da78d7bc4120c4b6fcb60e633e9e9bfc86027 Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Tue, 16 Apr 2024 17:03:24 -0400 Subject: [PATCH 3/6] chore: add @open-feature/sdk-dotnet-approvers as codeowner (#180) Signed-off-by: Michael Beemer Co-authored-by: Todd Baert --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 9436647d..2d0517e8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,4 +3,4 @@ # # Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-dotnet/workgroup.yaml # -* @open-feature/sdk-dotnet-maintainers +* @open-feature/sdk-dotnet-maintainers @open-feature/sdk-dotnet-approvers From 2a8093601ade4ee6295a9788b7b8a1c00d372685 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Tue, 23 Apr 2024 10:48:39 +0100 Subject: [PATCH 4/6] fix(flagsmith/tests): Fix ValueError in FlagsmithProvider tests (#186) Signed-off-by: Matthew Elwell --- .../FlagsmithProviderTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/OpenFeature.Contrib.Providers.Flagsmith.Test/FlagsmithProviderTest.cs b/test/OpenFeature.Contrib.Providers.Flagsmith.Test/FlagsmithProviderTest.cs index c5e60718..796e8edd 100644 --- a/test/OpenFeature.Contrib.Providers.Flagsmith.Test/FlagsmithProviderTest.cs +++ b/test/OpenFeature.Contrib.Providers.Flagsmith.Test/FlagsmithProviderTest.cs @@ -17,7 +17,7 @@ public class UnitTestFlagsmithProvider private static FlagsmithConfiguration GetDefaultFlagsmithConfiguration() => new() { ApiUrl = "https://edge.api.flagsmith.com/api/v1/", - EnvironmentKey = string.Empty, + EnvironmentKey = "some-key", EnableClientSideEvaluation = false, EnvironmentRefreshIntervalSeconds = 60, EnableAnalytics = false, From 65461c12f232da10627fe6be0892ba36945bedbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 14:41:15 +0100 Subject: [PATCH 5/6] chore(deps): update dependency flagsmith to v5.3.0 (#184) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../OpenFeature.Contrib.Providers.Flagsmith.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenFeature.Contrib.Providers.Flagsmith/OpenFeature.Contrib.Providers.Flagsmith.csproj b/src/OpenFeature.Contrib.Providers.Flagsmith/OpenFeature.Contrib.Providers.Flagsmith.csproj index 19acfeae..aa9e9868 100644 --- a/src/OpenFeature.Contrib.Providers.Flagsmith/OpenFeature.Contrib.Providers.Flagsmith.csproj +++ b/src/OpenFeature.Contrib.Providers.Flagsmith/OpenFeature.Contrib.Providers.Flagsmith.csproj @@ -19,7 +19,7 @@ - + From 6108d452d6c8a5c70c18b45ea9dd2e13612370ec Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 24 Apr 2024 15:56:08 -0400 Subject: [PATCH 6/6] fix: provider status incorrect (#187) Signed-off-by: Todd Baert --- .../FlagdProvider.cs | 10 ++++---- .../FlagdProviderTest.cs | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs b/src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs index 11bdd302..dc457da5 100644 --- a/src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs +++ b/src/OpenFeature.Contrib.Providers.Flagd/FlagdProvider.cs @@ -16,7 +16,7 @@ public sealed class FlagdProvider : FeatureProvider { const string ProviderName = "flagd Provider"; private readonly FlagdConfig _config; - private ProviderStatus _status; + private ProviderStatus _status = ProviderStatus.NotReady; private readonly Metadata _providerMetadata = new Metadata(ProviderName); private readonly Resolver.Resolver _resolver; @@ -118,11 +118,13 @@ public override Task Initialize(EvaluationContext context) { await _resolver.Init(); _status = ProviderStatus.Ready; - }).ContinueWith((t) => { - _status = ProviderStatus.Error; - if (t.IsFaulted) throw t.Exception; + if (t.IsFaulted) + { + _status = ProviderStatus.Error; + throw t.Exception; + }; }); } diff --git a/test/OpenFeature.Contrib.Providers.Flagd.Test/FlagdProviderTest.cs b/test/OpenFeature.Contrib.Providers.Flagd.Test/FlagdProviderTest.cs index e796ac90..70314b77 100644 --- a/test/OpenFeature.Contrib.Providers.Flagd.Test/FlagdProviderTest.cs +++ b/test/OpenFeature.Contrib.Providers.Flagd.Test/FlagdProviderTest.cs @@ -5,6 +5,7 @@ using Google.Protobuf.WellKnownTypes; using Grpc.Core; using NSubstitute; +using NSubstitute.ExceptionExtensions; using NSubstitute.ReceivedExtensions; using OpenFeature.Constant; using OpenFeature.Contrib.Providers.Flagd.Resolver.InProcess; @@ -525,6 +526,28 @@ public async Task TestCacheAsync() mockGrpcClient.Received(Quantity.AtLeastOne()).EventStream(Arg.Any(), null, null, CancellationToken.None); } + [Fact] + public async Task TestResolverInit_Success_Ready() + { + var mockResolver = Substitute.For(); + mockResolver.Init().Returns(Task.CompletedTask); + var provider = new FlagdProvider(resolver: mockResolver); + await provider.Initialize(EvaluationContext.Empty); + + Assert.Equal(ProviderStatus.Ready, provider.GetStatus()); + } + + [Fact] + public async Task TestResolverInit_Failure_Error() + { + var mockResolver = Substitute.For(); + mockResolver.Init().ThrowsAsync(new Exception("fake exception")); + var provider = new FlagdProvider(resolver: mockResolver); + await Assert.ThrowsAsync(() => provider.Initialize(EvaluationContext.Empty)); + + Assert.Equal(ProviderStatus.Error, provider.GetStatus()); + } + [Fact] public async Task TestCacheHitAsync() {