Update release-sdk-kotlin.yml for KMP: macOS runner, JVM build, NDK 29, fix paths
keypair34 committed
Apr 26, 2026 at 19:49 UTC
1ac6122630cdd28ae7169452ce89ef601db1b468
1 file changed
+116
-81
.github/workflows/release-sdk-kotlin.yml
+116
-81
@@ -1,56 +1,54 @@
1
-name: Release Kotlin SDK to Maven Central
1
+name: Release SDK Kotlin (Maven Central)
2
3
on:
4
push:
5
tags:
6
- - '[0-9]+.[0-9]+.[0-9]+'
6
+ - "[0-9]+.[0-9]+.[0-9]+"
7
workflow_dispatch:
8
- inputs:
9
- version:
10
- description: 'Version to publish (e.g. 0.1.3)'
11
- required: true
12
- type: string
8
+
9
+permissions:
10
+ contents: write
11
12
jobs:
13
publish:
16
- name: Build and publish AAR to Maven Central
17
- runs-on: ubuntu-latest
14
+ name: Build and publish KMP library to Maven Central
15
+ runs-on: macos-15
16
19
- steps:
20
- - name: Checkout repository
21
- uses: actions/checkout@v4
17
+ env:
18
+ GRESIQ_API_KEY_DEV: ${{ secrets.GRESIQ_API_KEY_DEV }}
19
+ GRESIQ_API_SECRET_DEV: ${{ secrets.GRESIQ_API_SECRET_DEV }}
20
+ GRESIQ_API_KEY_PRODUCTION: ${{ secrets.GRESIQ_API_KEY_PRODUCTION }}
21
+ GRESIQ_API_SECRET_PRODUCTION: ${{ secrets.GRESIQ_API_SECRET_PRODUCTION }}
22
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
23
23
- - name: Resolve version
24
- id: version
25
- run: |
26
- if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
27
- VERSION="${{ inputs.version }}"
28
- else
29
- VERSION="${GITHUB_REF_NAME}"
30
- fi
31
- echo "version=$VERSION" >> "$GITHUB_OUTPUT"
32
- echo "Publishing version: $VERSION"
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v6
27
28
+ # ── Java ──────────────────────────────────────────────────────────────────
29
- name: Set up JDK 17
30
uses: actions/setup-java@v4
31
with:
37
- java-version: '17'
38
- distribution: 'temurin'
32
+ java-version: "17"
33
+ distribution: temurin
34
35
+ # ── Gradle ───────────────────────────────────────────────────────────────
36
- name: Set up Gradle
37
uses: gradle/actions/setup-gradle@v3
38
with:
39
gradle-version: wrapper
40
build-root-directory: sdk/kotlin
41
46
- - name: Install Rust stable toolchain
42
+ # ── Rust ──────────────────────────────────────────────────────────────────
43
+ - name: Install stable Rust toolchain
44
uses: dtolnay/rust-toolchain@stable
45
with:
46
targets: >-
47
aarch64-linux-android,
48
armv7-linux-androideabi,
49
x86_64-linux-android,
53
- i686-linux-android
50
+ i686-linux-android,
51
+ aarch64-apple-darwin
52
53
- name: Cache Rust build artifacts
54
uses: actions/cache@v4
@@ -59,35 +57,38 @@ jobs:
57
~/.cargo/registry
58
~/.cargo/git
59
target/
62
- key: rust-android-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'src/**/*.rs') }}
63
- restore-keys: rust-android-
64
-
65
- - name: Cache NDK
66
- uses: actions/cache@v4
67
- id: ndk-cache
68
- with:
69
- path: ${{ runner.tool_cache }}/ndk
70
- key: ndk-26.1.10909125
60
+ key: rust-kotlin-sdk-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'src/**/*.rs') }}
61
+ restore-keys: rust-kotlin-sdk-
62
72
- - name: Install Android NDK
73
- if: steps.ndk-cache.outputs.cache-hit != 'true'
63
+ # ── Android NDK ───────────────────────────────────────────────────────────
64
+ - name: Install Android NDK 29
65
run: |
75
- ANDROID_SDK_ROOT="$ANDROID_SDK_ROOT"
66
echo "y" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager \
77
- "ndk;26.1.10909125"
78
-
79
- - name: Set ANDROID_NDK_HOME
80
- run: |
81
- echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/26.1.10909125" >> "$GITHUB_ENV"
67
+ "ndk;29.0.13113456" || true
68
+ # Fall back to whatever 29.x is already installed
69
+ NDK_PATH=$(ls -d $ANDROID_SDK_ROOT/ndk/29.* 2>/dev/null | sort -V | tail -1)
70
+ if [ -z "$NDK_PATH" ]; then
71
+ echo "Error: No NDK 29.x found"
72
+ exit 1
73
+ fi
74
+ echo "ANDROID_NDK_HOME=$NDK_PATH" >> "$GITHUB_ENV"
75
+ echo "Using NDK: $NDK_PATH"
76
77
- name: Install cargo-ndk
78
run: cargo install cargo-ndk --locked
79
86
- - name: Build Rust .so files for all Android ABIs
80
+ # ── Native builds ─────────────────────────────────────────────────────────
81
+ - name: Build Android .so files (all 4 ABIs)
82
run: |
83
chmod +x sdk/kotlin/scripts/build-android.sh
89
- sdk/kotlin/scripts/build-android.sh --release
84
+ sdk/kotlin/scripts/build-android.sh
85
+
86
+ - name: Build JVM native library (macOS Apple Silicon)
87
+ run: |
88
+ chmod +x sdk/kotlin/scripts/build-jvm.sh
89
+ sdk/kotlin/scripts/build-jvm.sh
90
91
+ # ── UniFFI bindings ───────────────────────────────────────────────────────
92
- name: Build uniffi-bindgen
93
run: cargo build --manifest-path uniffi-bindgen/Cargo.toml --release
94
@@ -96,77 +97,111 @@ jobs:
97
chmod +x sdk/kotlin/scripts/generate-bindings.sh
98
sdk/kotlin/scripts/generate-bindings.sh
99
99
- - name: Verify generated bindings exist
100
+ # ── Verify ────────────────────────────────────────────────────────────────
101
+ - name: Verify build inputs
102
run: |
101
- ls -lh sdk/kotlin/lib/src/generated/kotlin/
102
- echo "JNI libs:"
103
- find sdk/kotlin/lib/src/main/jniLibs -name "*.so" | sort
103
+ echo "=== Android JNI libs ==="
104
+ find sdk/kotlin/lib/src/androidMain/jniLibs -name "*.so" | sort
105
105
- - name: Validate version matches Cargo.toml
106
+ echo "=== JVM native libs ==="
107
+ find sdk/kotlin/lib/src/jvmMain/resources/native -type f | sort
108
+
109
+ echo "=== UniFFI bindings ==="
110
+ ls -lh sdk/kotlin/lib/src/generated/kotlin/uniffi/onde/
111
+
112
+ # ── Version validation ────────────────────────────────────────────────────
113
+ - name: Validate tag matches Cargo.toml version
114
+ if: startsWith(github.ref, 'refs/tags/')
115
run: |
107
- CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
108
- TAG_VERSION="${{ steps.version.outputs.version }}"
109
- echo "Cargo.toml version: $CARGO_VERSION"
110
- echo "Tag/input version: $TAG_VERSION"
111
- if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
112
- echo "Error: version mismatch — bump Cargo.toml before tagging."
116
+ TAG="${GITHUB_REF#refs/tags/}"
117
+ CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/version = "//;s/"//')
118
+ GRADLE_VERSION=$(grep '^VERSION_NAME' sdk/kotlin/gradle.properties | sed 's/VERSION_NAME=//')
119
+ echo "Tag: $TAG"
120
+ echo "Cargo.toml: $CARGO_VERSION"
121
+ echo "gradle.properties: $GRADLE_VERSION"
122
+ if [ "$TAG" != "$CARGO_VERSION" ]; then
123
+ echo "::error::Tag '$TAG' does not match Cargo.toml version '$CARGO_VERSION'."
124
+ exit 1
125
+ fi
126
+ if [ "$TAG" != "$GRADLE_VERSION" ]; then
127
+ echo "::error::Tag '$TAG' does not match gradle.properties VERSION_NAME '$GRADLE_VERSION'."
128
exit 1
129
fi
130
116
- - name: Update VERSION_NAME in gradle.properties
117
- run: |
118
- sed -i "s/^VERSION_NAME=.*/VERSION_NAME=${{ steps.version.outputs.version }}/" \
119
- sdk/kotlin/gradle.properties
131
+ # ── Publish ───────────────────────────────────────────────────────────────
132
+ - name: Dry-run publish (always)
133
+ working-directory: sdk/kotlin
134
+ run: ./gradlew :lib:publishToMavenCentral --dry-run --no-configuration-cache
135
121
- - name: Publish AAR to Maven Central
136
+ - name: Publish and release to Maven Central (tag push only)
137
+ if: startsWith(github.ref, 'refs/tags/')
138
working-directory: sdk/kotlin
139
env:
140
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
141
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
126
- ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
127
- ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
128
- ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
142
+ ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
143
+ ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
144
+ ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
145
run: ./gradlew :lib:publishAndReleaseToMavenCentral --no-configuration-cache
146
131
- - name: Collect AAR artifact
147
+ # ── Artifacts ────────────────────────────────────────────────────────────
148
+ - name: Collect build outputs
149
run: |
133
- find sdk/kotlin/lib/build/outputs/aar -name "*.aar" | sort
150
mkdir -p dist/kotlin
135
- cp sdk/kotlin/lib/build/outputs/aar/*.aar dist/kotlin/
151
+ find sdk/kotlin/lib/build/outputs/aar -name "*.aar" -exec cp {} dist/kotlin/ \;
152
+ find sdk/kotlin/lib/build/libs -name "*.jar" -exec cp {} dist/kotlin/ \;
153
137
- - name: Upload AAR as workflow artifact
154
+ - name: Upload build outputs as workflow artifact
155
uses: actions/upload-artifact@v4
156
with:
140
- name: onde-inference-${{ steps.version.outputs.version }}.aar
141
- path: dist/kotlin/*.aar
157
+ name: onde-inference-kotlin-${{ github.ref_name }}
158
+ path: dist/kotlin/
159
retention-days: 90
160
161
+ # ── GitHub Release ────────────────────────────────────────────────────────
162
- name: Create GitHub Release
145
- if: github.event_name == 'push'
163
+ if: startsWith(github.ref, 'refs/tags/')
164
uses: softprops/action-gh-release@v2
165
with:
166
tag_name: ${{ github.ref_name }}
149
- name: Kotlin SDK ${{ steps.version.outputs.version }}
167
+ name: Kotlin SDK ${{ github.ref_name }}
168
body: |
151
- ## Onde Inference Kotlin SDK ${{ steps.version.outputs.version }}
169
+ ## Onde Inference Kotlin SDK ${{ github.ref_name }}
170
+
171
+ On-device LLM inference for **Android** and **JVM (macOS Apple Silicon)**.
172
153
- ### Maven Central
173
+ ### Add to your project
174
175
```kotlin
176
// build.gradle.kts
177
dependencies {
158
- implementation("com.ondeinference:onde-inference:${{ steps.version.outputs.version }}")
178
+ implementation("com.ondeinference:onde-inference:${{ github.ref_name }}")
179
}
180
```
181
182
### What's included
183
164
- - Rust inference engine compiled for: `arm64-v8a`, `armeabi-v7a`, `x86_64`, `x86`
165
- - UniFFI-generated Kotlin bindings
166
- - Coroutine-first public API (`OndeInference`)
167
- - Flow-based token streaming
184
+ | Target | Backend | Default model |
185
+ |--------|---------|---------------|
186
+ | Android (`arm64-v8a`, `armeabi-v7a`, `x86_64`, `x86`) | CPU (Candle) | Qwen 2.5 1.5B (~941 MB) |
187
+ | JVM (macOS Apple Silicon) | Metal | Qwen 2.5 3B (~1.93 GB) |
188
+
189
+ ### Usage
190
+
191
+ ```kotlin
192
+ // Android
193
+ val onde = OndeInference(applicationContext)
194
+
195
+ // JVM (macOS)
196
+ val onde = OndeInference()
197
+
198
+ // Shared API
199
+ val elapsed = onde.loadDefaultModel(systemPrompt = "You are helpful.")
200
+ val result = onde.chat("Hello!")
201
+ onde.stream("Tell me a story.").collect { chunk -> print(chunk.delta) }
202
+ ```
203
169
- See the [README](https://github.com/ondeinference/onde/tree/main/sdk/kotlin/README.md) for full usage docs.
170
- files: dist/kotlin/*.aar
204
+ See the [README](https://github.com/ondeinference/onde/tree/main/sdk/kotlin/README.md) for full API docs.
205
+ files: dist/kotlin/*
206
draft: false
207
prerelease: false