|
| 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/) |
0 commit comments