Skip to content

Commit 3dcc6b4

Browse files
dmealingclaude
andcommitted
chore(java): bump to 7.0.1-SNAPSHOT + RELEASING-java.md post-7.0.0
Post-release cleanup following the successful 7.0.0 publish to Maven Central (14 artifacts live at com.metaobjects:metaobjects-*:7.0.0, v7.0.0 tag pushed). Two changes: 1. **Version bump to 7.0.1-SNAPSHOT** across all reactor poms + non-reactor poms with <parent> refs (integration-tests, integration-tests-kotlin, docs, archetype, examples/*). 2. **New docs/RELEASING-java.md** documenting the procedure as actually executed, including the non-obvious gotchas surfaced during the first publish: - -pl '!examples' doesn't transitively exclude examples/* under Maven 3.6.3; 7.0.0 dropped archetype + examples from the reactor instead. - Kotlin modules need dokka-maven-plugin for the javadoc.jar — Central rejects deployments missing it; maven-javadoc-plugin only scans Java sources. - -DskipTests is needed today because of 4 pre-existing provider-extension conformance failures on main (unrelated to release content). - autoPublish: true means no staging review window — BUILD SUCCESS = LIVE on Central. The doc reflects what actually happened, not a speculative procedure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 750a873 commit 3dcc6b4

26 files changed

Lines changed: 303 additions & 25 deletions

File tree

.claude/worktrees/fr-003-plan-2

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/RELEASING-java.md

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
# Releasing the Java line to Maven Central
2+
3+
_Written from the **7.0.0** release (first publish from the consolidated
4+
reactor at `server/java/`, 2026-05-27)._
5+
6+
## Companion doc
7+
8+
[`docs/RELEASING.md`](RELEASING.md) is TS / npm — different tooling, auth,
9+
and gotchas. Each language ecosystem gets its own guide per the policy
10+
documented there. Java tags are independent from TS (`v7.0.0` for Java; TS
11+
is on a separate `0.x` track).
12+
13+
## What gets published
14+
15+
The reactor (`server/java/pom.xml`) lists 14 publishable modules. As of
16+
7.0.0 the reactor explicitly **excludes** `archetype` and `examples` — they
17+
were aggregator entries but not consumer-facing dependencies, and keeping
18+
them in the reactor required `-pl` exclusions that didn't transitively
19+
cover `examples/*` sub-modules under Maven 3.6.3. They still exist as
20+
source directories (for scaffold + sample purposes) — just not built by
21+
the reactor and not deployed.
22+
23+
| Module dir | Maven coords (`com.metaobjects:*`) |
24+
|---|---|
25+
| `metadata/` | `metaobjects-metadata` |
26+
| `codegen-base/` | `metaobjects-codegen-base` |
27+
| `codegen-mustache/` | `metaobjects-codegen-mustache` |
28+
| `codegen-spring/` | `metaobjects-codegen-spring` |
29+
| `codegen-kotlin/` | `metaobjects-codegen-kotlin` |
30+
| `codegen-plantuml/` | `metaobjects-codegen-plantuml` |
31+
| `render/` | `metaobjects-render` |
32+
| `metadata-ktx/` | `metaobjects-metadata-ktx` |
33+
| `om/` | `metaobjects-om` |
34+
| `omdb/` | `metaobjects-omdb` |
35+
| `omdb-ktx/` | `metaobjects-omdb-ktx` |
36+
| `dynamic/` | `metaobjects-dynamic-core` |
37+
| `core-spring/` | `metaobjects-core-spring` |
38+
| `maven-plugin/` | `metaobjects-maven-plugin` |
39+
40+
## Prerequisites (one-time, per machine)
41+
42+
The reactor's `release` profile uses:
43+
44+
1. **Central Portal credentials.** Get a User Token from
45+
<https://central.sonatype.com/account>. Add to `~/.m2/settings.xml`:
46+
47+
```xml
48+
<servers>
49+
<server>
50+
<id>central</id>
51+
<username>YOUR_USER_TOKEN_NAME</username>
52+
<password>YOUR_USER_TOKEN_VALUE</password>
53+
</server>
54+
</servers>
55+
```
56+
57+
`<id>central</id>` must match `publishingServerId` in the reactor pom's
58+
`central-publishing-maven-plugin` config.
59+
60+
2. **GPG signing key.** Maven Central requires signed JARs. The key used
61+
for 7.0.0 was generated batch-mode with `%no-protection` (no passphrase
62+
— operationally simplest; rotate via the revocation cert if it ever
63+
leaks). Generate with:
64+
65+
```bash
66+
cat > /tmp/gen.txt <<'EOF'
67+
%no-protection
68+
Key-Type: RSA
69+
Key-Length: 4096
70+
Key-Usage: sign
71+
Subkey-Type: RSA
72+
Subkey-Length: 4096
73+
Subkey-Usage: encrypt
74+
Name-Real: Douglas Mealing
75+
Name-Email: doug@dougmealing.com
76+
Expire-Date: 5y
77+
%commit
78+
EOF
79+
gpg --batch --generate-key /tmp/gen.txt && rm /tmp/gen.txt
80+
```
81+
82+
Upload the public half to all three keyservers Sonatype validates against:
83+
84+
```bash
85+
FP=<your-key-fingerprint>
86+
gpg --keyserver hkps://keys.openpgp.org --send-keys $FP
87+
gpg --keyserver hkps://keyserver.ubuntu.com --send-keys $FP
88+
gpg --keyserver hkps://pgp.mit.edu --send-keys $FP
89+
```
90+
91+
Then back up `~/.gnupg/` + the revocation certificate in
92+
`~/.gnupg/openpgp-revocs.d/$FP.rev` to an offline location. **If you
93+
lose the secret key, the next release needs a new key + you lose
94+
key-continuity with prior releases.**
95+
96+
3. **GPG passphrase in settings.xml** — even when the key has no
97+
passphrase, the reactor pom interpolates `${gpg.passphrase}` so an
98+
empty property is required:
99+
100+
```xml
101+
<profiles>
102+
<profile>
103+
<id>gpg-credentials</id>
104+
<activation><activeByDefault>true</activeByDefault></activation>
105+
<properties>
106+
<gpg.passphrase></gpg.passphrase>
107+
<gpg.keyname>YOUR_KEY_FINGERPRINT</gpg.keyname>
108+
</properties>
109+
</profile>
110+
</profiles>
111+
```
112+
113+
For keys WITH a passphrase, drop the value in between the tags. CI-style
114+
`-Dgpg.passphrase=...` on the command line also works but is visible
115+
to process listings.
116+
117+
4. **`groupId` ownership.** `com.metaobjects` is already verified for the
118+
user token from steps 1–3. Verify in the Central Portal UI under
119+
Namespaces if you ever need to re-check.
120+
121+
## Procedure for a new release
122+
123+
### 1. Land all in-scope work on `main`
124+
125+
Confirm `main` is at the tip you want to release from. Run the per-port
126+
test suites you care about. The Java metadata module has 4 known
127+
pre-existing conformance failures in `provider-extension-*` fixtures
128+
(they need provider IDs that aren't registered in the standard test
129+
classpath); these are unrelated to release content and tracked separately.
130+
The actual release deploy uses `-DskipTests` because of them — see step 5.
131+
132+
### 2. Bump versions across the tree
133+
134+
```bash
135+
cd server/java
136+
137+
# Reactor poms — versions:set only touches modules in <modules>.
138+
mvn versions:set -DnewVersion=7.X.Y -DgenerateBackupPoms=false
139+
140+
# Non-reactor poms (integration-tests*, docs, archetype, examples/*) declare
141+
# <parent> refs and need a sed pass:
142+
for f in integration-tests/pom.xml integration-tests-kotlin/pom.xml docs/pom.xml \
143+
archetype/pom.xml examples/pom.xml examples/basic-example/pom.xml \
144+
examples/osgi-example/pom.xml examples/shared-resources/pom.xml \
145+
examples/spring-example/pom.xml; do
146+
[ -f "$f" ] && sed -i 's|<version>PREV-VERSION</version>|<version>7.X.Y</version>|' "$f"
147+
done
148+
149+
# Verify zero stragglers:
150+
grep -rln '<version>PREV-VERSION<' . --include='pom.xml' # should be empty
151+
```
152+
153+
Commit the bump on `main`:
154+
155+
```bash
156+
git add server/java
157+
git commit -m "release(java): bump version to 7.X.Y"
158+
git push origin main
159+
```
160+
161+
### 3. Local smoke build
162+
163+
```bash
164+
cd server/java && mvn install -DskipTests
165+
```
166+
167+
All 14 publishable modules should reach SUCCESS. The build also installs
168+
locally into `~/.m2/repository/com/metaobjects/*/7.X.Y/`.
169+
170+
### 4. Tag the release
171+
172+
```bash
173+
git tag -a v7.X.Y -m "metaobjects Java 7.X.Y — <one-line summary>"
174+
git push origin v7.X.Y
175+
```
176+
177+
### 5. Deploy to Central Portal
178+
179+
```bash
180+
cd server/java
181+
mvn deploy -P release -DperformRelease=true -DskipTests
182+
```
183+
184+
`-DskipTests` is intentional — the 4 pre-existing provider-extension
185+
conformance failures (see step 1) would otherwise block the release. The
186+
test gate ran per-module during development for the actual content of
187+
this release.
188+
189+
What the command does:
190+
191+
- Activates the `release` profile (triggered by `-DperformRelease=true`).
192+
- Includes all 14 reactor modules (no `-pl` exclusions needed since
193+
archetype/examples are out of `<modules>`).
194+
- Generates javadoc + sources jars for each module. **Kotlin modules use
195+
`dokka-maven-plugin` to produce javadoc** (added to each Kotlin pom
196+
during 7.0.0 prep) — `maven-javadoc-plugin` alone scans Java only and
197+
Central rejects deployments with missing javadoc jars.
198+
- Signs every artifact via `maven-gpg-plugin`.
199+
- Stages to the Central Portal via `central-publishing-maven-plugin`.
200+
- Because `autoPublish: true` + `waitUntil: published`, the plugin waits
201+
until artifacts are LIVE on Central before returning.
202+
203+
Wall time: typically 1–3 min for the build + 3–10 min waiting on Central's
204+
validation + publish. **Once `BUILD SUCCESS` prints, the artifacts are
205+
LIVE and irreversible — no manual promotion step.**
206+
207+
### 6. Verify on Central
208+
209+
```bash
210+
curl -s https://repo.maven.apache.org/maven2/com/metaobjects/metaobjects-metadata/maven-metadata.xml \
211+
| grep -E '<latest>|<release>'
212+
# Expected:
213+
# <latest>7.X.Y</latest>
214+
# <release>7.X.Y</release>
215+
216+
curl -sI https://repo.maven.apache.org/maven2/com/metaobjects/metaobjects-metadata/7.X.Y/metaobjects-metadata-7.X.Y.jar | head -1
217+
# Expected: HTTP/2 200
218+
```
219+
220+
### 7. Post-release: bump to next SNAPSHOT
221+
222+
```bash
223+
cd server/java
224+
mvn versions:set -DnewVersion=7.X.Z-SNAPSHOT -DgenerateBackupPoms=false
225+
# Same sed pass for non-reactor poms (step 2):
226+
for f in integration-tests/pom.xml integration-tests-kotlin/pom.xml docs/pom.xml \
227+
archetype/pom.xml examples/pom.xml examples/basic-example/pom.xml \
228+
examples/osgi-example/pom.xml examples/shared-resources/pom.xml \
229+
examples/spring-example/pom.xml; do
230+
[ -f "$f" ] && sed -i 's|<version>7.X.Y</version>|<version>7.X.Z-SNAPSHOT</version>|' "$f"
231+
done
232+
git add server/java
233+
git commit -m "chore(java): bump to 7.X.Z-SNAPSHOT post-7.X.Y"
234+
git push origin main
235+
```
236+
237+
## Lessons from the 7.0.0 publish
238+
239+
These are the actual non-obvious gotchas that surfaced during the first
240+
deploy from the consolidated reactor:
241+
242+
- **`-pl '!examples'` does NOT transitively exclude `examples/*` children
243+
under Maven 3.6.3.** Either list every child explicitly
244+
(`-pl '!examples,!examples/basic-example,!examples/osgi-example,...'`)
245+
or remove the offending modules from the reactor entirely. 7.0.0 went
246+
with the latter — `archetype` and `examples` are no longer in the
247+
reactor's `<modules>` list.
248+
249+
- **Kotlin modules need Dokka for the javadoc jar.** Central's validation
250+
rejects any artifact without a javadoc.jar. `maven-javadoc-plugin` only
251+
scans Java sources, so Kotlin-only modules (`metadata-ktx`,
252+
`codegen-kotlin`, `omdb-ktx`) produce no jar without a Kotlin doc
253+
generator. `dokka-maven-plugin` (bound to the `package` phase via the
254+
`javadocJar` goal) fills the gap. Each of the three Kotlin modules has
255+
this plugin in their pom.
256+
257+
- **`-DskipTests` is needed today.** The Java metadata module has 4
258+
`provider-extension-*` conformance test failures that pre-date the
259+
7.0.0 release (failing on `main` independent of release content). Until
260+
those test fixtures are reconciled, releases skip tests at deploy time.
261+
Per-module test gates still run during development.
262+
263+
- **`autoPublish: true` means no staging review.** Once `mvn deploy`
264+
returns `BUILD SUCCESS`, the artifacts are LIVE on Central and cannot
265+
be deleted. To get a review window before going live, temporarily flip
266+
`autoPublish` to `false` in `server/java/pom.xml`, run the deploy,
267+
manually promote via the Central Portal UI, then revert.
268+
269+
- **Central reads from `repo.maven.apache.org` shortly after publish.**
270+
The plugin's `waitUntil: published` blocks until artifacts are visible
271+
there, so the post-deploy `curl` verification (step 6) returns 200
272+
immediately. If you skip `waitUntil`, you'd need to wait a few minutes
273+
before verifying.
274+
275+
- **Maven Central rejects empty javadoc.jars structurally.** A common
276+
workaround for Kotlin/no-Java modules is to attach an empty
277+
`-javadoc.jar` via `maven-jar-plugin` with `<forceCreation>true</forceCreation>`.
278+
We didn't test whether Central accepts that today — we went with Dokka
279+
for proper docs instead.

server/java/archetype/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
<relativePath>../pom.xml</relativePath>
1111
</parent>
1212

server/java/codegen-base/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>metaobjects-codegen-base</artifactId>

server/java/codegen-kotlin/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<parent>
88
<groupId>com.metaobjects</groupId>
99
<artifactId>metaobjects</artifactId>
10-
<version>7.0.0</version>
10+
<version>7.0.1-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>metaobjects-codegen-kotlin</artifactId>

server/java/codegen-mustache/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>metaobjects-codegen-mustache</artifactId>

server/java/codegen-plantuml/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>metaobjects-codegen-plantuml</artifactId>

server/java/codegen-spring/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>metaobjects-codegen-spring</artifactId>

server/java/core-spring/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>com.metaobjects</groupId>
88
<artifactId>metaobjects</artifactId>
9-
<version>7.0.0</version>
9+
<version>7.0.1-SNAPSHOT</version>
1010
</parent>
1111

1212
<artifactId>metaobjects-core-spring</artifactId>

server/java/docs/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<artifactId>metaobjects</artifactId>
1010
<groupId>com.metaobjects</groupId>
11-
<version>7.0.0</version>
11+
<version>7.0.1-SNAPSHOT</version>
1212
</parent>
1313

1414
<artifactId>metaobjects-docs</artifactId>

0 commit comments

Comments
 (0)