Skip to content

Publish to Maven Central from the release workflow - #105

Merged
ctgnz merged 1 commit into
masterfrom
feat/103-maven-central
Sep 25, 2026
Merged

ctgnz merged 1 commit into
masterfrom
feat/103-maven-central

Conversation

@ctgnz

@ctgnz ctgnz commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Closes #103.

jmsfx has never published anywhere — a tag cut a GitHub release with jars attached, so nobody could depend on jmsfx-core or a generated library without building the repository themselves. Since the generated libraries are the things actually consumed, that was the gap worth closing, and #102 makes it a hard prerequisite rather than a nicety.

Follows foxglove, which already publishes under the same io.github.ctgnz namespace, so nothing new needed verifying.

maven-gpg-plugin signs at verify, loopback pinentry so CI signs unattended
central-publishing-maven-plugin uploads to the Portal, autoPublish: false
distributionManagement deleted, not corrected — it pointed at the retired s01.oss.sonatype.org, and the Portal plugin uploads directly
setup-java writes the central server and imports the signing key
publish step before Create release

Publishing before the release matters: a failed deploy must not leave a release announcing a version that never reached Central. foxglove learned that the other way round on 0.9.5.

Only the parent, jmsfx-core and jmsfx-standard go to Central. The other four are excluded by artifactId — the applications are delivered as bundles and a deployment, and the generator only becomes publishable when #102 gives library repositories something to depend on. The parent is the easy one to forget, and resolution breaks for every consumer without it.

The release profile had never been run, and did not work

This is the part worth reading. Three things were broken and invisible because nothing ever exercised them:

  • Four poms still pointed the javadoc plugin at nz.co.ctg.jmsfx — the package namespace from before the rename to io.github.ctgnz. jmsfx-server had been corrected; core, standard, creator and editor had not, so javadoc failed outright with No source files for package. Their excludePackageNames named a .model package that no module has.
  • A broken {@link}. IdentificationSymbol referenced GraphicType#FREE_CANVAS without importing that type — my own, written in FREE_CANVAS elements still draw a frame in a point-geometry symbol set #91 — which javadoc rejects as an unresolved reference. Qualified rather than imported, so no unused import is added.
  • doclint is now all,-missing. It keeps the syntax, html and reference checking that caught that link, and drops missing, which reported a hundred undocumented getters and buried the one real error among them.

Central requires a javadoc jar, so none of this was optional.

How far this is verified

Without credentials the upload itself cannot be exercised, but everything up to it can:

  • A full -Prelease build now produces javadoc and sources jars for every module, where before it failed on the first.
  • The plugin's own debug output confirms excludeArtifacts = [jmsfx-generator, jmsfx-creator, jmsfx-editor, jmsfx-server] — the XML shape of a list parameter was the part worth checking rather than assuming.
  • Running it without a central server entry fails with Cannot invoke Server.clone() because "server" is null, which is why setup-java gains server-id — the plugin resolves that server before it does anything else.
  • mvn verify green on the ordinary build.

The first real upload is the 2.0.0 tag. autoPublish: false is what makes that safe: a bad staging is dropped on the Portal rather than published.

Needs doing by hand

Repository secrets, as foxglove has them: CENTRAL_USERNAME, CENTRAL_PASSWORD, GPG_PRIVATE_KEY, GPG_PASSPHRASE. The workflow will fail at the publish step without them, on a tag only.

Rebased onto #104, so the checkout@v7 bumps are already in.

🤖 Generated with Claude Code

jmsfx has never published anywhere. A tag cut a GitHub release with jars
attached, so nobody could depend on jmsfx-core or a generated library without
building the repository themselves - which, since the generated libraries are the
things actually consumed, was the gap worth closing.

Following foxglove, which already publishes under the same io.github.ctgnz
namespace, so nothing new needed verifying:

- maven-gpg-plugin signs at verify, with loopback pinentry so CI can sign
  unattended. Central requires signed artifacts.
- central-publishing-maven-plugin uploads to the Portal. autoPublish stays false:
  a tag stages a validated deployment and publishing is a deliberate click, so a
  bad staging can be dropped rather than superseded.
- distributionManagement is deleted rather than corrected. It pointed at
  s01.oss.sonatype.org, retired mid-2025, and the Portal plugin uploads directly
  rather than deploying to a staging repository.
- setup-java writes the 'central' server and imports the signing key. The plugin
  resolves that server before anything else, so without it the build fails on a
  null server rather than on a rejected upload - confirmed by running it.
- The publish goes before the release is created, so a failed deploy cannot leave
  a release announcing a version that never reached Central. foxglove learned
  that the other way round on 0.9.5.

Only the parent, jmsfx-core and jmsfx-standard go to Central - the API a consumer
compiles against and the library it renders with. The other four are excluded by
artifactId; the parent is easy to forget and resolution breaks without it.

The release profile had never actually been run, and it did not work:

- Four poms still pointed the javadoc plugin at nz.co.ctg.jmsfx, the package
  namespace from before the rename. jmsfx-server had been corrected and the rest
  had not, so javadoc failed with "No source files for package". Their
  excludePackageNames named a .model package that no module has.
- IdentificationSymbol carried a {@link GraphicType#FREE_CANVAS} to a type that
  file never imports - my own, from #91 - which javadoc rejects as an unresolved
  reference. Qualified rather than importing, so nothing unused is added.
- doclint is set to all,-missing. It keeps the checking that found that broken
  link and drops "no comment", which reported a hundred undocumented getters and
  buried the one real error among them.

Verified as far as it can be without credentials: a full -Prelease build produces
javadoc and sources jars for every module, and the plugin's own debug output
confirms excludeArtifacts parsed to exactly the four intended artifactIds, which
was the part of the XML shape worth checking rather than assuming. The upload
itself is tag-only and first runs for real at 2.0.0 - which autoPublish: false is
what makes safe.

Still needs doing by hand: CENTRAL_USERNAME, CENTRAL_PASSWORD, GPG_PRIVATE_KEY
and GPG_PASSPHRASE as repository secrets, as foxglove has them.

Closes #103

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ctgnz
ctgnz merged commit 167a615 into master Sep 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish jmsfx to Maven Central from the release workflow

1 participant