|
| 1 | +# Publishing Guide |
| 2 | + |
| 3 | +This document describes how to publish the Permit.io Java SDK to Maven Central and GitHub Packages. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The SDK is published to two repositories: |
| 8 | + |
| 9 | +- **Maven Central** - Primary distribution for public consumption |
| 10 | +- **GitHub Packages** - Secondary distribution for GitHub-based workflows |
| 11 | + |
| 12 | +## Prerequisites |
| 13 | + |
| 14 | +### Maven Central Portal Account |
| 15 | + |
| 16 | +1. Create an account at [central.sonatype.com](https://central.sonatype.com) |
| 17 | +2. Verify ownership of the `io.permit` namespace |
| 18 | +3. Generate a User Token: Account → Generate User Token |
| 19 | + |
| 20 | +### GPG Signing Key |
| 21 | + |
| 22 | +Maven Central requires all artifacts to be signed with GPG. |
| 23 | +[For more info see here.](https://central.sonatype.org/publish/requirements/gpg/) |
| 24 | + |
| 25 | +#### Generate a new key (if you don't have one) |
| 26 | + |
| 27 | +```bash |
| 28 | +gpg --full-generate-key |
| 29 | +``` |
| 30 | + |
| 31 | +When prompted: |
| 32 | + |
| 33 | +1. **Key type**: Select `1` (RSA and RSA) |
| 34 | +2. **Key size**: Enter `4096` |
| 35 | +3. **Expiration**: Enter `0` (doesn't expire) or set a reasonable expiration |
| 36 | +4. **Name and email**: Use the same email as your Maven Central account |
| 37 | +5. **Passphrase**: Set a strong passphrase (this is your `signingInMemoryKeyPassword`) |
| 38 | + |
| 39 | +#### List your keys |
| 40 | + |
| 41 | +```bash |
| 42 | +gpg --list-secret-keys --keyid-format LONG |
| 43 | +``` |
| 44 | + |
| 45 | +#### Export the private key |
| 46 | + |
| 47 | +For local use: |
| 48 | + |
| 49 | +```bash |
| 50 | +gpg --armor --export-secret-keys YOUR_KEY_ID > key.asc |
| 51 | +``` |
| 52 | + |
| 53 | +For CI/CD (base64 encoded): |
| 54 | + |
| 55 | +```bash |
| 56 | +gpg --armor --export-secret-keys YOUR_KEY_ID | base64 |
| 57 | +``` |
| 58 | + |
| 59 | +#### Publish your public key (required for Maven Central verification) |
| 60 | + |
| 61 | +```bash |
| 62 | +gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID |
| 63 | +# Note: if you get a "no route to host" error, try an alternative keyserver such as keys.openpgp.org or pgp.mit.edu. |
| 64 | +``` |
| 65 | + |
| 66 | +## GitHub Secrets |
| 67 | + |
| 68 | +Configure these secrets in your GitHub repository: |
| 69 | + |
| 70 | +| Secret | Description | |
| 71 | +|--------------------------|--------------------------------------------------------| |
| 72 | +| `MAVEN_CENTRAL_USERNAME` | Username from Central Portal TOKEN (not the user) | |
| 73 | +| `MAVEN_CENTRAL_PASSWORD` | Password from Central Portal TOKEN (not user password) | |
| 74 | +| `GPG_SIGNING_KEY` | Base64-encoded GPG private key | |
| 75 | +| `GPG_SIGNING_PASSPHRASE` | Passphrase for the GPG key | |
| 76 | + |
| 77 | +## Publishing Methods |
| 78 | + |
| 79 | +### Automatic (CI/CD) |
| 80 | + |
| 81 | +Publishing is triggered automatically when: |
| 82 | + |
| 83 | +- A GitHub Release is created |
| 84 | +- The workflow is manually dispatched |
| 85 | + |
| 86 | +The workflow (`.github/workflows/publish.yaml`) handles: |
| 87 | + |
| 88 | +1. Javadoc verification |
| 89 | +2. Publishing to GitHub Packages |
| 90 | +3. Publishing to Maven Central |
| 91 | + |
| 92 | +### Manual (Local) |
| 93 | + |
| 94 | +#### Publish to Local Maven Repository |
| 95 | + |
| 96 | +Test artifact generation without uploading: |
| 97 | + |
| 98 | +```bash |
| 99 | +./gradlew publishToMavenLocal -PskipSigning |
| 100 | +``` |
| 101 | + |
| 102 | +Artifacts are published to `~/.m2/repository/io/permit/permit-sdk-java/` |
| 103 | + |
| 104 | +Note: Use `-PskipSigning` for local testing without GPG keys. This flag is not available for Maven Central publishing (signing is required). |
| 105 | + |
| 106 | +#### Publish to Maven Central (Staging Only) |
| 107 | + |
| 108 | +Upload to Central Portal without releasing: |
| 109 | + |
| 110 | +```bash |
| 111 | +./gradlew publishToMavenCentral \ |
| 112 | + -PmavenCentralUsername=TOKEN_USERNAME \ |
| 113 | + -PmavenCentralPassword=TOKEN_PASSWORD \ |
| 114 | + -PsigningInMemoryKey="$(cat key.asc)" \ |
| 115 | + -PsigningInMemoryKeyPassword=KEY_PASSPHRASE |
| 116 | +``` |
| 117 | + |
| 118 | +Review at [Central Portal Deployments](https://central.sonatype.com/publishing/deployments) |
| 119 | + |
| 120 | +#### Publish and Release to Maven Central |
| 121 | + |
| 122 | +Full publish with automatic release: |
| 123 | + |
| 124 | +```bash |
| 125 | +./gradlew publishAndReleaseToMavenCentral \ |
| 126 | + -PmavenCentralUsername=TOKEN_USERNAME \ |
| 127 | + -PmavenCentralPassword=TOKEN_PASSWORD \ |
| 128 | + -PsigningInMemoryKey="$(cat key.asc)" \ |
| 129 | + -PsigningInMemoryKeyPassword=KEY_PASSPHRASE |
| 130 | +``` |
| 131 | + |
| 132 | +#### Publish to GitHub Packages |
| 133 | + |
| 134 | +```bash |
| 135 | +GITHUB_ACTOR=username GITHUB_TOKEN=token ./gradlew publish |
| 136 | +``` |
| 137 | + |
| 138 | +## Gradle Tasks |
| 139 | + |
| 140 | +| Task | Description | |
| 141 | +|-----------------------------------|----------------------------------------------------------| |
| 142 | +| `publishToMavenLocal` | Publish to local Maven cache (~/.m2) | |
| 143 | +| `publishToMavenCentral` | Upload to Central Portal (staging) | |
| 144 | +| `publishAndReleaseToMavenCentral` | Upload and release to Maven Central | |
| 145 | +| `publish` | Publish to all configured repositories (GitHub Packages) | |
| 146 | + |
| 147 | +## Versioning |
| 148 | + |
| 149 | +Version is automatically determined by the `com.palantir.git-version` plugin based on git tags: |
| 150 | + |
| 151 | +- Tagged commit: `2.2.0` |
| 152 | +- Commits after tag: `2.2.0-1-gabcdef` |
| 153 | +- Dirty working directory: `2.2.0-1-gabcdef.dirty` |
| 154 | + |
| 155 | +To release a new version: |
| 156 | + |
| 157 | +```bash |
| 158 | +git tag 2.3.0 |
| 159 | +git push origin 2.3.0 |
| 160 | +``` |
| 161 | + |
| 162 | +## Troubleshooting |
| 163 | + |
| 164 | +### 403 Forbidden |
| 165 | + |
| 166 | +- Credentials may be invalid or expired |
| 167 | +- Regenerate token at Central Portal |
| 168 | + |
| 169 | +### Signature Verification Failed |
| 170 | + |
| 171 | +- GPG key may be malformed |
| 172 | +- Ensure key is base64 encoded without line breaks |
| 173 | + |
| 174 | +### Version Already Exists |
| 175 | + |
| 176 | +- Maven Central doesn't allow overwriting versions |
| 177 | +- Bump the version and try again |
| 178 | + |
| 179 | +## References |
| 180 | + |
| 181 | +- [Maven Central Portal](https://central.sonatype.com) |
| 182 | +- [vanniktech/gradle-maven-publish-plugin](https://vanniktech.github.io/gradle-maven-publish-plugin/central/) |
| 183 | +- [Sonatype Publishing Guide](https://central.sonatype.org/publish/publish-portal-gradle/) |
0 commit comments