Skip to content

Commit f0ff805

Browse files
gclaro-idmeclaude
andcommitted
Add release guide for publishing to Maven Central
Adds docs/releasing.md with step-by-step instructions for triggering the release workflow, configuring required secrets, verifying published artifacts, troubleshooting common failures, and testing locally. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent bafd57a commit f0ff805

1 file changed

Lines changed: 211 additions & 0 deletions

File tree

docs/releasing.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Releasing to Maven Central
2+
3+
This document covers how to create and publish a new release of the ID.me Auth Sample Code SDK to Maven Central and GitHub Packages.
4+
5+
## Overview
6+
7+
The release process is fully automated via the [`release.yml`](../.github/workflows/release.yml) GitHub Actions workflow. A single manual trigger:
8+
9+
1. Validates the version and checks for tag conflicts
10+
2. Builds the AAR and all Maven artifacts
11+
3. Generates SLSA build provenance attestations
12+
4. Publishes to both GitHub Packages and Maven Central (Sonatype OSSRH)
13+
5. Creates and pushes a git tag
14+
6. Creates a GitHub Release with the AAR and attestation bundle
15+
16+
**Maven coordinates:** `com.idmelabs.auth:android-auth-sample-code:<version>`
17+
18+
---
19+
20+
## Prerequisites
21+
22+
Before triggering a release, confirm the following are in place.
23+
24+
### GitHub Secrets
25+
26+
All secrets must be configured under the `release` GitHub Actions environment (not the default repository secrets). Navigate to **Settings → Environments → release** to manage them.
27+
28+
| Secret | Description |
29+
|---|---|
30+
| `SONATYPE_USERNAME` | Sonatype Central Portal account username |
31+
| `SONATYPE_PASSWORD` | Sonatype Central Portal account password or token |
32+
| `SIGNING_KEY_ID` | GPG key ID (last 8 characters of the key fingerprint) |
33+
| `SIGNING_KEY` | GPG private key in ASCII-armored format |
34+
| `SIGNING_PASSWORD` | Passphrase for the GPG key |
35+
36+
`GITHUB_TOKEN` is provided automatically by GitHub Actions and does not need to be configured manually.
37+
38+
### GPG Key Setup
39+
40+
If a GPG key has not been created yet:
41+
42+
```bash
43+
# Generate a new GPG key (use RSA 4096, no expiry)
44+
gpg --full-generate-key
45+
46+
# List keys to find your key ID
47+
gpg --list-secret-keys --keyid-format LONG
48+
49+
# Export the private key for the SIGNING_KEY secret
50+
gpg --armor --export-secret-keys <KEY_ID>
51+
52+
# Publish the public key to a keyserver so Maven Central can verify signatures
53+
gpg --keyserver keyserver.ubuntu.com --send-keys <KEY_ID>
54+
```
55+
56+
The `SIGNING_KEY_ID` is the **last 8 characters** of the full fingerprint shown by `--list-secret-keys`.
57+
58+
### Sonatype Account
59+
60+
Publishing to Maven Central requires a Sonatype account with publishing rights for the `com.idmelabs.auth` namespace. If you are setting this up for the first time, refer to the [Sonatype Central Portal documentation](https://central.sonatype.org/register/central-portal/) to register and claim the namespace.
61+
62+
---
63+
64+
## Triggering a Release
65+
66+
1. Go to the **Actions** tab of the repository on GitHub.
67+
2. Select the **Release Auth Sample** workflow from the left sidebar.
68+
3. Click **Run workflow**.
69+
4. Fill in the inputs:
70+
- **SDK Version** (required): The semantic version to release, e.g. `1.2.0` or `1.2.0-beta.1`.
71+
- **Make draft release** (optional): Check this box to create a draft GitHub Release (useful for review before publishing).
72+
5. Click **Run workflow** to start the job.
73+
74+
### Version Format
75+
76+
Versions must follow semantic versioning: `MAJOR.MINOR.PATCH` or `MAJOR.MINOR.PATCH-PRERELEASE`.
77+
78+
Valid examples:
79+
- `1.0.0`
80+
- `2.1.3`
81+
- `1.0.0-beta.1`
82+
- `1.0.0-rc.2`
83+
84+
The workflow will fail early if the version does not match this format or if the tag `v<version>` already exists.
85+
86+
---
87+
88+
## What the Workflow Does
89+
90+
### Step-by-Step
91+
92+
1. **Checkout** — Full git history is fetched (`fetch-depth: 0`) to support tagging.
93+
2. **Environment setup** — JDK 17 (Temurin), Android SDK, and Gradle are configured.
94+
3. **Version validation** — The version string is validated against the semver regex and checked for existing tags.
95+
4. **Build release AAR** — Runs `./gradlew :sdk:assembleRelease -PreleaseVersion=<version>`. Output: `sdk/build/outputs/aar/sdk-release.aar`.
96+
5. **Build Maven artifacts locally** — Runs `./gradlew :sdk:publishReleasePublicationToMavenLocalRepository -PreleaseVersion=<version>`. Produces POM, AAR, sources JAR, and Dokka javadoc JAR in `~/.m2`.
97+
6. **Generate attestations** — SLSA build provenance is generated for both the release AAR and all Maven artifacts using `actions/attest-build-provenance`.
98+
7. **Publish to GitHub Packages** — All Maven artifacts (POM, AAR, module metadata, attestation bundle) are uploaded via the GitHub Packages Maven registry API.
99+
8. **Publish to Maven Central** — Runs:
100+
```
101+
./gradlew :sdk:publishReleasePublicationToSonatypeRepository \
102+
closeAndReleaseSonatypeStagingRepository \
103+
-PreleaseVersion=<version>
104+
```
105+
This publishes signed artifacts to Sonatype staging and then closes and releases the staging repository to Maven Central.
106+
9. **Create git tag** — Tags the current commit as `v<version>` and pushes to `origin`.
107+
10. **Create GitHub Release** — A release is created with the AAR and SLSA attestation bundle attached.
108+
109+
### Published Artifacts
110+
111+
For version `1.2.0`, the following files are published:
112+
113+
```
114+
com/idmelabs/auth/android-auth-sample-code/1.2.0/
115+
├── android-auth-sample-code-1.2.0.aar
116+
├── android-auth-sample-code-1.2.0.pom
117+
├── android-auth-sample-code-1.2.0-sources.jar
118+
├── android-auth-sample-code-1.2.0-javadoc.jar
119+
├── android-auth-sample-code-1.2.0.module
120+
└── android-auth-sample-code-1.2.0.intoto.jsonl (attestation bundle)
121+
```
122+
123+
All artifacts are signed with the configured GPG key.
124+
125+
---
126+
127+
## Verifying a Release
128+
129+
### Maven Central
130+
131+
After the workflow completes, the release is available at:
132+
133+
```
134+
https://central.sonatype.com/artifact/com.idmelabs.auth/android-auth-sample-code
135+
```
136+
137+
Maven Central propagation typically takes 10–30 minutes after the staging repository is released.
138+
139+
### GitHub Packages
140+
141+
Artifacts are immediately available at:
142+
143+
```
144+
https://github.com/IDme/android-auth-sample-code/packages
145+
```
146+
147+
### SLSA Attestation
148+
149+
To verify the build provenance of a downloaded artifact:
150+
151+
```bash
152+
gh attestation verify android-auth-sample-code-<version>.aar --repo IDme/android-auth-sample-code
153+
```
154+
155+
---
156+
157+
## Troubleshooting
158+
159+
### Tag already exists
160+
161+
The workflow checks for existing tags before proceeding. If the tag `v<version>` already exists, the workflow will fail with:
162+
163+
```
164+
Tag v<version> already exists!
165+
```
166+
167+
Either choose a different version or, if the previous release failed partway through, delete the existing tag manually:
168+
169+
```bash
170+
git push --delete origin v<version>
171+
git tag -d v<version>
172+
```
173+
174+
### Sonatype staging repository not closed
175+
176+
If the `closeAndReleaseSonatypeStagingRepository` task fails, check the [Sonatype Central Portal](https://central.sonatype.com/) for the status of the staging repository. Common causes:
177+
178+
- GPG signature validation failed (key not published to a keyserver)
179+
- Missing required POM fields
180+
- Artifact checksums mismatch
181+
182+
### Signing failures
183+
184+
If the build fails with a PGP signing error, verify that:
185+
186+
- `SIGNING_KEY` contains the full ASCII-armored private key, including the `-----BEGIN PGP PRIVATE KEY BLOCK-----` header and footer
187+
- `SIGNING_KEY_ID` matches the key exported in `SIGNING_KEY`
188+
- `SIGNING_PASSWORD` is the correct passphrase for the key
189+
190+
---
191+
192+
## Local Publishing (for testing)
193+
194+
To test the build locally without publishing to any remote registry:
195+
196+
```bash
197+
# Build the AAR
198+
./gradlew :sdk:assembleRelease -PreleaseVersion=1.0.0-SNAPSHOT
199+
200+
# Publish to local Maven repository (~/.m2)
201+
./gradlew :sdk:publishReleasePublicationToMavenLocalRepository -PreleaseVersion=1.0.0-SNAPSHOT
202+
```
203+
204+
To consume the locally published artifact in another project, add `mavenLocal()` to the project's repository list:
205+
206+
```kotlin
207+
repositories {
208+
mavenLocal()
209+
mavenCentral()
210+
}
211+
```

0 commit comments

Comments
 (0)