Skip to content

Commit 036cb81

Browse files
committed
Migrate to new Maven Central Portal for publishing (#37)
1 parent ccbe6fd commit 036cb81

File tree

7 files changed

+281
-168
lines changed

7 files changed

+281
-168
lines changed

.github/workflows/javadoc.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- uses: actions/checkout@v4
14-
- uses: actions/setup-java@v3.11.0
1514
with:
16-
java-version: '8'
15+
fetch-depth: 0 # Required for git-version plugin
16+
- uses: actions/setup-java@v4
17+
with:
18+
java-version: '11'
1719
distribution: 'corretto'
1820
- name: Validate Gradle wrapper
19-
uses: gradle/wrapper-validation-action@v1
21+
uses: gradle/wrapper-validation-action@v2
22+
- name: Setup Gradle
23+
uses: gradle/actions/setup-gradle@v3
2024
- name: Generate Javadoc
21-
uses: gradle/gradle-build-action@v2
22-
with:
23-
arguments: javadoc
25+
run: ./gradlew javadoc
2426
- name: Check Javadoc generation
2527
run: |
2628
if [ -d "build/docs/javadoc" ]; then

.github/workflows/publish.yaml

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish package to GitHub Packages
1+
name: Publish package to GitHub Packages and Maven Central
22
on:
33
release:
44
types: [ created ]
@@ -11,17 +11,19 @@ jobs:
1111
contents: read
1212
packages: write
1313
steps:
14-
- uses: actions/checkout@v2
15-
- uses: actions/setup-java@v3.11.0
14+
- uses: actions/checkout@v4
1615
with:
17-
java-version: '8'
16+
fetch-depth: 0 # Required for git-version plugin
17+
- uses: actions/setup-java@v4
18+
with:
19+
java-version: '11'
1820
distribution: 'corretto'
1921
- name: Validate Gradle wrapper
20-
uses: gradle/wrapper-validation-action@v1
22+
uses: gradle/wrapper-validation-action@v2
23+
- name: Setup Gradle
24+
uses: gradle/actions/setup-gradle@v3
2125
- name: Verify Javadoc generation
22-
uses: gradle/gradle-build-action@v2
23-
with:
24-
arguments: javadoc
26+
run: ./gradlew javadoc
2527
- name: Check Javadoc generation
2628
run: |
2729
if [ -d "build/docs/javadoc" ]; then
@@ -30,15 +32,20 @@ jobs:
3032
echo "ERROR: Javadoc directory not found"
3133
exit 1
3234
fi
33-
- name: Publish package
34-
uses: gradle/gradle-build-action@v2
35-
with:
36-
arguments: publish publishToSonatype closeAndReleaseSonatypeStagingRepository
35+
- name: Publish to GitHub Packages
36+
# GitHub Packages doesn't require GPG signing (unlike Maven Central).
37+
# The -PskipSigning flag disables the vanniktech plugin's signAllPublications()
38+
# which would otherwise fail without GPG credentials.
39+
run: ./gradlew publish -PskipSigning
3740
env:
41+
GITHUB_ACTOR: ${{ github.actor }}
3842
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39-
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
40-
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
41-
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
42-
GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }}
43-
NEXUS_TOKEN_USERNAME: ${{ secrets.NEXUS_TOKEN_USERNAME }}
44-
NEXUS_TOKEN_PASSWORD: ${{ secrets.NEXUS_TOKEN_PASSWORD }}
43+
- name: Publish to Maven Central
44+
run: ./gradlew publishAndReleaseToMavenCentral
45+
env:
46+
# Nexus tokens were generated before we migrated to the new Maven Central,
47+
# it's backward compatible.
48+
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.NEXUS_TOKEN_USERNAME }}
49+
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.NEXUS_TOKEN_PASSWORD }}
50+
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SIGNING_KEY }}
51+
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SIGNING_PASSPHRASE }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ build
1111
# Ignore stg schemas
1212
stg-schemas/
1313
bin
14+
/key.asc

PUBLISHING.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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/)

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ For [Maven](https://maven.apache.org/) projects, use:
1515
<dependency>
1616
<groupId>io.permit</groupId>
1717
<artifactId>permit-sdk-java</artifactId>
18-
<version>2.0.0</version>
18+
<version>2.2.2</version>
1919
</dependency>
2020
```
2121

@@ -25,7 +25,7 @@ For [Gradle](https://gradle.org/) projects, configure `permit-sdk-java` as a dep
2525
dependencies {
2626
// ...
2727
28-
implementation 'io.permit:permit-sdk-java:2.0.0'
28+
implementation 'io.permit:permit-sdk-java:2.2.2'
2929
}
3030
```
3131

@@ -149,6 +149,6 @@ CreateOrUpdateResult<UserRead> result = permit.api.users.sync(new UserCreate("[U
149149

150150
## Javadoc reference
151151

152-
To view the javadoc reference, [click here](https://javadoc.io/doc/io.permit/permit-sdk-java/2.0.0/index.html).
152+
To view the javadoc reference, [click here](https://javadoc.io/doc/io.permit/permit-sdk-java/latest/index.html).
153153

154-
It's easiest to start with the root [Permit](https://javadoc.io/static/io.permit/permit-sdk-java/2.0.0/io/permit/sdk/Permit.html) class.
154+
It's easiest to start with the root [Permit](https://javadoc.io/doc/io.permit/permit-sdk-java/latest/io/permit/sdk/Permit.html) class.

0 commit comments

Comments
 (0)