Skip to content

feat(ofrep): AOT compatibility#651

Open
aldy505 wants to merge 14 commits into
open-feature:mainfrom
aldy505:feat/aot-compatibility
Open

feat(ofrep): AOT compatibility#651
aldy505 wants to merge 14 commits into
open-feature:mainfrom
aldy505:feat/aot-compatibility

Conversation

@aldy505

@aldy505 aldy505 commented May 18, 2026

Copy link
Copy Markdown

This PR

Provide AOT-compatible path for OFREP, maintains backward compatibility for users with dynamic code

Related Issues

Closes #600

Notes

Follow-up Tasks

How to test

@aldy505 aldy505 requested review from a team as code owners May 18, 2026 07:32
@github-actions github-actions Bot requested review from askpt and weyert May 18, 2026 07:33

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces Native AOT support for the OFREP provider by implementing typed evaluation methods and transitioning to source-generated JSON serialization. It also adds a dedicated AOT compatibility test project. Feedback focuses on resolving potential compilation errors related to dictionary type mismatches with the OpenFeature SDK and the use of .NET 5+ specific HttpContent methods in multi-targeted code. Additionally, there are recommendations to refactor duplicated validation and response mapping logic to improve maintainability.

Comment thread src/OpenFeature.Providers.Ofrep/Models/OfrepRequest.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs Outdated
@askpt

askpt commented May 18, 2026

Copy link
Copy Markdown
Member

@aldy505 Could you please sign-off your commits? You can follow these instructions:

  1. Ensure you have a local copy of your branch by checking out the pull request locally via command line.
  2. In your local branch, run: git rebase HEAD~4 --signoff
  3. Force push your changes to overwrite the branch: git push --force-with-lease origin feat/aot-compatibility

aldy505 added 4 commits May 19, 2026 14:52
Closes open-feature#600

Provide AOT-compatible path for OFREP, maintains backward compatibility for users with dynamic code

Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
…standard compatibility

Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
@aldy505 aldy505 force-pushed the feat/aot-compatibility branch from 74a698c to f7f84de Compare May 19, 2026 07:52

@askpt askpt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that you have a lot of "backward compatibility" in the OfrepClient. This client is not supposed to be used by the external consumers. I would encourage to remove the backwards compatibility and use only the AOT path.

Comment thread .github/workflows/ci.yml Outdated
Comment thread test/OpenFeature.Providers.Ofrep.AotCompatibility/Program.cs
Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
@aldy505 aldy505 force-pushed the feat/aot-compatibility branch from 05fd71d to 4019d56 Compare May 29, 2026 01:35
aldy505 added 2 commits May 29, 2026 08:48
Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
@aldy505

aldy505 commented May 29, 2026

Copy link
Copy Markdown
Author

@askpt Applied everything other than moving to single file app.

@askpt askpt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a couple of comments. Thanks for making the changes.

The single file can wait.

Comment thread src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/OfrepProvider.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/Client/IOfrepClient.cs Outdated
Comment thread src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs Outdated
aldy505 and others added 2 commits June 13, 2026 09:42
@aldy505 aldy505 requested a review from askpt June 18, 2026 05:41
@askpt

askpt commented Jun 21, 2026

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Native AOT compatibility to OpenFeature.Providers.Ofrep by introducing source-generated JSON serialization, refactoring OfrepClient for raw JSON handling, adding an AOT test project, and adding a CI workflow that publishes and runs the AOT build across Linux, Windows, and macOS.

Changes

OFREP AOT Compatibility

