Skip to content

Commit 69114d2

Browse files
authored
feat(bindings/dotnet):Bindings dotnet publish to nuget (#7323)
* feat(dotnet): Update project settings and add release workflow for DotOpenDAL * fix(dotnet): Update OSX target architecture from x86_64 to arm64 * fix(dotnet): Update AsyncState to include Context property and improve cancellation handling
1 parent 993b00e commit 69114d2

File tree

5 files changed

+208
-21
lines changed

5 files changed

+208
-21
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
name: Release Dotnet Binding
19+
20+
on:
21+
push:
22+
tags:
23+
- 'dotnet-v[0-9]+.[0-9]+.[0-9]+*'
24+
pull_request:
25+
branches:
26+
- main
27+
paths:
28+
- ".github/workflows/release_dotnet.yml"
29+
- "bindings/dotnet/build.py"
30+
- "bindings/dotnet/DotOpenDAL/DotOpenDAL.csproj"
31+
workflow_dispatch:
32+
inputs:
33+
dotnet_publish:
34+
description: "Publish DotOpenDAL to nuget.org"
35+
required: true
36+
type: boolean
37+
default: false
38+
39+
concurrency:
40+
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
41+
cancel-in-progress: true
42+
43+
permissions:
44+
contents: read
45+
46+
jobs:
47+
build-native:
48+
name: Build Native - ${{ matrix.classifier }}
49+
runs-on: ${{ matrix.os }}
50+
defaults:
51+
run:
52+
working-directory: "bindings/dotnet"
53+
strategy:
54+
fail-fast: false
55+
matrix:
56+
include:
57+
- os: ubuntu-latest
58+
classifier: linux-x86_64
59+
artifact: libopendal_dotnet.so
60+
- os: windows-latest
61+
classifier: windows-x86_64
62+
artifact: opendal_dotnet.dll
63+
- os: macos-latest
64+
classifier: osx-aarch_64
65+
artifact: libopendal_dotnet.dylib
66+
67+
steps:
68+
- uses: actions/checkout@v6
69+
- name: Setup Python
70+
uses: actions/setup-python@v6
71+
with:
72+
python-version: "3.11"
73+
- name: Setup Rust toolchain
74+
uses: ./.github/actions/setup
75+
with:
76+
need-protoc: true
77+
need-rocksdb: true
78+
github-token: ${{ secrets.GITHUB_TOKEN }}
79+
80+
- name: Build native library
81+
run: python build.py --classifier ${{ matrix.classifier }}
82+
83+
- name: Upload native artifact
84+
uses: actions/upload-artifact@v6
85+
with:
86+
name: native-${{ matrix.classifier }}
87+
path: bindings/dotnet/target/native/${{ matrix.classifier }}/${{ matrix.artifact }}
88+
if-no-files-found: error
89+
90+
package:
91+
name: Pack NuGet package
92+
runs-on: ubuntu-latest
93+
needs:
94+
- build-native
95+
defaults:
96+
run:
97+
working-directory: "bindings/dotnet"
98+
99+
steps:
100+
- uses: actions/checkout@v6
101+
- name: Setup dotnet toolchain
102+
uses: actions/setup-dotnet@v5
103+
with:
104+
dotnet-version: "10.0.x"
105+
106+
- name: Download native artifacts
107+
uses: actions/download-artifact@v7
108+
with:
109+
pattern: native-*
110+
merge-multiple: true
111+
path: bindings/dotnet/target/release-assets
112+
113+
- name: Prepare runtime assets
114+
shell: bash
115+
run: |
116+
mkdir -p DotOpenDAL/runtimes/win-x64/native
117+
mkdir -p DotOpenDAL/runtimes/linux-x64/native
118+
mkdir -p DotOpenDAL/runtimes/osx-arm64/native
119+
120+
cp target/release-assets/opendal_dotnet.dll DotOpenDAL/runtimes/win-x64/native/
121+
cp target/release-assets/libopendal_dotnet.so DotOpenDAL/runtimes/linux-x64/native/
122+
cp target/release-assets/libopendal_dotnet.dylib DotOpenDAL/runtimes/osx-arm64/native/
123+
124+
- name: Pack DotOpenDAL
125+
run: dotnet pack DotOpenDAL/DotOpenDAL.csproj -c Release -o artifacts/package
126+
127+
- name: Upload NuGet package
128+
uses: actions/upload-artifact@v6
129+
with:
130+
name: dotnet-package
131+
path: bindings/dotnet/artifacts/package/*.nupkg
132+
if-no-files-found: error
133+
134+
publish:
135+
name: Publish
136+
if: ${{ startsWith(github.ref, 'refs/tags/dotnet-v') || (github.event_name == 'workflow_dispatch' && inputs.dotnet_publish) }}
137+
runs-on: ubuntu-latest
138+
needs:
139+
- package
140+
permissions:
141+
contents: read
142+
id-token: write
143+
environment: production
144+
145+
steps:
146+
- name: Setup dotnet toolchain
147+
uses: actions/setup-dotnet@v5
148+
with:
149+
dotnet-version: "10.0.x"
150+
151+
- name: Download NuGet package
152+
uses: actions/download-artifact@v7
153+
with:
154+
name: dotnet-package
155+
path: bindings/dotnet/artifacts/package
156+
157+
- name: NuGet login
158+
uses: NuGet/login@v1
159+
id: login
160+
with:
161+
user: Apache.OpenDAL
162+
163+
- name: Publish package
164+
run: dotnet nuget push bindings/dotnet/artifacts/package/*.nupkg --api-key "${{ steps.login.outputs.NUGET_API_KEY }}" --source https://api.nuget.org/v3/index.json --skip-duplicate

bindings/dotnet/DotOpenDAL.Tests/DotOpenDAL.Tests.csproj

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,7 @@
1313
<ItemGroup>
1414
<ProjectReference Include="../DotOpenDAL/DotOpenDAL.csproj" />
1515
</ItemGroup>
16-
<ItemGroup>
17-
<!-- Linux/macOS -->
18-
<None Include="../target/debug/libopendal_dotnet.*"
19-
Condition="'$(OS)' != 'Windows_NT'">
20-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
21-
</None>
2216

23-
<!-- Windows -->
24-
<None Include="../target/debug/opendal_dotnet.dll"
25-
Condition="'$(OS)' == 'Windows_NT'">
26-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
27-
</None>
28-
</ItemGroup>
2917
<ItemGroup>
3018
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
3119
<PackageReference Include="xunit.v3" Version="3.2.0" />
@@ -39,4 +27,4 @@
3927
</PackageReference>
4028
</ItemGroup>
4129

42-
</Project>
30+
</Project>

bindings/dotnet/DotOpenDAL/AsyncState.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public static long Register<T>(out AsyncState<T> state)
4141

4242
if (AsyncStates.TryAdd(id, state))
4343
{
44+
state.Context = id;
4445
return id;
4546
}
4647
}
@@ -66,6 +67,8 @@ public static bool TryTake<TState>(long context, [NotNullWhen(true)] out TState?
6667

6768
public sealed class AsyncState<T>
6869
{
70+
internal long Context { get; set; }
71+
6972
public TaskCompletionSource<T> Completion { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously);
7073

7174
public CancellationTokenRegistration CancellationRegistration { get; private set; }
@@ -77,10 +80,24 @@ public void BindCancellation(CancellationToken cancellationToken)
7780
return;
7881
}
7982

80-
CancellationRegistration = cancellationToken.Register(static value =>
83+
var registration = cancellationToken.Register(static value =>
8184
{
8285
var current = (AsyncState<T>)value!;
86+
AsyncStateRegistry.Unregister(current.Context);
8387
current.Completion.TrySetCanceled();
8488
}, this);
89+
90+
if (Completion.Task.IsCompleted)
91+
{
92+
registration.Dispose();
93+
return;
94+
}
95+
96+
CancellationRegistration = registration;
97+
98+
if (Completion.Task.IsCompleted)
99+
{
100+
CancellationRegistration.Dispose();
101+
}
85102
}
86103
}

bindings/dotnet/DotOpenDAL/DotOpenDAL.csproj

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,39 @@
1818
</PropertyGroup>
1919

2020
<ItemGroup>
21-
<!-- Linux/macOS -->
22-
<None Include="../target/debug/libopendal_dotnet.*"
21+
<None Include="runtimes\win-x64\native\opendal_dotnet.dll"
22+
Pack="true"
23+
PackagePath="runtimes/win-x64/native/" />
24+
<None Include="runtimes\linux-x64\native\libopendal_dotnet.so"
25+
Pack="true"
26+
PackagePath="runtimes/linux-x64/native/" />
27+
<None Include="runtimes\osx-arm64\native\libopendal_dotnet.dylib"
28+
Pack="true"
29+
PackagePath="runtimes/osx-arm64/native/" />
30+
</ItemGroup>
31+
32+
<!-- Resolve Rust build output path -->
33+
<PropertyGroup>
34+
<RustTargetDir>../target</RustTargetDir>
35+
<NativeOutputDir Condition="'$(Configuration)' == 'Debug'">$(RustTargetDir)/debug</NativeOutputDir>
36+
<NativeOutputDir Condition="'$(Configuration)' == 'Release'">$(RustTargetDir)/release</NativeOutputDir>
37+
</PropertyGroup>
38+
39+
<!-- Copy native libs for local run -->
40+
<ItemGroup Condition="Exists('$(NativeOutputDir)')">
41+
42+
<!-- Unix (Linux + macOS) -->
43+
<None Include="$(NativeOutputDir)/libopendal_dotnet.*"
2344
Condition="'$(OS)' != 'Windows_NT'">
2445
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2546
</None>
2647

2748
<!-- Windows -->
28-
<None Include="../target/debug/opendal_dotnet.dll"
49+
<None Include="$(NativeOutputDir)/opendal_dotnet.dll"
2950
Condition="'$(OS)' == 'Windows_NT'">
3051
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
3152
</None>
53+
3254
</ItemGroup>
3355

3456
</Project>

bindings/dotnet/build.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
def classifier_to_target(classifier: str) -> str:
2828
if classifier == "osx-aarch_64":
2929
return "aarch64-apple-darwin"
30-
if classifier == "osx-x86_64":
31-
return "x86_64-apple-darwin"
3230
if classifier == "linux-x86_64":
3331
return "x86_64-unknown-linux-gnu"
3432
if classifier == "windows-x86_64":
@@ -39,8 +37,6 @@ def classifier_to_target(classifier: str) -> str:
3937
def get_cargo_artifact_name(classifier: str) -> str:
4038
if classifier == "osx-aarch_64":
4139
return "libopendal_dotnet.dylib"
42-
if classifier == "osx-x86_64":
43-
return "libopendal_dotnet.dylib"
4440
if classifier == "linux-x86_64":
4541
return "libopendal_dotnet.so"
4642
if classifier == "windows-x86_64":

0 commit comments

Comments
 (0)