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