Layer / File(s) Summary
AOT serialization context and model contract
src/OpenFeature.Providers.Ofrep/Serialization/OfrepJsonSerializerContext.cs, src/OpenFeature.Providers.Ofrep/Models/OfrepRequest.cs, src/OpenFeature.Providers.Ofrep/OpenFeature.Providers.Ofrep.csproj
Introduces OfrepJsonSerializerContext as a source-generated JsonSerializerContext with camelCase/ignore-nulls options and registrations for OfrepRequest, OfrepResponse<JsonElement>, primitives, and dictionaries. Narrows OfrepRequest.Context from object? to IDictionary<string, object?>?. Sets IsAotCompatible to true for the net8.0 target.
OfrepClient AOT-safe request/response handling
src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs
Replaces JsonContent.Create with JsonSerializer.Serialize + StringContent in CreateEvaluationRequest. Adds ReadRawResponseAsync to deserialize responses as OfrepResponse<JsonElement> via OfrepJsonSerializerContext. Introduces DeserializeResponseValue<T> to convert JsonElement to supported types, refactors both bad-request and OK response paths away from ReadFromJsonAsync and JsonOptions, and updates EvaluateFlag<T> XML docs.
Provider wiring and existing test updates
src/OpenFeature.Providers.Ofrep/OfrepProvider.cs, test/OpenFeature.Providers.Ofrep.Test/Client/OfrepClientTest.cs, test/OpenFeature.Providers.Ofrep.Test/OfrepProviderTest.cs
Reformats ResolveFlag(...) call sites in OfrepProvider. Updates OfrepClientTest to use a strongly typed SampleObject with per-property assertions for the object-type evaluation test. Reformats Received(1).EvaluateFlag(...) verifications in OfrepProviderTest.
AOT compatibility test project
test/OpenFeature.Providers.Ofrep.AotCompatibility/*, DotnetSdkContrib.slnx
Adds a new net8.0 Exe project with PublishAot enabled and OpenFeature.Providers.Ofrep as TrimmerRootAssembly. Program.cs configures an OfrepProvider, builds an EvaluationContext, cancels a token immediately, invokes multiple resolution methods, shuts down the provider, and constructs a second provider from an environment variable. Registers the project in the solution and imports shared build props for the test directory.
AOT compatibility CI workflow
.github/workflows/aot-compatibility.yml
Adds a GitHub Actions workflow with a cross-platform matrix (Linux, Windows, macOS; x64 and ARM64) that checks out the repo, sets up .NET from global.json, restores/builds the solution, publishes the AOT test project for each runtime, and runs the resulting binary with OS-specific steps.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: bacherfl, toddbaert, jonathannorris

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding AOT compatibility for OFREP.
Description check ✅ Passed The description matches the PR goals and mentions AOT compatibility and backward compatibility for OFREP.
Linked Issues check ✅ Passed The changes address issue #600 by adding AOT-friendly serialization, compatibility flags, and tests/workflow support.
Out of Scope Changes check ✅ Passed The added workflow, test project, and refactors all support AOT compatibility and do not appear unrelated.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs (1)

388-423: ⚠️ Potential issue | 🔴 Critical

Non-primitive EvaluateFlag<T> values are now silently dropped.

DeserializeResponseValue<T> only supports bool/string/int/double/JsonElement; every other type returns defaultValue instead of attempting deserialization. The test EvaluateFlag_WithObjectType_ShouldReturnObjectValue demonstrates this regression—it expects object deserialization but the current implementation will return the default value, causing the assertion at line 654 (Assert.Equal(expectedValue.Name, result.Value.Name)) to fail.

Suggested fix
 private static T DeserializeResponseValue<T>(JsonElement valueElement, T defaultValue)
 {
     if (typeof(T) == typeof(JsonElement?))
     {
         JsonElement? nullableElement = valueElement;
         return (T)(object)nullableElement;
     }

-    return defaultValue;
+    // Keep AOT-safe behavior, but preserve non-AOT backward compatibility.
+#if NET8_0_OR_GREATER
+    if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported)
+    {
+        return defaultValue;
+    }
+#endif
+    var deserialized = JsonSerializer.Deserialize<T>(valueElement.GetRawText());
+    return deserialized is null ? defaultValue : deserialized;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs` around lines 388 -
423, The DeserializeResponseValue<T> method only handles specific primitive
types (bool, string, int, double, JsonElement) and silently returns the default
value for any other type, causing the
EvaluateFlag_WithObjectType_ShouldReturnObjectValue test to fail. Add a fallback
case before the final return statement that attempts to deserialize unsupported
types using JsonSerializer.Deserialize, passing the valueElement and
defaultValue appropriately to handle object deserialization instead of silently
dropping non-primitive values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/aot-compatibility.yml:
- Around line 48-52: The Checkout step using actions/checkout is currently
persisting git credentials in the local git config, which increases the risk of
token exposure in later workflow steps or artifacts. Add `persist-credentials:
false` to the `with` section of the Checkout action (after `fetch-depth` and
`submodules`) to disable credential persistence and reduce the security risk.
- Around line 74-76: The dotnet publish command in the AOT compatibility
workflow uses target framework net10.0, but the
OpenFeature.Providers.Ofrep.AotCompatibility test project targets net8.0. Change
the -f parameter value from net10.0 to net8.0 in the publish step to match the
actual target framework of the AOT compatibility test project, which will
resolve the publish failure on the AOT validation path.
- Around line 67-69: The Test AOT compatibility project build step specifies an
incorrect project path. Update the dotnet build command in the run step to point
to the correct AOT compatibility project path
test/OpenFeature.Providers.Ofrep.AotCompatibility/OpenFeature.Providers.Ofrep.AotCompatibility.csproj
instead of the current
test/OpenFeature.AotCompatibility/OpenFeature.AotCompatibility.csproj. This
ensures the build step targets the actual AOT compatibility test project that
was added.

---

Duplicate comments:
In `@src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs`:
- Around line 388-423: The DeserializeResponseValue<T> method only handles
specific primitive types (bool, string, int, double, JsonElement) and silently
returns the default value for any other type, causing the
EvaluateFlag_WithObjectType_ShouldReturnObjectValue test to fail. Add a fallback
case before the final return statement that attempts to deserialize unsupported
types using JsonSerializer.Deserialize, passing the valueElement and
defaultValue appropriately to handle object deserialization instead of silently
dropping non-primitive values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 54089c7f-bd5e-4bd8-9b82-84384e738a93

📥 Commits

Reviewing files that changed from the base of the PR and between f45da64 and a7f7081.

📒 Files selected for processing (12)
  • .github/workflows/aot-compatibility.yml
  • DotnetSdkContrib.slnx
  • src/OpenFeature.Providers.Ofrep/Client/OfrepClient.cs
  • src/OpenFeature.Providers.Ofrep/Models/OfrepRequest.cs
  • src/OpenFeature.Providers.Ofrep/OfrepProvider.cs
  • src/OpenFeature.Providers.Ofrep/OpenFeature.Providers.Ofrep.csproj
  • src/OpenFeature.Providers.Ofrep/Serialization/OfrepJsonSerializerContext.cs
  • test/OpenFeature.Providers.Ofrep.AotCompatibility/Directory.Build.props
  • test/OpenFeature.Providers.Ofrep.AotCompatibility/OpenFeature.Providers.Ofrep.AotCompatibility.csproj
  • test/OpenFeature.Providers.Ofrep.AotCompatibility/Program.cs
  • test/OpenFeature.Providers.Ofrep.Test/Client/OfrepClientTest.cs
  • test/OpenFeature.Providers.Ofrep.Test/OfrepProviderTest.cs

Comment thread .github/workflows/aot-compatibility.yml
Comment thread .github/workflows/aot-compatibility.yml Outdated
Comment thread .github/workflows/aot-compatibility.yml
aldy505 and others added 2 commits June 26, 2026 11:03
@aldy505

aldy505 commented Jun 26, 2026

Copy link
Copy Markdown
Author

@askpt anything else to help move this forward?

@askpt

askpt commented Jun 27, 2026

Copy link
Copy Markdown
Member

@askpt anything else to help move this forward?

The GH Actions are failing at the moment.

For the AOT Compatibility, from a quick look it seems it is missing a GH_TOKEN permission to access the packages in the GH Artifactory.

For the format I think it is just do dotnet format at the root of the repository and it should fix it.

…e registry

Signed-off-by: Reinaldy Rafli <github@reinaldyrafli.com>
@aldy505

aldy505 commented Jun 30, 2026

Copy link
Copy Markdown
Author

For the AOT Compatibility, from a quick look it seems it is missing a GH_TOKEN permission to access the packages in the GH Artifactory.

I'm not sure with the current solution, I only follow this guide: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry#authenticating-in-a-github-actions-workflow -- let's see how it goes.

Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.github/workflows/aot-compatibility.yml (1)

73-79: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Publish target framework still mismatched with the AOT project.

Line 77 publishes -f net9.0, but per the OpenFeature.Providers.Ofrep.AotCompatibility.csproj contract (test/OpenFeature.Providers.Ofrep.AotCompatibility/OpenFeature.Providers.Ofrep.AotCompatibility.csproj), the project's <TargetFramework> is net8.0. This is the same class of issue flagged in a prior review round (previously net10.0, now net9.0), still not aligned with the actual project TFM — the publish step will fail.

🐛 Proposed fix
           dotnet publish test/OpenFeature.Providers.Ofrep.AotCompatibility/OpenFeature.Providers.Ofrep.AotCompatibility.csproj `
-            -f net9.0 `
+            -f net8.0 `
             -r ${{ matrix.runtime }} `
             -o ./aot-output
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/aot-compatibility.yml around lines 73 - 79, The AOT
publish step is still using the wrong target framework in the workflow. Update
the `dotnet publish` command in the `Publish AOT compatibility test
(cross-platform)` step to match the
`OpenFeature.Providers.Ofrep.AotCompatibility` project’s actual
`TargetFramework` (`net8.0`) instead of `net9.0`, so the `publish` command and
the project contract stay aligned.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/workflows/aot-compatibility.yml:
- Around line 73-79: The AOT publish step is still using the wrong target
framework in the workflow. Update the `dotnet publish` command in the `Publish
AOT compatibility test (cross-platform)` step to match the
`OpenFeature.Providers.Ofrep.AotCompatibility` project’s actual
`TargetFramework` (`net8.0`) instead of `net9.0`, so the `publish` command and
the project contract stay aligned.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 88571187-53b7-4c70-bd6e-731acddaa3e6

📥 Commits

Reviewing files that changed from the base of the PR and between b44d773 and a60336d.

📒 Files selected for processing (1)
  • .github/workflows/aot-compatibility.yml

@askpt askpt force-pushed the feat/aot-compatibility branch from 5455cf3 to a60336d Compare July 3, 2026 16:52
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
@askpt

askpt commented Jul 3, 2026

Copy link
Copy Markdown
Member

For the AOT Compatibility, from a quick look it seems it is missing a GH_TOKEN permission to access the packages in the GH Artifactory.

I'm not sure with the current solution, I only follow this guide: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry#authenticating-in-a-github-actions-workflow -- let's see how it goes.

Managed to get the restore step passing but it is still failing with other errors.

@aldy505

aldy505 commented Jul 8, 2026

Copy link
Copy Markdown
Author

Hmm, this is harder than I thought. I'll revisit this tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OFREP AOT Compatibility

3 participants