@ondeinference / onde / commits / 1ac6122

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