diff --git a/.github/workflows/build-dotnet.yaml b/.github/workflows/build-dotnet.yaml new file mode 100644 index 00000000..74930b1a --- /dev/null +++ b/.github/workflows/build-dotnet.yaml @@ -0,0 +1,66 @@ +--- +name: .NET Build + +on: + push: + branches: + - main + paths: + - 'dotnet-engine/**' + pull_request: + branches: + - main + paths: + - 'dotnet-engine/**' + +jobs: + build-dotnet: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read + steps: + - name: Checkout code + uses: actions/checkout@v3 + + ## snatched from build-java.yml + ## begin build yggdrasil (maybe this can be a separate job) + - name: Install rust + run: | + rustup set auto-self-update disable + rustup toolchain install stable --profile default + rustup show + - name: Rust cache + uses: Swatinem/rust-cache@v2 + - name: Build yggdrasil + run: cargo build --release + ## end build yggdrasil + + ## snatched from build-java.yml + ## Test requirements + - name: Get client spec + uses: actions/checkout@v3 + with: + repository: Unleash/client-specification + ref: v5.0.2 + path: client-specification + + - name: Set up .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.0.x' + + - name: Restore dependencies + run: | + cd dotnet-engine + dotnet restore dotnet-engine.sln + + - name: Build + run: dotnet build dotnet-engine.sln --configuration Release --no-restore + + - name: Test + run: | + cd Yggdrasil.Engine.Tests + dotnet test --no-restore + \ No newline at end of file diff --git a/.github/workflows/build-wasm.yaml b/.github/workflows/build-wasm.yaml new file mode 100644 index 00000000..097c6b9e --- /dev/null +++ b/.github/workflows/build-wasm.yaml @@ -0,0 +1,34 @@ +name: Build and Publish WASM + +on: + push: + branches: + - main + paths: + - 'wasm-engine/**' + tags: + - '*' + workflow_dispatch: + inputs: + version: + description: 'Version (for manual trigger)' + required: true + +jobs: + build-and-publish-wasm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: Install wasm-pack + uses: jetli/wasm-pack-action@v0.3.0 + + - name: Build WASM + run: wasm-pack build --target nodejs diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/dotnet-engine/README.md b/dotnet-engine/README.md index c7049225..270e88ec 100644 --- a/dotnet-engine/README.md +++ b/dotnet-engine/README.md @@ -20,6 +20,25 @@ dotnet build dotnet test ``` +## Development + +You can publish local packages to test with your SDK like this: + +```bash +dotnet build +dotnet pack /p:Version=1.0.0-alpha.0 +cd bin/Debug +dotnet nuget push "*.nupkg" -s ~/path/to/local/feed +``` + +Then add that local folder as a feed in NuGet + +```bash +dotnet nuget add source ~/path/to/local/feed +``` + +Now you can switch package source in package manager and import your locally published package to work with. + ## Running the benchmarks ```bash diff --git a/dotnet-engine/README.md.orig b/dotnet-engine/README.md.orig new file mode 100644 index 00000000..fbcca3d1 --- /dev/null +++ b/dotnet-engine/README.md.orig @@ -0,0 +1,50 @@ +# CSharp Bindings for Yggdrasil + +## Build + +Build the base project with cargo: + +```bash +cargo build --release +``` + +Csharp doesn't require the library path so this should work: + +```bash +dotnet build +``` + +## Running the tests + +```bash +dotnet test +``` + +<<<<<<< HEAD +## Running the benchmarks + +```bash +dotnet run --project Yggdrasil.Benchmarks -c Release +``` + +Output can be read in Yggdrasil.Benchmarks/BenchmarkDotNet.Artifacts/results +======= +## Development + +You can publish local packages to test with your SDK like this: + +```bash +dotnet build +dotnet pack /p:Version=1.0.0-alpha.0 +cd bin/Debug +dotnet nuget push "*.nupkg" -s ~/path/to/local/feed +``` + +Then add that local folder as a feed in NuGet + +```bash +dotnet nuget add source ~/path/to/local/feed +``` + +Now you can switch package source in package manager and import your locally published package to work with. +>>>>>>> origin/main diff --git a/dotnet-engine/Yggdrasil.Engine.Tests/YggdrasilEngineTest.cs b/dotnet-engine/Yggdrasil.Engine.Tests/YggdrasilEngineTest.cs index b3ace80e..0a19d2c1 100644 --- a/dotnet-engine/Yggdrasil.Engine.Tests/YggdrasilEngineTest.cs +++ b/dotnet-engine/Yggdrasil.Engine.Tests/YggdrasilEngineTest.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using System; using Newtonsoft.Json.Linq; -using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Yggdrasil; @@ -101,4 +100,67 @@ public void TestClientSpec() } } + [Test] + public void Impression_Data_Test_Enabled() { + var testDataObject = new { + Version = 2, + Features = new [] { + new { + Name = "with.impression.data", + Type = "release", + Enabled = true, + ImpressionData = true, + Strategies = new [] { + new { + Name = "default", + Parameters = new Dictionary() + } + } + } + } + }; + + var testData = JsonSerializer.Serialize(testDataObject, options); + var engine = new YggdrasilEngine(); + engine.TakeState(testData); + var featureName = "with.impression.data"; + var result = engine.IsEnabled(featureName, new Context()); + var shouldEmit = engine.ShouldEmitImpressionEvent(featureName); + Assert.NotNull(result); + Assert.IsTrue(result); + Assert.NotNull(shouldEmit); + Assert.IsTrue(shouldEmit); + } + + [Test] + public void Impression_Data_Test_Disabled() { + var testDataObject = new { + Version = 2, + Features = new [] { + new { + Name = "with.impression.data.false", + Type = "release", + Enabled = true, + ImpressionData = false, + Strategies = new [] { + new { + Name = "default", + Parameters = new Dictionary() + } + } + } + } + }; + + var testData = JsonSerializer.Serialize(testDataObject, options); + var engine = new YggdrasilEngine(); + engine.TakeState(testData); + var featureName = "with.impression.data.false"; + var result = engine.IsEnabled(featureName, new Context()); + var shouldEmit = engine.ShouldEmitImpressionEvent(featureName); + Assert.NotNull(result); + Assert.IsTrue(result); + Assert.NotNull(shouldEmit); + Assert.IsFalse(shouldEmit); + } } diff --git a/dotnet-engine/Yggdrasil.Engine/FFI.cs b/dotnet-engine/Yggdrasil.Engine/FFI.cs index 7403a21d..91aab6ea 100644 --- a/dotnet-engine/Yggdrasil.Engine/FFI.cs +++ b/dotnet-engine/Yggdrasil.Engine/FFI.cs @@ -24,6 +24,7 @@ string customStrategyResults private delegate void FreeResponseDelegate(IntPtr ptr); private delegate void CountToggleDelegate(IntPtr ptr, string toggle_name, bool enabled); private delegate void CountVariantDelegate(IntPtr ptr, string toggle_name, string variant_name); + private delegate bool ShouldEmitImpressionEventDelegate(IntPtr ptr, string toggle_name); private static readonly NewEngineDelegate _newEngine; private static readonly FreeEngineDelegate _freeEngine; @@ -34,6 +35,7 @@ string customStrategyResults private static readonly FreeResponseDelegate _free_response; private static readonly CountToggleDelegate _count_toggle; private static readonly CountVariantDelegate _count_variant; + private static readonly ShouldEmitImpressionEventDelegate _should_emit_impression_event; static FFI() { @@ -75,6 +77,10 @@ static FFI() _count_variant = Marshal.GetDelegateForFunctionPointer( NativeLibrary.GetExport(libHandle, "count_variant") ); + + _should_emit_impression_event = Marshal.GetDelegateForFunctionPointer( + NativeLibrary.GetExport(libHandle, "should_emit_impression_event") + ); } private static string GetLibraryPath() @@ -149,4 +155,9 @@ public static void CountVariant(IntPtr ptr, string toggle_name, string variant_n { _count_variant(ptr, toggle_name, variant_name); } + + public static bool ShouldEmitImpressionEvent(IntPtr ptr, string toggle_name) + { + return _should_emit_impression_event(ptr, toggle_name); + } } diff --git a/dotnet-engine/Yggdrasil.Engine/Yggdrasil.Engine.csproj b/dotnet-engine/Yggdrasil.Engine/Yggdrasil.Engine.csproj index 17f4c731..fff6dd77 100644 --- a/dotnet-engine/Yggdrasil.Engine/Yggdrasil.Engine.csproj +++ b/dotnet-engine/Yggdrasil.Engine/Yggdrasil.Engine.csproj @@ -4,17 +4,26 @@ net6.0 enable enable + Yggdrasil.Engine + 1.0.0-beta.0 + Bricks Software AS + Unleash + True + true Always + true Always + true Always + true diff --git a/dotnet-engine/Yggdrasil.Engine/YggdrasilEngine.cs b/dotnet-engine/Yggdrasil.Engine/YggdrasilEngine.cs index fc931f32..1afe792a 100644 --- a/dotnet-engine/Yggdrasil.Engine/YggdrasilEngine.cs +++ b/dotnet-engine/Yggdrasil.Engine/YggdrasilEngine.cs @@ -17,6 +17,11 @@ public YggdrasilEngine() state = FFI.NewEngine(); } + public bool ShouldEmitImpressionEvent(string featureName) + { + return FFI.ShouldEmitImpressionEvent(state, featureName); + } + public void Dispose() { FFI.FreeEngine(this.state); diff --git a/java-engine/build.gradle b/java-engine/build.gradle index 30811ac0..a4f4065e 100644 --- a/java-engine/build.gradle +++ b/java-engine/build.gradle @@ -24,9 +24,9 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' - jmh 'org.openjdk.jmh:jmh-core:1.33' + jmh 'org.openjdk.jmh:jmh-core:1.35' - jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.33' + jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.35' } // Apply a specific Java toolchain to ease working on different environments. @@ -42,7 +42,7 @@ tasks.named('test') { } jmh { - version = '1.33' + version = '1.35' fork = 2 includeTests = false iterations = 5 diff --git a/java-engine/src/jmh/java/UnleashEngineBenchmark.java b/java-engine/src/jmh/java/UnleashEngineBenchmark.java index 20aa5519..3e849ff9 100644 --- a/java-engine/src/jmh/java/UnleashEngineBenchmark.java +++ b/java-engine/src/jmh/java/UnleashEngineBenchmark.java @@ -1,17 +1,20 @@ package io.getunleash.engine; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Scope; -import com.fasterxml.jackson.core.type.TypeReference; +import com.sun.management.HotSpotDiagnosticMXBean; +import org.openjdk.jmh.annotations.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; + +import javax.management.MBeanServer; +import java.io.File; +import java.lang.management.ManagementFactory; import java.nio.file.Paths; import java.io.IOException; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; -@State(Scope.Thread) +@State(Scope.Benchmark) public class UnleashEngineBenchmark { private UnleashEngine engine; @@ -28,7 +31,12 @@ private static String loadFeaturesFromFile(String filePath) throws IOException { public void setUp() { engine = new UnleashEngine(new YggdrasilFFI("../target/release")); try { - engine.takeState(loadFeaturesFromFile(featureFilePath)); + dumpHeap("pre-take-state", true); + System.out.println("Loading features from " + featureFilePath); + String toggles = loadFeaturesFromFile(featureFilePath); + System.out.println("Taking state "+toggles); + engine.takeState(toggles); + dumpHeap("after-take-state", true); } catch (Exception e) { System.out.println("Failed to setup benchmarks"); e.printStackTrace(); @@ -36,15 +44,56 @@ public void setUp() { } } + long counter = 0; @Benchmark + @Fork(jvmArgsAppend = +{ + //"-XX:StartFlightRecording:settings=/home/gaston/.sdkman/candidates/java/20.0.2-oracle/lib/jfr/profile.jfc" + "-Xmx32m", + "-XX:+UseStringDeduplication", + "-XX:StartFlightRecording:filename=myrecording.jfr,settings=profile" +}) public void benchmarkFeatureToggle() { Context context = new Context(); try { - Boolean result = engine.isEnabled("Feature.A", context); + engine.isEnabled("Feature.A", context); + counter ++; + if (counter % (1500000+teardownCounter) == 0) { + UnleashEngineBenchmark.dumpHeap("inprocess-"+counter, true); + } } catch (Exception e) { System.out.println("Exception caught during benchmark, this is no longer a valid benchmark so early exiting"); e.printStackTrace(); System.exit(1); } } + + long teardownCounter = 0; + @TearDown + public void tearDown() throws Exception { + teardownCounter++; + System.out.println("After testing "+counter+" isEnabled calls"); + UnleashEngineBenchmark.dumpHeap("teardown-"+teardownCounter, true); + } + + static Random random = new Random(); + static Integer randomFamily = Double.valueOf(random.nextInt(100)).intValue(); + static AtomicLong dumpCounter = new AtomicLong(0); + public static void dumpHeap(String ref, boolean live) throws Exception { + String filepath = "heapdump."+randomFamily+"."+dumpCounter.incrementAndGet()+"-"+ref+".hprof"; + // check if file exists, if so, increment counter + while (new File(filepath).exists()) { + filepath = "heapdump."+randomFamily+"."+dumpCounter.incrementAndGet()+"-"+ref+".hprof"; + } + try { + + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy( + server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); + mxBean.dumpHeap(filepath, live); + } catch (IOException e) { + System.out.println("Failed to dump heap to "+filepath); + throw new Exception(e); + } + } } \ No newline at end of file diff --git a/java-engine/src/main/java/io/getunleash/engine/UnleashEngine.java b/java-engine/src/main/java/io/getunleash/engine/UnleashEngine.java index 6ba8b6ea..7109eaa3 100644 --- a/java-engine/src/main/java/io/getunleash/engine/UnleashEngine.java +++ b/java-engine/src/main/java/io/getunleash/engine/UnleashEngine.java @@ -4,8 +4,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.sun.jna.Pointer; @@ -13,9 +11,10 @@ public class UnleashEngine { private static final String UTF_8 = "UTF-8"; + private static final String CUSTOM_STRATEGY_RESULTS = "{}"; private final YggdrasilFFI yggdrasil; - private final ObjectReader reader; - private final ObjectWriter writer; + + private final ObjectMapper mapper; public UnleashEngine() { this(new YggdrasilFFI()); @@ -23,11 +22,9 @@ public UnleashEngine() { UnleashEngine(YggdrasilFFI yggdrasil) { this.yggdrasil = yggdrasil; - ObjectMapper mapper = new ObjectMapper(); + this.mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - reader = mapper.reader(); - writer = mapper.writer(); } public void takeState(String toggles) throws YggdrasilInvalidInputException { @@ -39,8 +36,8 @@ public void takeState(String toggles) throws YggdrasilInvalidInputException { public Boolean isEnabled(String name, Context context) throws YggdrasilInvalidInputException, YggdrasilError { try { - String jsonContext = writer.writeValueAsString(context); - YggResponse isEnabled = read(yggdrasil.checkEnabled(name, jsonContext, "{}"), new TypeReference<>() {}); + String jsonContext = mapper.writeValueAsString(context); + YggResponse isEnabled = read(yggdrasil.checkEnabled(name, jsonContext, CUSTOM_STRATEGY_RESULTS), new TypeReference<>() {}); return isEnabled.getValue(); } catch (JsonProcessingException e) { throw new YggdrasilInvalidInputException(context); @@ -49,8 +46,8 @@ public Boolean isEnabled(String name, Context context) throws YggdrasilInvalidIn public VariantDef getVariant(String name, Context context) throws YggdrasilInvalidInputException, YggdrasilError { try { - String jsonContext = writer.writeValueAsString(context); - YggResponse response = read(yggdrasil.checkVariant(name, jsonContext, "{}"), new TypeReference<>() {}); + String jsonContext = mapper.writeValueAsString(context); + YggResponse response = read(yggdrasil.checkVariant(name, jsonContext, CUSTOM_STRATEGY_RESULTS), new TypeReference<>() {}); return response.getValue(); } catch (JsonProcessingException e) { throw new YggdrasilInvalidInputException(context); @@ -66,20 +63,25 @@ public void countVariant(String flagName, String variantName) { } public MetricsBucket getMetrics() throws YggdrasilError { - YggResponse response = read(yggdrasil.getMetrics(), new TypeReference<>() {}); + YggResponse response = read(yggdrasil.getMetrics(), new TypeReference<>() { + }); return response.getValue(); } /** * Handle reading from a pointer into a String and mapping it to an object */ - private T read(Pointer pointer, TypeReference typeReference) { - String str = pointer.getString(0, UTF_8); - yggdrasil.freeResponse(pointer); + private T read(Pointer pointer, TypeReference clazz) { try { - return reader.forType(typeReference).readValue(str); - } catch (IOException e) { - throw new YggdrasilParseException(str, typeReference.getClass(), e); + String str = pointer.getString(0, UTF_8); + try { + return mapper.readValue(str, clazz); + } catch (IOException e) { + System.out.println("Failed to parse response from Yggdrasil: " + str); + throw new YggdrasilParseException(str, clazz.getClass(), e); + } + } finally { + yggdrasil.freeResponse(pointer); } } } \ No newline at end of file diff --git a/java-engine/src/test/java/io/getunleash/engine/UnleashEngineTest.java b/java-engine/src/test/java/io/getunleash/engine/UnleashEngineTest.java index e27734c4..99b35427 100644 --- a/java-engine/src/test/java/io/getunleash/engine/UnleashEngineTest.java +++ b/java-engine/src/test/java/io/getunleash/engine/UnleashEngineTest.java @@ -116,6 +116,10 @@ public void testClientSpec() throws Exception { result = false; // Default should be provided by SDK } + System.out.printf("[%s] Test '%s': expected %b, got %b%n", + suiteData.name, + test.get("description"), expectedResult, + result); assertEquals(expectedResult, result, String.format("[%s] Failed test '%s': expected %b, got %b", suiteData.name, @@ -141,6 +145,10 @@ public void testClientSpec() throws Exception { String expectedResultJson = objectMapper.writeValueAsString(expectedResult); String resultJson = objectMapper.writeValueAsString(result); + System.out.printf("[%s] Test '%s': expected %b, got %b%n", + suiteData.name, + test.get("description"), expectedResultJson, + resultJson); assertEquals(expectedResultJson, resultJson, String.format("[%s] Failed test '%s': expected %b, got %b", suiteData.name, diff --git a/unleash-yggdrasil/CHANGELOG.md b/unleash-yggdrasil/CHANGELOG.md index d7c94a37..48acd796 100644 --- a/unleash-yggdrasil/CHANGELOG.md +++ b/unleash-yggdrasil/CHANGELOG.md @@ -5,20 +5,91 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.8.0 (2023-11-13) + +### Chore + + - apply cargo fmt + +### New Features + + - add shouldemitimpressionevents to yggdrasil and .NET wrapper + * feat: add shouldemitimpressionevents to yggdrasil and .NET wrapper + + * feat: added some impression events tests in dotnet engine + - custom strategies in ruby and support in the core engine + +### Bug Fixes + + - make free floating quotes in string operators work correctly + +### Other + + - fix normalized hash result to start from 1 instead of 0 + +### Commit Statistics + + + + - 6 commits contributed to the release over the course of 12 calendar days. + - 13 days passed between releases. + - 5 commits were understood as [conventional](https://www.conventionalcommits.org). + - 5 unique issues were worked on: [#56](https://github.com/sighphyre/yggdrasil/issues/56), [#63](https://github.com/sighphyre/yggdrasil/issues/63), [#65](https://github.com/sighphyre/yggdrasil/issues/65), [#75](https://github.com/sighphyre/yggdrasil/issues/75), [#80](https://github.com/sighphyre/yggdrasil/issues/80) + +### Commit Details + + + +
view details + + * **[#56](https://github.com/sighphyre/yggdrasil/issues/56)** + - Custom strategies in ruby and support in the core engine ([`77537e0`](https://github.com/sighphyre/yggdrasil/commit/77537e0b45f197fa8ed43e061e1107dabb5c2a57)) + * **[#63](https://github.com/sighphyre/yggdrasil/issues/63)** + - Apply cargo fmt ([`fbfbe32`](https://github.com/sighphyre/yggdrasil/commit/fbfbe329dfbf435e4a010769bd118e6a9e347325)) + * **[#65](https://github.com/sighphyre/yggdrasil/issues/65)** + - Fix normalized hash result to start from 1 instead of 0 ([`adb57f6`](https://github.com/sighphyre/yggdrasil/commit/adb57f62ea8fd3db99107fdb22c562371c7032b0)) + * **[#75](https://github.com/sighphyre/yggdrasil/issues/75)** + - Add shouldemitimpressionevents to yggdrasil and .NET wrapper ([`8c5330b`](https://github.com/sighphyre/yggdrasil/commit/8c5330b1b6935ecd695058b9c7aa79d3f7766122)) + * **[#80](https://github.com/sighphyre/yggdrasil/issues/80)** + - Make free floating quotes in string operators work correctly ([`6919241`](https://github.com/sighphyre/yggdrasil/commit/6919241817638a7005974b0b85753e2464faa0fe)) + * **Uncategorized** + - Release unleash-yggdrasil v0.7.0 ([`d9204d6`](https://github.com/sighphyre/yggdrasil/commit/d9204d6e4301f64a038f2bed447bf3db08c0f8a8)) +
+ ## v0.7.0 (2023-10-30) + + + +### Other + + - fix normalized hash result to start from 1 instead of 0 + +### Bug Fixes + + - make free floating quotes in string operators work correctly + +### Chore + + - apply cargo fmt + ### New Features + + - new hashing implemented for variants + - add shouldemitimpressionevents to yggdrasil and .NET wrapper + * feat: add shouldemitimpressionevents to yggdrasil and .NET wrapper +* feat: added some impression events tests in dotnet engine ### Commit Statistics - - 2 commits contributed to the release. + - 3 commits contributed to the release. - 17 days passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#61](https://github.com/Unleash/yggdrasil/issues/61) + - 1 unique issue was worked on: [#61](https://github.com/sighphyre/yggdrasil/issues/61) ### Commit Details @@ -26,12 +97,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#61](https://github.com/Unleash/yggdrasil/issues/61)** - - New hashing implemented for variants ([`df0d854`](https://github.com/Unleash/yggdrasil/commit/df0d85445a91d987219fc60d26f2c6c097c0d878)) + * **[#61](https://github.com/sighphyre/yggdrasil/issues/61)** + - New hashing implemented for variants ([`df0d854`](https://github.com/sighphyre/yggdrasil/commit/df0d85445a91d987219fc60d26f2c6c097c0d878)) * **Uncategorized** - - Release unleash-yggdrasil v0.7.0 ([`38b87b5`](https://github.com/Unleash/yggdrasil/commit/38b87b52d980fe623d683d4d9bd792bbf34eeff2)) + - Release unleash-yggdrasil v0.7.0 ([`b57e44c`](https://github.com/sighphyre/yggdrasil/commit/b57e44cbcd79973896c6facd50f91866c1641a4a)) + - Release unleash-yggdrasil v0.7.0 ([`38b87b5`](https://github.com/sighphyre/yggdrasil/commit/38b87b52d980fe623d683d4d9bd792bbf34eeff2))
+ + custom strategies in ruby and support in the core engine + ## v0.6.1 (2023-10-13) ### New Features @@ -75,7 +150,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 4 commits contributed to the release. - 2 days passed between releases. - 2 commits were understood as [conventional](https://www.conventionalcommits.org). - - 2 unique issues were worked on: [#49](https://github.com/Unleash/yggdrasil/issues/49), [#51](https://github.com/Unleash/yggdrasil/issues/51) + - 2 unique issues were worked on: [#49](https://github.com/sighphyre/yggdrasil/issues/49), [#51](https://github.com/sighphyre/yggdrasil/issues/51) ### Commit Details @@ -83,13 +158,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#49](https://github.com/Unleash/yggdrasil/issues/49)** - - Add dependent flags ([`d89c183`](https://github.com/Unleash/yggdrasil/commit/d89c1837e1ef965eaea49e2b54c5a71bfa475877)) - * **[#51](https://github.com/Unleash/yggdrasil/issues/51)** - - Allows current time to be assumed when calculating the context ([`8bf7a69`](https://github.com/Unleash/yggdrasil/commit/8bf7a697411cd9e4b029151253740d67104faa88)) + * **[#49](https://github.com/sighphyre/yggdrasil/issues/49)** + - Add dependent flags ([`d89c183`](https://github.com/sighphyre/yggdrasil/commit/d89c1837e1ef965eaea49e2b54c5a71bfa475877)) + * **[#51](https://github.com/sighphyre/yggdrasil/issues/51)** + - Allows current time to be assumed when calculating the context ([`8bf7a69`](https://github.com/sighphyre/yggdrasil/commit/8bf7a697411cd9e4b029151253740d67104faa88)) * **Uncategorized** - - Release unleash-yggdrasil v0.6.1 ([`7cc8312`](https://github.com/Unleash/yggdrasil/commit/7cc831213005a619452121074a997d4a23a6f7b4)) - - Release unleash-yggdrasil v0.6.1 ([`32c21f6`](https://github.com/Unleash/yggdrasil/commit/32c21f6155deb4c1b7331f11c18e9a7a232f9489)) + - Release unleash-yggdrasil v0.6.1 ([`7cc8312`](https://github.com/sighphyre/yggdrasil/commit/7cc831213005a619452121074a997d4a23a6f7b4)) + - Release unleash-yggdrasil v0.6.1 ([`32c21f6`](https://github.com/sighphyre/yggdrasil/commit/32c21f6155deb4c1b7331f11c18e9a7a232f9489))
## v0.6.0 (2023-10-10) @@ -119,7 +194,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 4 commits contributed to the release over the course of 56 calendar days. - 84 days passed between releases. - 3 commits were understood as [conventional](https://www.conventionalcommits.org). - - 3 unique issues were worked on: [#42](https://github.com/Unleash/yggdrasil/issues/42), [#43](https://github.com/Unleash/yggdrasil/issues/43), [#48](https://github.com/Unleash/yggdrasil/issues/48) + - 3 unique issues were worked on: [#42](https://github.com/sighphyre/yggdrasil/issues/42), [#43](https://github.com/sighphyre/yggdrasil/issues/43), [#48](https://github.com/sighphyre/yggdrasil/issues/48) ### Commit Details @@ -127,14 +202,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#42](https://github.com/Unleash/yggdrasil/issues/42)** - - Better public api for ffi consumers ([`e08f62b`](https://github.com/Unleash/yggdrasil/commit/e08f62b77a8eb20121989fecf2b0161f9dc34215)) - * **[#43](https://github.com/Unleash/yggdrasil/issues/43)** - - Make ruby useful ([`c878e95`](https://github.com/Unleash/yggdrasil/commit/c878e9535018ecc10f99419528d1f6b8d2e9d6c5)) - * **[#48](https://github.com/Unleash/yggdrasil/issues/48)** - - Non strategy variants will work with empty strategy variants ([`137e4c8`](https://github.com/Unleash/yggdrasil/commit/137e4c8364f62262d7968c21e012e06083b6bd50)) + * **[#42](https://github.com/sighphyre/yggdrasil/issues/42)** + - Better public api for ffi consumers ([`e08f62b`](https://github.com/sighphyre/yggdrasil/commit/e08f62b77a8eb20121989fecf2b0161f9dc34215)) + * **[#43](https://github.com/sighphyre/yggdrasil/issues/43)** + - Make ruby useful ([`c878e95`](https://github.com/sighphyre/yggdrasil/commit/c878e9535018ecc10f99419528d1f6b8d2e9d6c5)) + * **[#48](https://github.com/sighphyre/yggdrasil/issues/48)** + - Non strategy variants will work with empty strategy variants ([`137e4c8`](https://github.com/sighphyre/yggdrasil/commit/137e4c8364f62262d7968c21e012e06083b6bd50)) * **Uncategorized** - - Release unleash-yggdrasil v0.6.0 ([`26f86b6`](https://github.com/Unleash/yggdrasil/commit/26f86b6023fa8be52a20158aade78646550c00cf)) + - Release unleash-yggdrasil v0.6.0 ([`26f86b6`](https://github.com/sighphyre/yggdrasil/commit/26f86b6023fa8be52a20158aade78646550c00cf))
## v0.5.9 (2023-07-18) @@ -156,7 +231,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 3 commits contributed to the release over the course of 20 calendar days. - 25 days passed between releases. - 2 commits were understood as [conventional](https://www.conventionalcommits.org). - - 2 unique issues were worked on: [#40](https://github.com/Unleash/yggdrasil/issues/40), [#41](https://github.com/Unleash/yggdrasil/issues/41) + - 2 unique issues were worked on: [#40](https://github.com/sighphyre/yggdrasil/issues/40), [#41](https://github.com/sighphyre/yggdrasil/issues/41) ### Commit Details @@ -164,12 +239,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#40](https://github.com/Unleash/yggdrasil/issues/40)** - - Updated to new chrono and unleash-types ([`7707e87`](https://github.com/Unleash/yggdrasil/commit/7707e875027b6e100205ae5e3a2fd416f4af17ea)) - * **[#41](https://github.com/Unleash/yggdrasil/issues/41)** - - Add support for strategy variants ([`135639f`](https://github.com/Unleash/yggdrasil/commit/135639fca552048221a626ff5e3beef1c35d7825)) + * **[#40](https://github.com/sighphyre/yggdrasil/issues/40)** + - Updated to new chrono and unleash-types ([`7707e87`](https://github.com/sighphyre/yggdrasil/commit/7707e875027b6e100205ae5e3a2fd416f4af17ea)) + * **[#41](https://github.com/sighphyre/yggdrasil/issues/41)** + - Add support for strategy variants ([`135639f`](https://github.com/sighphyre/yggdrasil/commit/135639fca552048221a626ff5e3beef1c35d7825)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.9 ([`851f488`](https://github.com/Unleash/yggdrasil/commit/851f488a2e4ec4c5217ffaa221cbc62aef5f6d2f)) + - Release unleash-yggdrasil v0.5.9 ([`851f488`](https://github.com/sighphyre/yggdrasil/commit/851f488a2e4ec4c5217ffaa221cbc62aef5f6d2f))
## v0.5.8 (2023-06-23) @@ -186,7 +261,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 3 commits contributed to the release. - 18 days passed between releases. - 2 commits were understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#39](https://github.com/Unleash/yggdrasil/issues/39) + - 1 unique issue was worked on: [#39](https://github.com/sighphyre/yggdrasil/issues/39) ### Commit Details @@ -194,11 +269,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#39](https://github.com/Unleash/yggdrasil/issues/39)** - - Add single toggle resolve method ([`a14f972`](https://github.com/Unleash/yggdrasil/commit/a14f97229ecf31eeef003d74b29b09e319f2d394)) + * **[#39](https://github.com/sighphyre/yggdrasil/issues/39)** + - Add single toggle resolve method ([`a14f972`](https://github.com/sighphyre/yggdrasil/commit/a14f97229ecf31eeef003d74b29b09e319f2d394)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.8 ([`64828b7`](https://github.com/Unleash/yggdrasil/commit/64828b70dd0a26336ba3113e585dab077dcb15e1)) - - Basic FFI language bindings ([`b36de19`](https://github.com/Unleash/yggdrasil/commit/b36de19e5c13add657273eff3c42ba204a31e860)) + - Release unleash-yggdrasil v0.5.8 ([`64828b7`](https://github.com/sighphyre/yggdrasil/commit/64828b70dd0a26336ba3113e585dab077dcb15e1)) + - Basic FFI language bindings ([`b36de19`](https://github.com/sighphyre/yggdrasil/commit/b36de19e5c13add657273eff3c42ba204a31e860))
## v0.5.7 (2023-06-05) @@ -215,7 +290,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 2 commits contributed to the release. - 18 days passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#37](https://github.com/Unleash/yggdrasil/issues/37) + - 1 unique issue was worked on: [#37](https://github.com/sighphyre/yggdrasil/issues/37) ### Commit Details @@ -223,10 +298,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#37](https://github.com/Unleash/yggdrasil/issues/37)** - - Support for arbitrary strings ([`280670e`](https://github.com/Unleash/yggdrasil/commit/280670e46cf654838d67817ade2b8963aaeb6198)) + * **[#37](https://github.com/sighphyre/yggdrasil/issues/37)** + - Support for arbitrary strings ([`280670e`](https://github.com/sighphyre/yggdrasil/commit/280670e46cf654838d67817ade2b8963aaeb6198)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.7 ([`fb00e58`](https://github.com/Unleash/yggdrasil/commit/fb00e58fbd151cbe149b0a0c6b6fff466fed0781)) + - Release unleash-yggdrasil v0.5.7 ([`fb00e58`](https://github.com/sighphyre/yggdrasil/commit/fb00e58fbd151cbe149b0a0c6b6fff466fed0781))
## v0.5.6 (2023-05-17) @@ -242,7 +317,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 2 commits contributed to the release. - 15 days passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#36](https://github.com/Unleash/yggdrasil/issues/36) + - 1 unique issue was worked on: [#36](https://github.com/sighphyre/yggdrasil/issues/36) ### Commit Details @@ -250,10 +325,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#36](https://github.com/Unleash/yggdrasil/issues/36)** - - Redesigns the way stickiness is handled in the grammar to support default and random ([`afb1cf8`](https://github.com/Unleash/yggdrasil/commit/afb1cf8512def7cfdbea4dde9e667fe4424e1bdf)) + * **[#36](https://github.com/sighphyre/yggdrasil/issues/36)** + - Redesigns the way stickiness is handled in the grammar to support default and random ([`afb1cf8`](https://github.com/sighphyre/yggdrasil/commit/afb1cf8512def7cfdbea4dde9e667fe4424e1bdf)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.6 ([`796dccb`](https://github.com/Unleash/yggdrasil/commit/796dccbd5e1d28e47d293cab1c6a07d0c8b2cc16)) + - Release unleash-yggdrasil v0.5.6 ([`796dccb`](https://github.com/sighphyre/yggdrasil/commit/796dccbd5e1d28e47d293cab1c6a07d0c8b2cc16))
## v0.5.5 (2023-05-02) @@ -269,7 +344,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 2 commits contributed to the release. - 13 days passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#34](https://github.com/Unleash/yggdrasil/issues/34) + - 1 unique issue was worked on: [#34](https://github.com/sighphyre/yggdrasil/issues/34) ### Commit Details @@ -277,10 +352,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#34](https://github.com/Unleash/yggdrasil/issues/34)** - - Fix variant stickiness ([`acf5cc1`](https://github.com/Unleash/yggdrasil/commit/acf5cc1007262675b0f5a03589ad0a62fd2c4fa6)) + * **[#34](https://github.com/sighphyre/yggdrasil/issues/34)** + - Fix variant stickiness ([`acf5cc1`](https://github.com/sighphyre/yggdrasil/commit/acf5cc1007262675b0f5a03589ad0a62fd2c4fa6)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.5 ([`c445d78`](https://github.com/Unleash/yggdrasil/commit/c445d78f98b559778649cf89bb95cbc59d027ff3)) + - Release unleash-yggdrasil v0.5.5 ([`c445d78`](https://github.com/sighphyre/yggdrasil/commit/c445d78f98b559778649cf89bb95cbc59d027ff3))
## v0.5.4 (2023-04-19) @@ -298,7 +373,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 2 commits contributed to the release. - 46 days passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#33](https://github.com/Unleash/yggdrasil/issues/33) + - 1 unique issue was worked on: [#33](https://github.com/sighphyre/yggdrasil/issues/33) ### Commit Details @@ -306,10 +381,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#33](https://github.com/Unleash/yggdrasil/issues/33)** - - Bump unleash types to 0.10.0 ([`0c1edd3`](https://github.com/Unleash/yggdrasil/commit/0c1edd38338e9ad0659ed80218aabd8235c36899)) + * **[#33](https://github.com/sighphyre/yggdrasil/issues/33)** + - Bump unleash types to 0.10.0 ([`0c1edd3`](https://github.com/sighphyre/yggdrasil/commit/0c1edd38338e9ad0659ed80218aabd8235c36899)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.4 ([`4da3483`](https://github.com/Unleash/yggdrasil/commit/4da34832edb373cda59ecd80f961ed2fc6d80918)) + - Release unleash-yggdrasil v0.5.4 ([`4da3483`](https://github.com/sighphyre/yggdrasil/commit/4da34832edb373cda59ecd80f961ed2fc6d80918))
## v0.5.3 (2023-03-03) @@ -325,7 +400,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 2 commits contributed to the release. - 1 day passed between releases. - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#31](https://github.com/Unleash/yggdrasil/issues/31) + - 1 unique issue was worked on: [#31](https://github.com/sighphyre/yggdrasil/issues/31) ### Commit Details @@ -333,10 +408,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#31](https://github.com/Unleash/yggdrasil/issues/31)** - - Add support for variants overrides on arbitrary context fields ([`6f8bd36`](https://github.com/Unleash/yggdrasil/commit/6f8bd369287000d248608a3ac4b2d062326c8cab)) + * **[#31](https://github.com/sighphyre/yggdrasil/issues/31)** + - Add support for variants overrides on arbitrary context fields ([`6f8bd36`](https://github.com/sighphyre/yggdrasil/commit/6f8bd369287000d248608a3ac4b2d062326c8cab)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.3 ([`b58f062`](https://github.com/Unleash/yggdrasil/commit/b58f06258e4f8540a93afe9dd3b5f264d84adc77)) + - Release unleash-yggdrasil v0.5.3 ([`b58f062`](https://github.com/sighphyre/yggdrasil/commit/b58f06258e4f8540a93afe9dd3b5f264d84adc77))
## v0.5.2 (2023-03-02) @@ -400,7 +475,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 30 commits contributed to the release over the course of 44 calendar days. - 22 commits were understood as [conventional](https://www.conventionalcommits.org). - - 25 unique issues were worked on: [#11](https://github.com/Unleash/yggdrasil/issues/11), [#12](https://github.com/Unleash/yggdrasil/issues/12), [#13](https://github.com/Unleash/yggdrasil/issues/13), [#14](https://github.com/Unleash/yggdrasil/issues/14), [#15](https://github.com/Unleash/yggdrasil/issues/15), [#16](https://github.com/Unleash/yggdrasil/issues/16), [#17](https://github.com/Unleash/yggdrasil/issues/17), [#18](https://github.com/Unleash/yggdrasil/issues/18), [#19](https://github.com/Unleash/yggdrasil/issues/19), [#2](https://github.com/Unleash/yggdrasil/issues/2), [#20](https://github.com/Unleash/yggdrasil/issues/20), [#21](https://github.com/Unleash/yggdrasil/issues/21), [#23](https://github.com/Unleash/yggdrasil/issues/23), [#24](https://github.com/Unleash/yggdrasil/issues/24), [#25](https://github.com/Unleash/yggdrasil/issues/25), [#27](https://github.com/Unleash/yggdrasil/issues/27), [#28](https://github.com/Unleash/yggdrasil/issues/28), [#29](https://github.com/Unleash/yggdrasil/issues/29), [#30](https://github.com/Unleash/yggdrasil/issues/30), [#4](https://github.com/Unleash/yggdrasil/issues/4), [#5](https://github.com/Unleash/yggdrasil/issues/5), [#6](https://github.com/Unleash/yggdrasil/issues/6), [#7](https://github.com/Unleash/yggdrasil/issues/7), [#8](https://github.com/Unleash/yggdrasil/issues/8), [#9](https://github.com/Unleash/yggdrasil/issues/9) + - 25 unique issues were worked on: [#11](https://github.com/sighphyre/yggdrasil/issues/11), [#12](https://github.com/sighphyre/yggdrasil/issues/12), [#13](https://github.com/sighphyre/yggdrasil/issues/13), [#14](https://github.com/sighphyre/yggdrasil/issues/14), [#15](https://github.com/sighphyre/yggdrasil/issues/15), [#16](https://github.com/sighphyre/yggdrasil/issues/16), [#17](https://github.com/sighphyre/yggdrasil/issues/17), [#18](https://github.com/sighphyre/yggdrasil/issues/18), [#19](https://github.com/sighphyre/yggdrasil/issues/19), [#2](https://github.com/sighphyre/yggdrasil/issues/2), [#20](https://github.com/sighphyre/yggdrasil/issues/20), [#21](https://github.com/sighphyre/yggdrasil/issues/21), [#23](https://github.com/sighphyre/yggdrasil/issues/23), [#24](https://github.com/sighphyre/yggdrasil/issues/24), [#25](https://github.com/sighphyre/yggdrasil/issues/25), [#27](https://github.com/sighphyre/yggdrasil/issues/27), [#28](https://github.com/sighphyre/yggdrasil/issues/28), [#29](https://github.com/sighphyre/yggdrasil/issues/29), [#30](https://github.com/sighphyre/yggdrasil/issues/30), [#4](https://github.com/sighphyre/yggdrasil/issues/4), [#5](https://github.com/sighphyre/yggdrasil/issues/5), [#6](https://github.com/sighphyre/yggdrasil/issues/6), [#7](https://github.com/sighphyre/yggdrasil/issues/7), [#8](https://github.com/sighphyre/yggdrasil/issues/8), [#9](https://github.com/sighphyre/yggdrasil/issues/9) ### Commit Details @@ -408,61 +483,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
view details - * **[#11](https://github.com/Unleash/yggdrasil/issues/11)** - - Update unleash-types to 0.4.1 to deal with variant weight type response from unleash ([`6e9688a`](https://github.com/Unleash/yggdrasil/commit/6e9688a251cc7a5ce77eb6ceef41a9038b9ff0a4)) - * **[#12](https://github.com/Unleash/yggdrasil/issues/12)** - - Bump version to 0.3.0 ([`01d5aef`](https://github.com/Unleash/yggdrasil/commit/01d5aefc52b07c2616116518b5de68d6ac36788c)) - * **[#13](https://github.com/Unleash/yggdrasil/issues/13)** - - Remove context object from this project ([`6e73b31`](https://github.com/Unleash/yggdrasil/commit/6e73b31448a39ecf1b194fb24039f7b3d6bf533c)) - * **[#14](https://github.com/Unleash/yggdrasil/issues/14)** - - Bump version to 0.4.0 ([`e1619d5`](https://github.com/Unleash/yggdrasil/commit/e1619d527175c197ff36bdaf9e57f6bbef0e17bf)) - * **[#15](https://github.com/Unleash/yggdrasil/issues/15)** - - Add basic benchmarks ([`36e55c6`](https://github.com/Unleash/yggdrasil/commit/36e55c6ce33f0710e7f41f72dab86e01ddff6707)) - * **[#16](https://github.com/Unleash/yggdrasil/issues/16)** - - Allow the engine to report the version of the Unleash client spec that it supports ([`d3f94be`](https://github.com/Unleash/yggdrasil/commit/d3f94be8ea473a8f3d465daa24bddbee487c8d45)) - * **[#17](https://github.com/Unleash/yggdrasil/issues/17)** - - Upgrade user id strategy to string types rather than numerics ([`0a6a19b`](https://github.com/Unleash/yggdrasil/commit/0a6a19b9be93c85b095f9f1bc4f1eb8b5cfd522c)) - * **[#18](https://github.com/Unleash/yggdrasil/issues/18)** - - Bump version to 0.4.1 ([`083f839`](https://github.com/Unleash/yggdrasil/commit/083f83994e44840647e6615164ebd17d781fd236)) - * **[#19](https://github.com/Unleash/yggdrasil/issues/19)** - - Handle cases where get_variant is called and variants is Some but empty ([`58d1cae`](https://github.com/Unleash/yggdrasil/commit/58d1cae7fbfa78f44adccf7c098011fc047f5c9c)) - * **[#2](https://github.com/Unleash/yggdrasil/issues/2)** - - Add readme for rust core ([`bdc912a`](https://github.com/Unleash/yggdrasil/commit/bdc912ab6a23c13d9b939152f6a7173040641ee4)) - * **[#20](https://github.com/Unleash/yggdrasil/issues/20)** - - Chore/clippy upgrade ([`b167998`](https://github.com/Unleash/yggdrasil/commit/b167998af3fe2edd88793d0e08b8409e1c046a7b)) - * **[#21](https://github.com/Unleash/yggdrasil/issues/21)** - - Bump types to 0.8.0 and upgrade version to 0.4.3 ([`ee13f4e`](https://github.com/Unleash/yggdrasil/commit/ee13f4ed2a6a1a13f70533fe568400bd2411742e)) - * **[#23](https://github.com/Unleash/yggdrasil/issues/23)** - - Bump version to 0.4.4 and unleash types to 0.8.1 ([`5ec32ac`](https://github.com/Unleash/yggdrasil/commit/5ec32accf621858f74fc454d4e99616eb96b7a38)) - * **[#24](https://github.com/Unleash/yggdrasil/issues/24)** - - Bump version to 0.4.5 ([`d996bcb`](https://github.com/Unleash/yggdrasil/commit/d996bcb37c9e0571ccc32dd130408b9b655cc406)) - * **[#25](https://github.com/Unleash/yggdrasil/issues/25)** - - Implement metrics gathering for core ([`0b5437f`](https://github.com/Unleash/yggdrasil/commit/0b5437ff5e6417bf8c2886ed97aad77c3b5b698a)) - * **[#27](https://github.com/Unleash/yggdrasil/issues/27)** - - Add resolve all features method ([`1617775`](https://github.com/Unleash/yggdrasil/commit/1617775d48207454bda7bc373de2bf0da7dd04cc)) - * **[#28](https://github.com/Unleash/yggdrasil/issues/28)** - - Bump unleash types to 0.9.0 ([`1e46813`](https://github.com/Unleash/yggdrasil/commit/1e4681329b1ca5436966c22c0e892b7a024496b9)) - * **[#29](https://github.com/Unleash/yggdrasil/issues/29)** - - Bump version to 0.5.1 ([`66bf3d8`](https://github.com/Unleash/yggdrasil/commit/66bf3d804482c0def165f2ebe282ac72c8917c57)) - * **[#30](https://github.com/Unleash/yggdrasil/issues/30)** - - Expose project on resolved toggle ([`7f402c2`](https://github.com/Unleash/yggdrasil/commit/7f402c238163d83cd8329dc8c4cbd005c4182a9e)) - * **[#4](https://github.com/Unleash/yggdrasil/issues/4)** - - Make clippy happy ([`0b89a94`](https://github.com/Unleash/yggdrasil/commit/0b89a94f5d91eb7ea218a7b8c502e2185c70b259)) - * **[#5](https://github.com/Unleash/yggdrasil/issues/5)** - - Add robustness handling to context property parsing when incoming properties values have null data ([`749ac3a`](https://github.com/Unleash/yggdrasil/commit/749ac3a51076e18313b4d4b1fcff8f47b24d497f)) - * **[#6](https://github.com/Unleash/yggdrasil/issues/6)** - - Remove reqwest, we don't use it ([`2384c16`](https://github.com/Unleash/yggdrasil/commit/2384c165aca366a6e7fdf4d7f688fd9949931471)) - * **[#7](https://github.com/Unleash/yggdrasil/issues/7)** - - Improve sad path handling of variants ([`2b6f889`](https://github.com/Unleash/yggdrasil/commit/2b6f88924d8c7a6dd592ac816fd0a86fb223db37)) - * **[#8](https://github.com/Unleash/yggdrasil/issues/8)** - - Add unicode support for the rule parser, this should now tolerate strings that contain unicode and a subset of punctuation ([`941bb90`](https://github.com/Unleash/yggdrasil/commit/941bb90e5c97cd14e843f55ed946005a2de811ea)) - * **[#9](https://github.com/Unleash/yggdrasil/issues/9)** - - Bump version to 0.2.0 ([`45787e3`](https://github.com/Unleash/yggdrasil/commit/45787e38e529427bd8e351a3c69f38f84e98657f)) + * **[#11](https://github.com/sighphyre/yggdrasil/issues/11)** + - Update unleash-types to 0.4.1 to deal with variant weight type response from unleash ([`6e9688a`](https://github.com/sighphyre/yggdrasil/commit/6e9688a251cc7a5ce77eb6ceef41a9038b9ff0a4)) + * **[#12](https://github.com/sighphyre/yggdrasil/issues/12)** + - Bump version to 0.3.0 ([`01d5aef`](https://github.com/sighphyre/yggdrasil/commit/01d5aefc52b07c2616116518b5de68d6ac36788c)) + * **[#13](https://github.com/sighphyre/yggdrasil/issues/13)** + - Remove context object from this project ([`6e73b31`](https://github.com/sighphyre/yggdrasil/commit/6e73b31448a39ecf1b194fb24039f7b3d6bf533c)) + * **[#14](https://github.com/sighphyre/yggdrasil/issues/14)** + - Bump version to 0.4.0 ([`e1619d5`](https://github.com/sighphyre/yggdrasil/commit/e1619d527175c197ff36bdaf9e57f6bbef0e17bf)) + * **[#15](https://github.com/sighphyre/yggdrasil/issues/15)** + - Add basic benchmarks ([`36e55c6`](https://github.com/sighphyre/yggdrasil/commit/36e55c6ce33f0710e7f41f72dab86e01ddff6707)) + * **[#16](https://github.com/sighphyre/yggdrasil/issues/16)** + - Allow the engine to report the version of the Unleash client spec that it supports ([`d3f94be`](https://github.com/sighphyre/yggdrasil/commit/d3f94be8ea473a8f3d465daa24bddbee487c8d45)) + * **[#17](https://github.com/sighphyre/yggdrasil/issues/17)** + - Upgrade user id strategy to string types rather than numerics ([`0a6a19b`](https://github.com/sighphyre/yggdrasil/commit/0a6a19b9be93c85b095f9f1bc4f1eb8b5cfd522c)) + * **[#18](https://github.com/sighphyre/yggdrasil/issues/18)** + - Bump version to 0.4.1 ([`083f839`](https://github.com/sighphyre/yggdrasil/commit/083f83994e44840647e6615164ebd17d781fd236)) + * **[#19](https://github.com/sighphyre/yggdrasil/issues/19)** + - Handle cases where get_variant is called and variants is Some but empty ([`58d1cae`](https://github.com/sighphyre/yggdrasil/commit/58d1cae7fbfa78f44adccf7c098011fc047f5c9c)) + * **[#2](https://github.com/sighphyre/yggdrasil/issues/2)** + - Add readme for rust core ([`bdc912a`](https://github.com/sighphyre/yggdrasil/commit/bdc912ab6a23c13d9b939152f6a7173040641ee4)) + * **[#20](https://github.com/sighphyre/yggdrasil/issues/20)** + - Chore/clippy upgrade ([`b167998`](https://github.com/sighphyre/yggdrasil/commit/b167998af3fe2edd88793d0e08b8409e1c046a7b)) + * **[#21](https://github.com/sighphyre/yggdrasil/issues/21)** + - Bump types to 0.8.0 and upgrade version to 0.4.3 ([`ee13f4e`](https://github.com/sighphyre/yggdrasil/commit/ee13f4ed2a6a1a13f70533fe568400bd2411742e)) + * **[#23](https://github.com/sighphyre/yggdrasil/issues/23)** + - Bump version to 0.4.4 and unleash types to 0.8.1 ([`5ec32ac`](https://github.com/sighphyre/yggdrasil/commit/5ec32accf621858f74fc454d4e99616eb96b7a38)) + * **[#24](https://github.com/sighphyre/yggdrasil/issues/24)** + - Bump version to 0.4.5 ([`d996bcb`](https://github.com/sighphyre/yggdrasil/commit/d996bcb37c9e0571ccc32dd130408b9b655cc406)) + * **[#25](https://github.com/sighphyre/yggdrasil/issues/25)** + - Implement metrics gathering for core ([`0b5437f`](https://github.com/sighphyre/yggdrasil/commit/0b5437ff5e6417bf8c2886ed97aad77c3b5b698a)) + * **[#27](https://github.com/sighphyre/yggdrasil/issues/27)** + - Add resolve all features method ([`1617775`](https://github.com/sighphyre/yggdrasil/commit/1617775d48207454bda7bc373de2bf0da7dd04cc)) + * **[#28](https://github.com/sighphyre/yggdrasil/issues/28)** + - Bump unleash types to 0.9.0 ([`1e46813`](https://github.com/sighphyre/yggdrasil/commit/1e4681329b1ca5436966c22c0e892b7a024496b9)) + * **[#29](https://github.com/sighphyre/yggdrasil/issues/29)** + - Bump version to 0.5.1 ([`66bf3d8`](https://github.com/sighphyre/yggdrasil/commit/66bf3d804482c0def165f2ebe282ac72c8917c57)) + * **[#30](https://github.com/sighphyre/yggdrasil/issues/30)** + - Expose project on resolved toggle ([`7f402c2`](https://github.com/sighphyre/yggdrasil/commit/7f402c238163d83cd8329dc8c4cbd005c4182a9e)) + * **[#4](https://github.com/sighphyre/yggdrasil/issues/4)** + - Make clippy happy ([`0b89a94`](https://github.com/sighphyre/yggdrasil/commit/0b89a94f5d91eb7ea218a7b8c502e2185c70b259)) + * **[#5](https://github.com/sighphyre/yggdrasil/issues/5)** + - Add robustness handling to context property parsing when incoming properties values have null data ([`749ac3a`](https://github.com/sighphyre/yggdrasil/commit/749ac3a51076e18313b4d4b1fcff8f47b24d497f)) + * **[#6](https://github.com/sighphyre/yggdrasil/issues/6)** + - Remove reqwest, we don't use it ([`2384c16`](https://github.com/sighphyre/yggdrasil/commit/2384c165aca366a6e7fdf4d7f688fd9949931471)) + * **[#7](https://github.com/sighphyre/yggdrasil/issues/7)** + - Improve sad path handling of variants ([`2b6f889`](https://github.com/sighphyre/yggdrasil/commit/2b6f88924d8c7a6dd592ac816fd0a86fb223db37)) + * **[#8](https://github.com/sighphyre/yggdrasil/issues/8)** + - Add unicode support for the rule parser, this should now tolerate strings that contain unicode and a subset of punctuation ([`941bb90`](https://github.com/sighphyre/yggdrasil/commit/941bb90e5c97cd14e843f55ed946005a2de811ea)) + * **[#9](https://github.com/sighphyre/yggdrasil/issues/9)** + - Bump version to 0.2.0 ([`45787e3`](https://github.com/sighphyre/yggdrasil/commit/45787e38e529427bd8e351a3c69f38f84e98657f)) * **Uncategorized** - - Release unleash-yggdrasil v0.5.2 ([`2a4a0fa`](https://github.com/Unleash/yggdrasil/commit/2a4a0faa1cbfb594e51b242818fc3f96b4ddc187)) - - Include changelog to prep for smart release ([`9b015f5`](https://github.com/Unleash/yggdrasil/commit/9b015f543b914e028b54717b2c79b4c04a8f3d8c)) - - Release unleash-yggdrasil v0.5.2 ([`e15c4a4`](https://github.com/Unleash/yggdrasil/commit/e15c4a46403461c4cedba6a2875ae7b8a075d4ee)) - - Add description and license to core ([`750e204`](https://github.com/Unleash/yggdrasil/commit/750e204ed3be475580c869c1a603c0e4da6af9bd)) - - Rename sdk-core to unleash-yggdrasil in preparation for publishing ([`d798951`](https://github.com/Unleash/yggdrasil/commit/d798951a5e34bde13974feaa8e189a5771712789)) + - Release unleash-yggdrasil v0.5.2 ([`2a4a0fa`](https://github.com/sighphyre/yggdrasil/commit/2a4a0faa1cbfb594e51b242818fc3f96b4ddc187)) + - Include changelog to prep for smart release ([`9b015f5`](https://github.com/sighphyre/yggdrasil/commit/9b015f543b914e028b54717b2c79b4c04a8f3d8c)) + - Release unleash-yggdrasil v0.5.2 ([`e15c4a4`](https://github.com/sighphyre/yggdrasil/commit/e15c4a46403461c4cedba6a2875ae7b8a075d4ee)) + - Add description and license to core ([`750e204`](https://github.com/sighphyre/yggdrasil/commit/750e204ed3be475580c869c1a603c0e4da6af9bd)) + - Rename sdk-core to unleash-yggdrasil in preparation for publishing ([`d798951`](https://github.com/sighphyre/yggdrasil/commit/d798951a5e34bde13974feaa8e189a5771712789))
diff --git a/unleash-yggdrasil/Cargo.toml b/unleash-yggdrasil/Cargo.toml index b0229b48..8c0a80ee 100644 --- a/unleash-yggdrasil/Cargo.toml +++ b/unleash-yggdrasil/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "unleash-yggdrasil" -version = "0.7.0" +version = "0.8.0" description = "This is the Unleash SDK domain logic extracted into a library to facilitate building your own Unleash SDKs in anything, anywhere." license = "MIT" diff --git a/unleash-yggdrasil/src/lib.rs b/unleash-yggdrasil/src/lib.rs index ac2edad9..d1469bb0 100644 --- a/unleash-yggdrasil/src/lib.rs +++ b/unleash-yggdrasil/src/lib.rs @@ -398,6 +398,15 @@ impl EngineState { }) } + pub fn should_emit_impression_event( + &self, + name: &str, + ) -> bool { + self.compiled_state.as_ref().and_then(|state| { + state.get(name).map(|compiled_toggle| compiled_toggle.impression_data) + }).unwrap_or_default() + } + pub fn check_enabled( &self, name: &str, diff --git a/unleash-yggdrasil/src/strategy_parsing.rs b/unleash-yggdrasil/src/strategy_parsing.rs index 53ec9590..c3878c26 100644 --- a/unleash-yggdrasil/src/strategy_parsing.rs +++ b/unleash-yggdrasil/src/strategy_parsing.rs @@ -206,7 +206,8 @@ fn string(node: Pair) -> String { let mut chars = node.as_str().chars(); chars.next(); chars.next_back(); - chars.as_str().into() + let string: String = chars.as_str().into(); + string.replace("\\\"", "\"") } //Constraints @@ -909,4 +910,13 @@ mod tests { assert!(true_result); assert!(!false_result); } + + #[test] + fn evaluates_quotes_in_stringy_rules_correctly() { + let rule = compile_rule("user_id contains_any [\"some\\\"thing\"]").unwrap(); + + let context = context_from_user_id("some\"thing"); + + assert!(rule(&context)); + } } diff --git a/unleash-yggdrasil/src/strategy_upgrade.rs b/unleash-yggdrasil/src/strategy_upgrade.rs index bef84362..2b3819fe 100644 --- a/unleash-yggdrasil/src/strategy_upgrade.rs +++ b/unleash-yggdrasil/src/strategy_upgrade.rs @@ -263,6 +263,10 @@ fn is_stringy(op: &Operator) -> bool { ) } +fn escape_quotes(stringy_operator: &str) -> String { + stringy_operator.replace('\"', "\\\"") +} + fn upgrade_constraint(constraint: &Constraint) -> String { let context_name = upgrade_context_name(&constraint.context_name); let op = upgrade_operator(&constraint.operator, constraint.case_insensitive); @@ -279,7 +283,7 @@ fn upgrade_constraint(constraint: &Constraint) -> String { .map(|values| { values .iter() - .map(|x| format!("\"{x}\"")) + .map(|x| format!("\"{}\"", escape_quotes(x))) .collect::>() .join(", ") }) @@ -803,4 +807,18 @@ mod tests { "true or true or external_value[\"customStrategy1\"] or external_value[\"customStrategy2\"] or true or external_value[\"customStrategy3\"]" ) } + + #[test] + fn correctly_escapes_free_quotes_in_string_operators() { + let constraint = Constraint { + context_name: "userId".into(), + operator: Operator::StrContains, + case_insensitive: false, + inverted: false, + values: Some(vec!["some\"thing".into()]), + value: None, + }; + let rule = upgrade_constraint(&constraint); + assert_eq!(rule.as_str(), "user_id contains_any [\"some\\\"thing\"]"); + } } diff --git a/wasm-engine/Cargo.toml b/wasm-engine/Cargo.toml index 594ba24e..2d60f1fa 100644 --- a/wasm-engine/Cargo.toml +++ b/wasm-engine/Cargo.toml @@ -1,8 +1,11 @@ [package] -name = "wasm-engine" -version = "0.1.0" -authors = ["sighphyre "] +name = "yggdrasil-engine" +version = "0.2.0" +authors = ["sighphyre "] +repository = "https://github.com/unleash/yggdrasil" +description = "Direct bindings to the Yggdrasil grammar for NodeJS" edition = "2018" +license = "MIT" [lib] crate-type = ["cdylib", "rlib"] diff --git a/wasm-engine/LICENSE b/wasm-engine/LICENSE new file mode 100644 index 00000000..8e0ee306 --- /dev/null +++ b/wasm-engine/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2023 Unleash + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/yggdrasilffi/Cargo.toml b/yggdrasilffi/Cargo.toml index 1fbde244..68dd52ef 100644 --- a/yggdrasilffi/Cargo.toml +++ b/yggdrasilffi/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "yggdrasilffi" -version = "0.1.0" +version = "0.2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/yggdrasilffi/src/lib.rs b/yggdrasilffi/src/lib.rs index 3917a39d..348ea9a3 100644 --- a/yggdrasilffi/src/lib.rs +++ b/yggdrasilffi/src/lib.rs @@ -312,6 +312,29 @@ pub unsafe extern "C" fn get_metrics(engine_ptr: *mut c_void) -> *mut c_char { result_to_json_ptr(result) } +/// Lets you know whether impression events are enabled for this toggle or not. +/// Returns false in case of error or if the toggle is not found. +/// +/// # Safety +/// +/// The caller is responsible for ensuring the engine_ptr is a valid pointer to an unleash engine. +/// An invalid pointer to unleash engine will result in undefined behaviour. +/// Null pointers will result in a false return value without undefined behaviour. +#[no_mangle] +pub unsafe extern "C" fn should_emit_impression_event( + engine_ptr: *mut c_void, + toggle_name_ptr: *const c_char +) -> bool { + let result: Result = (|| { + let engine = get_engine(engine_ptr)?; + let toggle_name = get_str(toggle_name_ptr)?; + + Ok(engine.should_emit_impression_event(toggle_name)) + })(); + + result.unwrap_or_default() +} + #[cfg(test)] mod tests { use std::ffi::{CStr, CString};