From 9fcde9d5cee487782d8e9cf3914a032e99ffb8d6 Mon Sep 17 00:00:00 2001 From: bojancrevar Date: Mon, 23 Feb 2026 09:41:36 +0100 Subject: [PATCH] C# CI --- .github/workflows/uniffi.yaml | 56 ++++++++++++++++++ bindings/uniffi/.gitignore | 2 + .../csharp/GoRules/ZenEngine/JsonBuffer.cs | 23 ++++++++ .../uniffi/nuget/GoRules.ZenEngine.csproj | 58 +++++++++++++++++++ .../uniffi/scripts/fix-csharp-bindings.sh | 38 ++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs create mode 100644 bindings/uniffi/nuget/GoRules.ZenEngine.csproj create mode 100755 bindings/uniffi/scripts/fix-csharp-bindings.sh diff --git a/.github/workflows/uniffi.yaml b/.github/workflows/uniffi.yaml index b4193941..fa231c2b 100644 --- a/.github/workflows/uniffi.yaml +++ b/.github/workflows/uniffi.yaml @@ -137,6 +137,62 @@ jobs: run: ./gradlew publishMavenKotlinPublicationToCentralPortal publishMavenJavaPublicationToCentralPortal + release-csharp: + runs-on: ubuntu-latest + needs: [ build ] + if: "startsWith(github.event.head_commit.message, 'chore(release): publish uniffi')" + defaults: + run: + working-directory: ${{ env.UNIFFI_DIRECTORY }} + + steps: + - uses: actions/checkout@v3 + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Setup Rust Toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: build/generated/resources + + - name: Move artifacts + run: mv ../../build ./ + + - name: Install uniffi-bindgen-cs + run: cargo install uniffi-bindgen-cs --git https://github.com/aspect-build/uniffi-bindgen-cs --tag v0.10.0+v0.29.4 + + - name: Generate C# bindings + run: | + uniffi-bindgen-cs \ + --library build/generated/resources/darwin-x86-64/libzen_uniffi.dylib \ + --out-dir build/generated/csharp + + - name: Fix async callback interfaces + run: bash scripts/fix-csharp-bindings.sh build/generated/csharp/zen_uniffi.cs + + - name: Extract version from Cargo.toml + id: version + run: | + VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Detected version: $VERSION" + + - name: Pack NuGet package + run: dotnet pack nuget/GoRules.ZenEngine.csproj -c Release -p:Version=$VERSION + + - name: Push to NuGet.org + run: | + dotnet nuget push nuget/bin/Release/*.nupkg \ + --api-key ${{ secrets.NUGET_API_KEY }} \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate + build-ios: if: "!contains(github.event.head_commit.message, 'skip ci')" env: diff --git a/bindings/uniffi/.gitignore b/bindings/uniffi/.gitignore index 6eb8b6a7..dd20902a 100644 --- a/bindings/uniffi/.gitignore +++ b/bindings/uniffi/.gitignore @@ -1,3 +1,5 @@ .idea .gradle build/ +build-android/ +jniLibs/ \ No newline at end of file diff --git a/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs b/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs new file mode 100644 index 00000000..d63fc8d6 --- /dev/null +++ b/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs @@ -0,0 +1,23 @@ +namespace GoRules.ZenEngine; + +using System.Text; + +public class JsonBuffer +{ + public byte[] Value { get; } + + public JsonBuffer(byte[] value) + { + Value = value; + } + + public JsonBuffer(string json) + { + Value = Encoding.UTF8.GetBytes(json); + } + + public override string ToString() + { + return Encoding.UTF8.GetString(Value); + } +} diff --git a/bindings/uniffi/nuget/GoRules.ZenEngine.csproj b/bindings/uniffi/nuget/GoRules.ZenEngine.csproj new file mode 100644 index 00000000..3c9b0d27 --- /dev/null +++ b/bindings/uniffi/nuget/GoRules.ZenEngine.csproj @@ -0,0 +1,58 @@ + + + + net8.0 + GoRules.ZenEngine + GoRules + ZEN Engine - Business Rules Engine for .NET. Execute JSON Decision Models (JDM) with native performance via Rust FFI bindings. + MIT + https://github.com/gorules/zen + https://github.com/gorules/zen + rules-engine;business-rules;decision-engine;jdm;gorules + enable + enable + true + true + $(NoWarn);CS1591 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bindings/uniffi/scripts/fix-csharp-bindings.sh b/bindings/uniffi/scripts/fix-csharp-bindings.sh new file mode 100755 index 00000000..fd164418 --- /dev/null +++ b/bindings/uniffi/scripts/fix-csharp-bindings.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# +# fix-csharp-bindings.sh +# +# Fixes the async callback interface bug in C# bindings generated by uniffi-bindgen-cs. +# +# The generator produces sync interface methods (returning T directly) but the +# calling code uses await + .WaitAsync(), causing compilation errors. This script +# patches the interface method signatures to return Task instead. +# +# Usage: ./fix-csharp-bindings.sh + +set -euo pipefail + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +FILE="$1" + +if [ ! -f "$FILE" ]; then + echo "Error: File not found: $FILE" + exit 1 +fi + +echo "Fixing async callback interfaces in $FILE..." + +# Fix ZenCustomNodeCallback.Handle: sync → async (Task<>) +sed -i.bak 's/ZenEngineHandlerResponse Handle(ZenEngineHandlerRequest @key)/Task Handle(ZenEngineHandlerRequest @key)/' "$FILE" + +# Fix ZenDecisionLoaderCallback.Load: sync → async (Task<>) +sed -i.bak 's/JsonBuffer? Load(string @key)/Task Load(string @key)/' "$FILE" + +# Clean up backup file +rm -f "${FILE}.bak" + +echo "Done. Fixed async interfaces in $FILE"