|
1 | 1 | # Release guide (Maven Central) |
2 | 2 |
|
3 | | -This project is configured for Sonatype OSSRH publishing under the `release` Maven profile. |
| 3 | +This project publishes to Maven Central via the **Sonatype Central Portal** (`central.sonatype.com`). |
| 4 | +The `release` Maven profile handles sources jar, javadoc jar, GPG signing, and upload automatically. |
4 | 5 |
|
5 | | -## 1) Prerequisites |
| 6 | +--- |
6 | 7 |
|
7 | | -1. Sonatype OSSRH account with publish access for `com.danubemessaging`. |
8 | | -2. GPG key pair available locally. |
9 | | -3. `~/.m2/settings.xml` configured with server credentials: |
| 8 | +## 1) One-time setup: Central Portal account |
| 9 | + |
| 10 | +> Skip this section if the account already exists. |
| 11 | +
|
| 12 | +1. Go to **https://central.sonatype.com** and sign up (GitHub SSO works). |
| 13 | +2. Click **Namespaces** → **Add Namespace**. |
| 14 | +3. Enter `com.danube-messaging`. |
| 15 | +4. Sonatype will show a **DNS TXT verification token**. Add it to the `danube-messaging.com` DNS: |
| 16 | + ``` |
| 17 | + TXT @ sonatype-central-verification=<token> |
| 18 | + ``` |
| 19 | +5. Click **Verify Namespace**. Once verified the namespace is permanently linked to your account. |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## 2) One-time setup: Portal user token (credentials) |
| 24 | + |
| 25 | +1. In the Central Portal: **Account** → **Generate User Token**. |
| 26 | +2. Copy the `username` and `password` values shown. |
| 27 | +3. Add them to `~/.m2/settings.xml`: |
10 | 28 |
|
11 | 29 | ```xml |
12 | 30 | <settings> |
13 | 31 | <servers> |
14 | 32 | <server> |
15 | | - <id>ossrh</id> |
16 | | - <username>${env.OSSRH_USERNAME}</username> |
17 | | - <password>${env.OSSRH_PASSWORD}</password> |
| 33 | + <id>central</id> |
| 34 | + <username>YOUR_TOKEN_USERNAME</username> |
| 35 | + <password>YOUR_TOKEN_PASSWORD</password> |
18 | 36 | </server> |
19 | 37 | </servers> |
20 | 38 | </settings> |
21 | 39 | ``` |
22 | 40 |
|
23 | | -4. Environment variables set for CI/local release: |
| 41 | +> **Never** commit these credentials. Use environment variable substitution if needed: |
| 42 | +> ```xml |
| 43 | +> <username>${env.CENTRAL_TOKEN_USERNAME}</username> |
| 44 | +> <password>${env.CENTRAL_TOKEN_PASSWORD}</password> |
| 45 | +> ``` |
| 46 | +
|
| 47 | +--- |
| 48 | +
|
| 49 | +## 3) One-time setup: GPG signing key |
24 | 50 |
|
25 | 51 | ```bash |
26 | | -export OSSRH_USERNAME=... |
27 | | -export OSSRH_PASSWORD=... |
28 | | -export GPG_TTY=$(tty) |
| 52 | +# Generate a key (if you don't have one) |
| 53 | +gpg --gen-key |
| 54 | +
|
| 55 | +# List keys and note the key ID |
| 56 | +gpg --list-secret-keys --keyid-format=long |
| 57 | +
|
| 58 | +# Publish the public key to a keyserver |
| 59 | +gpg --keyserver keyserver.ubuntu.com --send-keys <KEY_ID> |
29 | 60 | ``` |
30 | 61 |
|
31 | | -If using passphrase-based signing in CI, also pass: |
| 62 | +Set the passphrase in your environment for headless signing: |
32 | 63 |
|
33 | 64 | ```bash |
34 | | --Dgpg.passphrase=... |
| 65 | +export GPG_TTY=$(tty) |
35 | 66 | ``` |
36 | 67 |
|
37 | | -## 2) Local verification (no deploy) |
| 68 | +--- |
| 69 | + |
| 70 | +## 4) Local verification (no deploy) |
| 71 | + |
| 72 | +Before publishing, verify that all artifacts build and sign correctly: |
38 | 73 |
|
39 | 74 | ```bash |
40 | 75 | mvn -Prelease -DskipTests verify |
41 | 76 | ``` |
42 | 77 |
|
43 | | -This validates source jar, javadoc jar, and artifact signing configuration. |
| 78 | +This produces and signs: |
| 79 | +- `danube-client-proto-0.2.0.jar` + sources + javadoc |
| 80 | +- `danube-client-0.2.0.jar` + sources + javadoc |
44 | 81 |
|
45 | | -## 3) Publish snapshot |
| 82 | +--- |
| 83 | + |
| 84 | +## 5) Publish release version |
| 85 | + |
| 86 | +1. Confirm root `pom.xml` version is `0.2.0` (no `-SNAPSHOT` suffix). |
| 87 | +2. Commit and tag the release: |
| 88 | + |
| 89 | +```bash |
| 90 | +git add -A |
| 91 | +git commit -m "release: v0.2.0" |
| 92 | +git tag v0.2.0 |
| 93 | +git push origin main --tags |
| 94 | +``` |
| 95 | + |
| 96 | +3. Deploy to Maven Central: |
46 | 97 |
|
47 | 98 | ```bash |
48 | 99 | mvn -Prelease -DskipTests deploy |
49 | 100 | ``` |
50 | 101 |
|
51 | | -For `-SNAPSHOT` versions this publishes to: |
| 102 | +Both `danube-client-proto` and `danube-client` are published in one command (multi-module build). |
| 103 | +The `central-publishing-maven-plugin` uploads, validates, and releases automatically |
| 104 | +(`autoPublish=true`, `waitUntil=published`). Artifacts are typically searchable within 30 minutes. |
| 105 | + |
| 106 | +If GPG passphrase entry is required during deployment: |
| 107 | + |
| 108 | +```bash |
| 109 | +mvn -Prelease -DskipTests -Dgpg.passphrase=YOUR_PASSPHRASE deploy |
| 110 | +``` |
52 | 111 |
|
53 | | -- `https://s01.oss.sonatype.org/content/repositories/snapshots` |
| 112 | +--- |
54 | 113 |
|
55 | | -## 4) Publish release version |
| 114 | +## 6) After release |
56 | 115 |
|
57 | | -1. Update root `<version>` from `x.y.z-SNAPSHOT` to `x.y.z`. |
58 | | -2. Commit and tag the release. |
59 | | -3. Run: |
| 116 | +1. Bump to the next development version: |
60 | 117 |
|
61 | 118 | ```bash |
62 | | -mvn -Prelease -DskipTests deploy |
| 119 | +# In pom.xml, danube-client/pom.xml, danube-client-proto/pom.xml |
| 120 | +# Change version: 0.2.0 → 0.3.0-SNAPSHOT |
| 121 | +``` |
| 122 | + |
| 123 | +2. Commit and push: |
| 124 | + |
| 125 | +```bash |
| 126 | +git add -A |
| 127 | +git commit -m "chore: bump to 0.3.0-SNAPSHOT" |
| 128 | +git push origin main |
63 | 129 | ``` |
64 | 130 |
|
65 | | -Release artifacts are staged and closed/released automatically via `nexus-staging-maven-plugin`. |
| 131 | +--- |
| 132 | + |
| 133 | +## CI/CD (GitHub Actions) |
66 | 134 |
|
67 | | -## 5) After release |
| 135 | +To automate publishing from CI, set these repository secrets: |
68 | 136 |
|
69 | | -1. Bump to next development version (e.g. `x.y.(z+1)-SNAPSHOT`). |
70 | | -2. Push commit and tag. |
| 137 | +| Secret | Value | |
| 138 | +|--------|-------| |
| 139 | +| `CENTRAL_TOKEN_USERNAME` | Portal user token username | |
| 140 | +| `CENTRAL_TOKEN_PASSWORD` | Portal user token password | |
| 141 | +| `GPG_PRIVATE_KEY` | Output of `gpg --armor --export-secret-keys <KEY_ID>` | |
| 142 | +| `GPG_PASSPHRASE` | GPG key passphrase | |
| 143 | + |
| 144 | +Then in your workflow: |
| 145 | + |
| 146 | +```yaml |
| 147 | +- name: Import GPG key |
| 148 | + run: echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import |
| 149 | + |
| 150 | +- name: Publish to Maven Central |
| 151 | + run: mvn -Prelease -DskipTests -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} deploy |
| 152 | + env: |
| 153 | + CENTRAL_TOKEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }} |
| 154 | + CENTRAL_TOKEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }} |
| 155 | +``` |
0 commit comments