|
1 | 1 | # Publishing Guide |
2 | 2 |
|
3 | | -This document describes how to publish the rootly-java SDK to Maven Central and GitHub Packages. |
| 3 | +This document describes how to publish the rootly-java SDK to Maven Central and GitHub Packages using the **new Maven Central Portal Publisher API**. |
4 | 4 |
|
5 | 5 | ## Prerequisites |
6 | 6 |
|
7 | | -### 1. Sonatype OSSRH Account |
| 7 | +### 1. Maven Central Portal Account |
8 | 8 |
|
9 | | -Create an account and request access to publish under the `com.rootly.client` groupId: |
10 | | -1. Create a [Sonatype JIRA account](https://issues.sonatype.org/secure/Signup!default.jspa) |
11 | | -2. Create a ticket requesting access to `com.rootly.client` groupId |
12 | | -3. Follow the verification process (may require domain ownership proof) |
| 9 | +The new publishing process uses the Maven Central Portal (not the legacy Sonatype OSSRH): |
13 | 10 |
|
14 | | -### 2. GPG Key for Signing |
| 11 | +1. **Create account**: Go to https://central.sonatype.com/ |
| 12 | +2. **Sign up** using GitHub, Google, or email |
| 13 | +3. **Verify namespace**: |
| 14 | + - Click "Add Namespace" button |
| 15 | + - Enter `com.rootly.client` |
| 16 | + - Verify ownership via: |
| 17 | + - **GitHub verification** (recommended): Add verification code to repository description or create a verification file |
| 18 | + - **DNS verification**: Add TXT record to `rootly.com` domain |
| 19 | + - **Publish verification key**: Create a public verification file |
15 | 20 |
|
16 | | -Maven Central requires all artifacts to be signed with GPG: |
| 21 | +**Namespace verification typically completes within minutes for GitHub verification.** |
17 | 22 |
|
18 | | -```bash |
19 | | -# Generate a GPG key |
20 | | -gpg --gen-key |
| 23 | +### 2. Generate User Token |
| 24 | + |
| 25 | +Once your namespace is verified: |
| 26 | + |
| 27 | +1. Go to https://central.sonatype.com/account |
| 28 | +2. Click **"Generate User Token"** |
| 29 | +3. Copy both the **Username** and **Password** (you'll need both) |
| 30 | +4. Store these securely - they're your `MAVEN_CENTRAL_USERNAME` and `MAVEN_CENTRAL_PASSWORD` |
21 | 31 |
|
22 | | -# List your keys |
23 | | -gpg --list-keys |
| 32 | +**Note**: This is much simpler than the old OSSRH JIRA ticket process! |
24 | 33 |
|
25 | | -# Export your public key (submit to key server) |
26 | | -gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID |
| 34 | +### 3. GPG Key for Signing |
27 | 35 |
|
28 | | -# Export your private key (for GitHub Secrets) |
29 | | -gpg --export-secret-keys YOUR_KEY_ID | base64 |
| 36 | +Maven Central requires all artifacts to be signed with GPG: |
| 37 | + |
| 38 | +```bash |
| 39 | +# Generate a GPG key (if you don't have one) |
| 40 | +gpg --gen-key |
| 41 | +# Follow prompts: |
| 42 | +# - Real name: Rootly (or your name) |
| 43 | +# - Email: support@rootly.com |
| 44 | +# - Set a passphrase (save this for later) |
| 45 | + |
| 46 | +# List your keys to find the KEY_ID |
| 47 | +gpg --list-secret-keys --keyid-format=long |
| 48 | +# Output shows: sec rsa3072/ABCD1234EFGH5678 |
| 49 | +# The part after / is your KEY_ID |
| 50 | + |
| 51 | +# Upload public key to key servers (required) |
| 52 | +gpg --keyserver keyserver.ubuntu.com --send-keys ABCD1234EFGH5678 |
| 53 | +gpg --keyserver keys.openpgp.org --send-keys ABCD1234EFGH5678 |
| 54 | +gpg --keyserver pgp.mit.edu --send-keys ABCD1234EFGH5678 |
| 55 | + |
| 56 | +# Export private key in base64 for GitHub Secrets |
| 57 | +gpg --export-secret-keys ABCD1234EFGH5678 | base64 |
| 58 | +# Copy the entire base64 output |
30 | 59 | ``` |
31 | 60 |
|
32 | | -### 3. Configure GitHub Secrets |
| 61 | +### 4. Configure GitHub Secrets |
33 | 62 |
|
34 | | -Add the following secrets to your GitHub repository (Settings → Secrets and variables → Actions): |
| 63 | +Add these secrets to your GitHub repository (Settings → Secrets and variables → Actions): |
35 | 64 |
|
36 | 65 | | Secret Name | Description | How to Get | |
37 | 66 | |-------------|-------------|------------| |
38 | | -| `MAVEN_USERNAME` | Sonatype OSSRH username | Your JIRA username | |
39 | | -| `MAVEN_PASSWORD` | Sonatype OSSRH password or token | Your JIRA password or [generated token](https://oss.sonatype.org/#profile;User%20Token) | |
| 67 | +| `MAVEN_CENTRAL_USERNAME` | Maven Central Portal username | From token generation at central.sonatype.com/account | |
| 68 | +| `MAVEN_CENTRAL_PASSWORD` | Maven Central Portal password | From token generation at central.sonatype.com/account | |
40 | 69 | | `GPG_PRIVATE_KEY` | GPG private key in base64 | Run: `gpg --export-secret-keys YOUR_KEY_ID \| base64` | |
41 | 70 | | `GPG_PASSPHRASE` | Passphrase for GPG key | The passphrase you set when creating the GPG key | |
42 | 71 |
|
43 | | -**Note**: GitHub Packages publishing uses the automatic `GITHUB_TOKEN` and requires no manual setup. |
| 72 | +```bash |
| 73 | +# Add secrets using GitHub CLI |
| 74 | +gh secret set MAVEN_CENTRAL_USERNAME --body "your-token-username" |
| 75 | +gh secret set MAVEN_CENTRAL_PASSWORD --body "your-token-password" |
| 76 | +gh secret set GPG_PASSPHRASE --body "your-gpg-passphrase" |
| 77 | + |
| 78 | +# For GPG_PRIVATE_KEY (multiline): |
| 79 | +gpg --export-secret-keys ABCD1234EFGH5678 | base64 > gpg-key.txt |
| 80 | +gh secret set GPG_PRIVATE_KEY < gpg-key.txt |
| 81 | +rm gpg-key.txt |
| 82 | +``` |
44 | 83 |
|
45 | 84 | ## Publishing Process |
46 | 85 |
|
47 | 86 | The publish workflow runs automatically when you create a GitHub release. |
48 | 87 |
|
49 | 88 | ### Step 1: Update Version |
50 | 89 |
|
51 | | -Update the version in both build files: |
52 | | - |
53 | 90 | ```bash |
54 | | -# Update version in pom.xml |
55 | | -sed -i '' 's/<version>0.0.1<\/version>/<version>0.0.2<\/version>/' pom.xml |
56 | | - |
57 | | -# Update version in build.gradle |
58 | | -sed -i '' "s/version = '0.0.1'/version = '0.0.2'/" build.gradle |
59 | | - |
60 | | -# Or use the Makefile |
| 91 | +# Using Makefile (recommended) |
61 | 92 | make bump-patch # 0.0.1 -> 0.0.2 |
62 | 93 | make bump-minor # 0.0.1 -> 0.1.0 |
63 | 94 | make bump-major # 0.0.1 -> 1.0.0 |
| 95 | + |
| 96 | +# Manual update |
| 97 | +sed -i '' 's/<version>0.0.1<\/version>/<version>0.0.2<\/version>/' pom.xml |
| 98 | +sed -i '' "s/version = '0.0.1'/version = '0.0.2'/" build.gradle |
| 99 | +git add pom.xml build.gradle |
| 100 | +git commit -m "Bump version to 0.0.2" |
64 | 101 | ``` |
65 | 102 |
|
66 | | -### Step 2: Commit and Push |
| 103 | +### Step 2: Push Changes |
67 | 104 |
|
68 | 105 | ```bash |
69 | | -git add pom.xml build.gradle |
70 | | -git commit -m "Bump version to 0.0.2" |
71 | 106 | git push origin master |
72 | 107 | ``` |
73 | 108 |
|
74 | | -### Step 3: Create a Release |
75 | | - |
76 | | -Create a release via GitHub UI or CLI: |
| 109 | +### Step 3: Create a GitHub Release |
77 | 110 |
|
78 | 111 | ```bash |
79 | | -# Using GitHub CLI |
80 | | -gh release create v0.0.2 --title "Release 0.0.2" --notes "Release notes here" |
| 112 | +# Using GitHub CLI (recommended) |
| 113 | +gh release create v0.0.2 \ |
| 114 | + --title "Release 0.0.2" \ |
| 115 | + --notes "Release notes here" |
81 | 116 |
|
82 | | -# Or push the tag created by make |
83 | | -make push-tag |
| 117 | +# Or via GitHub UI: |
| 118 | +# Go to https://github.com/rootlyhq/rootly-java/releases/new |
84 | 119 | ``` |
85 | 120 |
|
86 | 121 | ### Step 4: Monitor the Workflow |
87 | 122 |
|
88 | | -The publish workflow will: |
89 | | -1. Run all tests |
90 | | -2. Deploy to Maven Central (with GPG signing) |
91 | | -3. Deploy to GitHub Packages |
| 123 | +The publish workflow will automatically: |
| 124 | + |
| 125 | +1. ✅ Run all tests |
| 126 | +2. ✅ Sign artifacts with GPG |
| 127 | +3. ✅ Deploy to Maven Central Portal |
| 128 | +4. ✅ Auto-publish to Maven Central (no manual UI steps needed!) |
| 129 | +5. ✅ Deploy to GitHub Packages |
| 130 | + |
| 131 | +Check the Actions tab: https://github.com/rootlyhq/rootly-java/actions |
| 132 | + |
| 133 | +### Step 5: Verify Publication |
| 134 | + |
| 135 | +**Maven Central** (available within 30 minutes): |
| 136 | +- Search: https://central.sonatype.com/artifact/com.rootly.client/rootly |
| 137 | +- Check deployments: https://central.sonatype.com/publishing |
| 138 | + |
| 139 | +**GitHub Packages** (available immediately): |
| 140 | +- View: https://github.com/rootlyhq/rootly-java/packages |
92 | 141 |
|
93 | | -Check the Actions tab in GitHub for progress. |
| 142 | +## What's Different from Legacy OSSRH? |
94 | 143 |
|
95 | | -### Step 5: Release on Maven Central |
| 144 | +The new Maven Central Portal is **much simpler**: |
96 | 145 |
|
97 | | -After the workflow completes: |
98 | | -1. Go to [Sonatype OSSRH](https://oss.sonatype.org/) |
99 | | -2. Log in with your credentials |
100 | | -3. Click "Staging Repositories" in the left sidebar |
101 | | -4. Find your repository (com.rootly.client) |
102 | | -5. Click "Close" to validate the artifacts |
103 | | -6. Once validation passes, click "Release" to publish |
| 146 | +| Old Way (OSSRH) | New Way (Portal) | |
| 147 | +|-----------------|------------------| |
| 148 | +| Create Sonatype JIRA ticket | Sign up at central.sonatype.com | |
| 149 | +| Wait 1-2 days for approval | Verify namespace in minutes | |
| 150 | +| Manually close/release in UI | Auto-publish with `autoPublish=true` | |
| 151 | +| Complex Nexus repository URL | Simple API endpoint | |
| 152 | +| Token from JIRA profile | Token from Account page | |
104 | 153 |
|
105 | | -Artifacts will be available on Maven Central within 2 hours and synchronized to Maven Central search within 4 hours. |
| 154 | +**No more manual UI steps after deployment!** The new process is fully automated. |
106 | 155 |
|
107 | 156 | ## Verification |
108 | 157 |
|
@@ -137,24 +186,49 @@ Artifacts will be available on Maven Central within 2 hours and synchronized to |
137 | 186 |
|
138 | 187 | ### GPG Signing Fails |
139 | 188 |
|
| 189 | +**Error**: "gpg: signing failed: No secret key" |
140 | 190 | - Verify `GPG_PRIVATE_KEY` is base64 encoded correctly |
141 | 191 | - Ensure `GPG_PASSPHRASE` matches your key's passphrase |
142 | | -- Check that the key hasn't expired: `gpg --list-keys` |
| 192 | +- Check key hasn't expired: `gpg --list-keys` |
143 | 193 |
|
144 | 194 | ### Maven Central Deployment Fails |
145 | 195 |
|
146 | | -- Verify `MAVEN_USERNAME` and `MAVEN_PASSWORD` are correct |
147 | | -- Check that you have permission for the `com.rootly.client` groupId |
148 | | -- Review Sonatype JIRA ticket status |
| 196 | +**Error**: "401 Unauthorized" |
| 197 | +- Verify `MAVEN_CENTRAL_USERNAME` and `MAVEN_CENTRAL_PASSWORD` are from the token (not your login credentials) |
| 198 | +- Regenerate token at: https://central.sonatype.com/account |
| 199 | + |
| 200 | +**Error**: "403 Forbidden - Namespace not verified" |
| 201 | +- Complete namespace verification at: https://central.sonatype.com/publishing |
| 202 | +- Choose GitHub verification for fastest approval |
| 203 | + |
| 204 | +**Error**: "POM validation failed" |
| 205 | +- Ensure `pom.xml` has required fields: name, description, url, licenses, developers, scm |
| 206 | +- Check artifact includes -sources.jar and -javadoc.jar |
149 | 207 |
|
150 | 208 | ### GitHub Packages Deployment Fails |
151 | 209 |
|
152 | | -- Verify the workflow has `packages: write` permission |
153 | | -- Check that `GITHUB_TOKEN` is being passed correctly |
154 | | -- Ensure the repository URL matches your GitHub repository |
| 210 | +**Error**: "401 Unauthorized" |
| 211 | +- Verify workflow has `packages: write` permission |
| 212 | +- Check `GITHUB_TOKEN` is being passed correctly |
| 213 | + |
| 214 | +## Testing Locally |
| 215 | + |
| 216 | +Before creating a release, test the publishing process locally: |
| 217 | + |
| 218 | +```bash |
| 219 | +# Build and sign artifacts |
| 220 | +mvn clean verify -P sign-artifacts |
| 221 | + |
| 222 | +# Check that artifacts are signed |
| 223 | +ls -la target/*.asc |
| 224 | + |
| 225 | +# Test deployment (dry run) |
| 226 | +mvn deploy -P sign-artifacts -DskipTests |
| 227 | +``` |
155 | 228 |
|
156 | 229 | ## Resources |
157 | 230 |
|
158 | | -- [Maven Central Guide](https://central.sonatype.org/publish/publish-guide/) |
| 231 | +- [Maven Central Portal](https://central.sonatype.com/) |
| 232 | +- [Portal Documentation](https://central.sonatype.org/publish/publish-portal-maven/) |
159 | 233 | - [GitHub Packages Maven](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry) |
160 | | -- [GPG Key Generation](https://central.sonatype.org/publish/requirements/gpg/) |
| 234 | +- [GPG Signing Guide](https://central.sonatype.org/publish/requirements/gpg/) |
0 commit comments