Skip to content

Commit 75d67ac

Browse files
committed
android: rename package to org.codeshipping.llamakotlin and prepare for Maven Central (#1)
* android: rename package from com.llamakotlin.android to org.codeshipping.llamakotlin * android: update namespace and groupId in build.gradle.kts * android: add signing configuration and publish script for Maven Central * android: remove unused resources and manifest entries from library module * android: update JNI function names to match new package structure * android: add PUBLISHING.md documentation * llama.cpp: update submodule reference * sample: update to use published library dependency instead of local project reference
1 parent 01aa718 commit 75d67ac

37 files changed

Lines changed: 379 additions & 384 deletions

PUBLISHING.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Publishing to Maven Central
2+
3+
This guide explains how to publish `llama-kotlin-android` to Maven Central.
4+
5+
## Prerequisites
6+
7+
### 1. Sonatype Central Account
8+
9+
1. Go to [central.sonatype.com](https://central.sonatype.com/)
10+
2. Create an account (or sign in with GitHub)
11+
3. Register your namespace (e.g., `org.codeshipping`)
12+
4. Verify domain ownership via DNS TXT record
13+
14+
### 2. GPG Key
15+
16+
Generate a GPG key for signing artifacts:
17+
18+
```bash
19+
# Generate key
20+
gpg --full-generate-key
21+
# Choose: RSA and RSA, 4096 bits, no expiration
22+
23+
# List keys to get key ID
24+
gpg --list-secret-keys --keyid-format SHORT
25+
# Example output shows key ID like: AF5FBB39
26+
27+
# Export public key (for your records)
28+
gpg --armor --export YOUR_KEY_ID > public-key.asc
29+
30+
# Export private key (keep secure!)
31+
gpg --armor --export-secret-keys YOUR_KEY_ID > private-key.asc
32+
```
33+
34+
### 3. Upload Public Key to Keyservers
35+
36+
Sonatype needs to verify signatures using your public key:
37+
38+
```bash
39+
# Method 1: Via HTTP POST (recommended if HKP is blocked)
40+
gpg --armor --export YOUR_KEY_ID | curl -X POST --data-urlencode "keytext@-" "https://keyserver.ubuntu.com/pks/add"
41+
42+
# Method 2: Via GPG command
43+
gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID
44+
```
45+
46+
Verify upload:
47+
```bash
48+
curl "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xYOUR_KEY_ID" | head -5
49+
```
50+
51+
## Configuration
52+
53+
### ~/.gradle/gradle.properties
54+
55+
Create or edit `~/.gradle/gradle.properties`:
56+
57+
```properties
58+
# Maven Central Credentials (from central.sonatype.com → View Account → Generate User Token)
59+
mavenCentralUsername=YOUR_TOKEN_USERNAME
60+
mavenCentralPassword=YOUR_TOKEN_PASSWORD
61+
62+
# GPG Signing (key ID only - password prompted at runtime)
63+
signing.keyId=YOUR_8_CHAR_KEY_ID
64+
```
65+
66+
### GPG Private Key File
67+
68+
Store your private key (ASCII armored) at:
69+
```
70+
~/personal-workspace/Importants/gpg-maven-signing-key.asc
71+
```
72+
73+
**Keep this file secure and never commit it to version control!**
74+
75+
## Publishing
76+
77+
### Quick Publish
78+
79+
Run the publish script:
80+
81+
```bash
82+
./publish.sh
83+
```
84+
85+
This will:
86+
1. Prompt for your GPG passphrase (hidden input)
87+
2. Build release AAR
88+
3. Sign all artifacts
89+
4. Create bundle.zip
90+
5. Upload to Maven Central
91+
92+
### Manual Steps
93+
94+
If automatic upload fails:
95+
96+
1. Build and sign:
97+
```bash
98+
./gradlew clean :app:assembleRelease
99+
./gradlew :app:publishReleasePublicationToLocalRepository -Psigning.password="YOUR_PASSPHRASE"
100+
```
101+
102+
2. Create bundle:
103+
```bash
104+
cd app/build/repo && zip -r ../bundle.zip org
105+
```
106+
107+
3. Upload manually:
108+
- Go to [central.sonatype.com](https://central.sonatype.com/)
109+
- Click **Publish****Upload Bundle**
110+
- Upload `app/build/bundle.zip`
111+
112+
4. Verify and publish:
113+
- Go to [Deployments](https://central.sonatype.com/publishing/deployments)
114+
- Review validation results
115+
- Click **Publish** when ready
116+
117+
## Artifact Information
118+
119+
| Field | Value |
120+
|-------|-------|
121+
| **Group ID** | `org.codeshipping` |
122+
| **Artifact ID** | `llama-kotlin-android` |
123+
| **Version** | `0.1.0` |
124+
| **Packaging** | `aar` |
125+
126+
## Usage After Publishing
127+
128+
Users can add the dependency:
129+
130+
```kotlin
131+
// build.gradle.kts
132+
dependencies {
133+
implementation("org.codeshipping:llama-kotlin-android:0.1.0")
134+
}
135+
```
136+
137+
## Troubleshooting
138+
139+
### "Invalid signature - Could not find public key"
140+
141+
Your GPG public key isn't on keyservers yet. Upload it:
142+
143+
```bash
144+
gpg --armor --export YOUR_KEY_ID | curl -X POST --data-urlencode "keytext@-" "https://keyserver.ubuntu.com/pks/add"
145+
```
146+
147+
Wait 5-10 minutes for propagation, then retry.
148+
149+
### "Cannot perform signing task - no configured signatory"
150+
151+
1. Ensure `signing.keyId` is set in `~/.gradle/gradle.properties`
152+
2. Ensure GPG private key file exists at the configured path
153+
3. Ensure you're passing the password: `-Psigning.password="..."`
154+
155+
### Build Errors with Resources
156+
157+
This library module shouldn't have themes, icons, or string resources. The `res/` folder should be empty or removed entirely.
158+
159+
## Security Notes
160+
161+
- **Never commit** credentials or private keys to version control
162+
- Store credentials in `~/.gradle/gradle.properties` (outside project)
163+
- Store GPG private key in a secure location outside the project
164+
- GPG passphrase is prompted at runtime for security
165+
166+
## Links
167+
168+
- [Maven Central Portal](https://central.sonatype.com/)
169+
- [Publishing Guide](https://central.sonatype.org/publish/)
170+
- [Keyserver Status](https://keyserver.ubuntu.com/)

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ A Kotlin-first Android library for running LLaMA models on-device using [llama.c
3939

4040
```kotlin
4141
dependencies {
42-
implementation("io.github.it5prasoon:llama-kotlin-android:0.1.0")
42+
implementation("org.codeshipping:llama-kotlin-android:0.1.0")
4343
}
4444
```
4545

@@ -57,7 +57,7 @@ Recommended models for Android:
5757
### 3. Basic Usage
5858

5959
```kotlin
60-
import com.llamakotlin.android.LlamaModel
60+
import org.codeshipping.llamakotlin.LlamaModel
6161

6262
class MyActivity : AppCompatActivity() {
6363
private var model: LlamaModel? = null
@@ -301,7 +301,7 @@ llama-kotlin-android/
301301
│ │ │ ├── llama.cpp/ # llama.cpp submodule
302302
│ │ │ ├── llama_jni.cpp # JNI bridge
303303
│ │ │ └── llama_context_wrapper.cpp
304-
│ │ └── java/com/llamakotlin/
304+
│ │ └── java/org/codeshipping/llamakotlin/
305305
│ │ ├── LlamaModel.kt # Main API
306306
│ │ ├── LlamaConfig.kt # Configuration
307307
│ │ └── exception/ # Exceptions

app/build.gradle.kts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ plugins {
22
id("com.android.library")
33
id("org.jetbrains.kotlin.android")
44
id("maven-publish")
5+
id("signing")
56
}
67

78
android {
8-
namespace = "com.llamakotlin.android"
9+
namespace = "org.codeshipping.llamakotlin"
910
compileSdk = 36
1011

1112
ndkVersion = "27.3.13750724"
@@ -87,7 +88,7 @@ dependencies {
8788
publishing {
8889
publications {
8990
register<MavenPublication>("release") {
90-
groupId = "io.github.it5prasoon"
91+
groupId = "org.codeshipping"
9192
artifactId = "llama-kotlin-android"
9293
version = "0.1.0"
9394

@@ -98,7 +99,7 @@ publishing {
9899
pom {
99100
name.set("LLaMA Kotlin Android")
100101
description.set("A Kotlin-first Android library for running LLaMA models on-device using llama.cpp")
101-
url.set("https://github.com/it5prasoon/llama-kotlin-android")
102+
url.set("https://github.com/codeshipping/llama-kotlin-android")
102103

103104
licenses {
104105
license {
@@ -110,17 +111,39 @@ publishing {
110111
developers {
111112
developer {
112113
id.set("it5prasoon")
113-
name.set("Prasoon")
114+
name.set("Prasoon Kumar")
114115
email.set("prasoonk187@gmail.com")
115116
}
116117
}
117118

118119
scm {
119-
connection.set("scm:git:git://github.com/it5prasoon/llama-kotlin-android.git")
120-
developerConnection.set("scm:git:ssh://github.com/it5prasoon/llama-kotlin-android.git")
121-
url.set("https://github.com/it5prasoon/llama-kotlin-android")
120+
connection.set("scm:git:git://github.com/codeshipping/llama-kotlin-android.git")
121+
developerConnection.set("scm:git:ssh://github.com/codeshipping/llama-kotlin-android.git")
122+
url.set("https://github.com/codeshipping/llama-kotlin-android")
122123
}
123124
}
124125
}
125126
}
127+
128+
repositories {
129+
maven {
130+
name = "local"
131+
url = uri(layout.buildDirectory.dir("repo"))
132+
}
133+
}
134+
}
135+
136+
signing {
137+
val signingKeyId = findProperty("signing.keyId") as String?
138+
val signingPassword = findProperty("signing.password") as String?
139+
val signingKeyFile = file(System.getProperty("user.home") + "/personal-workspace/Importants/gpg-maven-signing-key.asc")
140+
141+
if (signingKeyFile.exists()) {
142+
useInMemoryPgpKeys(
143+
signingKeyId,
144+
signingKeyFile.readText(),
145+
signingPassword
146+
)
147+
sign(publishing.publications["release"])
148+
}
126149
}

app/consumer-rules.pro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
}
77

88
# Keep the main API classes
9-
-keep class com.llamakotlin.android.LlamaModel { *; }
10-
-keep class com.llamakotlin.android.LlamaConfig { *; }
11-
-keep class com.llamakotlin.android.LlamaNative { *; }
9+
-keep class org.codeshipping.llamakotlin.LlamaModel { *; }
10+
-keep class org.codeshipping.llamakotlin.LlamaConfig { *; }
11+
-keep class org.codeshipping.llamakotlin.LlamaNative { *; }
1212

1313
# Keep exception classes
14-
-keep class com.llamakotlin.android.exception.** { *; }
14+
-keep class org.codeshipping.llamakotlin.exception.** { *; }
1515

1616
# Keep callback interfaces
17-
-keep interface com.llamakotlin.android.** { *; }
17+
-keep interface org.codeshipping.llamakotlin.** { *; }

app/src/androidTest/java/com/llamakotlin/android/ExampleInstrumentedTest.kt renamed to app/src/androidTest/java/org/codeshipping/llamakotlin/ExampleInstrumentedTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.llamakotlin.android
1+
package org.codeshipping.llamakotlin
22

33
import androidx.test.platform.app.InstrumentationRegistry
44
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
1919
fun useAppContext() {
2020
// Context of the app under test.
2121
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22-
assertEquals("com.llamakotlin.android", appContext.packageName)
22+
assertEquals("org.codeshipping.llamakotlin", appContext.packageName)
2323
}
2424
}

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:tools="http://schemas.android.com/tools">
4-
5-
<application
6-
android:allowBackup="true"
7-
android:dataExtractionRules="@xml/data_extraction_rules"
8-
android:fullBackupContent="@xml/backup_rules"
9-
android:icon="@mipmap/ic_launcher"
10-
android:label="@string/app_name"
11-
android:roundIcon="@mipmap/ic_launcher_round"
12-
android:supportsRtl="true"
13-
android:theme="@style/Theme.Llamakotlinandroid" />
14-
15-
</manifest>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
<!-- Library manifest - no application tag needed -->
4+
</manifest>

app/src/main/cpp/llama.cpp

Submodule llama.cpp updated 474 files

0 commit comments

Comments
 (0)