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