Skip to content

Adds CI and the tag-push release workflow for Maven Central - #3

Merged
johnnyt merged 1 commit into
mainfrom
uxjv-19l-ci-and-release-workflow
Oct 21, 2026
Merged

johnnyt merged 1 commit into
mainfrom
uxjv-19l-ci-and-release-workflow

Conversation

@johnnyt

@johnnyt johnnyt commented Oct 21, 2026

Copy link
Copy Markdown
Member

Refs: uxjv-19l

What this adds

  • .github/workflows/ci.yml: on pushes to main, pull requests and manual dispatch, with contents: read. The gate job runs mise run gate (read from .claude/wurk.json gate.full) on the JDK and Maven mise.toml pins, then checks the checkout is clean. The tests job runs mvn test on Temurin 17, 21 and 25.
  • .github/workflows/release.yml: on a v*.*.* tag push only. Its header states what each step checks, what a failure leaves behind, which re-run can go green, and the remedies.
  • pom.xml: a release profile (enforcer checksum check, maven-gpg-plugin 3.2.8 with the Bouncy Castle signer, central-publishing-maven-plugin 0.12.0) and the two plugin versions pinned in pluginManagement. The gate never activates the profile.
  • changelog.d/README.md: the fragment rule and format.
  • CLAUDE.md: the sentences that called CI and the release workflow future now state what the tree holds. The publish row already named .github/workflows/release.yml.

No changelog fragment: CI, the release workflow and docs take none under the rule this PR writes down.

The Java 17 and 21 test legs

The Error Prone release pom.xml pins is compiled for Java 21 (class file major 65), so it cannot run on a Java 17 compiler. Each tests leg therefore compiles on the mise.toml JDK (with Error Prone, at --release 17) and runs the tests on the leg's JDK through Surefire's jvm parameter (-Djvm=<leg JDK>/bin/java). The step then fails unless every Surefire report records the leg's java.specification.version, so a run that fell back to the build JDK cannot pass. The format check and the coverage check run in the verify phase, which only the gate job reaches. This keeps one compiler configuration and puts the gate's bytecode under every test JDK, rather than a second profile that turns Error Prone off on two legs.

The release workflow

  • verify (contents: read, reads no secret): the tagged commit is on the default branch; the tag is v plus the project's own <version> in pom.xml, not a snapshot; Maven Central does not list that version; the full gate; a clean checkout; then mvn -B -ntp -DskipTests clean package, and the SHA-256 of the main, sources and javadoc jars into SHA256SUMS, uploaded with the jars as one artifact. The SHA-256 of SHA256SUMS is the job's output.
  • "Maven Central lists the version" is the version's POM file answering 200 at repo1.maven.org (404: not listed; anything else stops). repo1 is the repository Maven resolves from; the search pages at central.sonatype.com can lag it.
  • publish (needs: verify, contents: read): re-checks the version and the listing, downloads the artifact and matches it to verify's sums, installs only java and maven through mise (install_args, MISE_EXEC_AUTO_INSTALL=false), writes a settings.xml holding ${env.NAME} references only, then runs one mvn -P release -DskipTests clean deploy. In that invocation the enforcer's requireFileChecksum refuses, in the verify phase and before gpg:sign, unless each rebuilt jar's SHA-256 equals verify's; the signer signs the jars and the POM; the Central Portal plugin uploads with autoPublish true and waitUntil published (up to 3600 s). The last step prints the central.sonatype.com and repo1 addresses.
  • MAVEN_CENTRAL_USERNAME, MAVEN_CENTRAL_PASSWORD, MAVEN_GPG_PRIVATE_KEY and MAVEN_GPG_PASSPHRASE are read by secrets expressions only in the env of that deploy step.
  • Re-run path: if publish failed after an upload that the Portal went on to publish, "Re-run failed jobs" re-runs publish alone; it sees the version listed, downloads the three listed jars and passes when their SHA-256 values equal verify's, without building, signing or uploading. Re-running every job re-runs verify, which refuses a listed version.

Checks run for this PR

  • mise run gate green on the head (Temurin 25.0.4, Maven 3.9.16).
  • Two mvn -DskipTests clean package runs gave byte-identical jars.
  • With signing skipped (-Dgpg.skip=true, no deploy): -P release with no sums refused ("Checksum unspecified"); with a wrong javadoc sum it refused with the javadoc message; with the sums from the plain package build it passed, so the release-profile build reproduces the plain build. The log order was the checksum check, then gpg:sign.
  • buildplan:list for the deploy task under -P release: the deploy phase runs central-publishing-maven-plugin:publish (injected), not maven-deploy-plugin.
  • Surefire -Djvm pointed at a Temurin 21 install: the tests ran and the report recorded java.specification.version 21.
  • actionlint 1.7.12: clean.
  • Nothing was signed, deployed or uploaded, and no secret was read or set.

Actions, pinned to full commit SHAs

Action Version SHA
actions/checkout v4.4.0 11d5960a326750d5838078e36cf38b85af677262
actions/setup-java v6.0.1 de7274f081f381c8f8158605e0321c36c376e2e6
actions/upload-artifact v7.0.2 cf430e030ddbb5b0abf93d22962f4752f3646cd9
actions/download-artifact v8.0.1 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
jdx/mise-action v4.3.0 c2a87611a18de5b3828c5652fe268e992400cb5c

Provenance

Decided by the conductor under a standing consent, 2026-10-21: compiling every test leg on the gate JDK and moving only the test JVM (rather than a profile without Error Prone); the checksum check as an enforcer rule inside the signing invocation; the repo1 POM read as the listing check; the publish-job re-run path that compares the listed jars; the plugin and action versions above. actionlint stays out of mise.toml: the gate does not run it, and the publish job's mise installs only the JDK and Maven.

CI runs the full gate on the mise.toml JDK and the tests on Temurin
17, 21 and 25. The Error Prone release in pom.xml runs only on Java
21 or later, so every leg compiles on the gate JDK and Surefire forks
the test JVM from the leg's JDK; each report is checked for that
Java version.

The release workflow publishes on a version tag: a verify job checks
the branch, the version and Maven Central, runs the gate and records
the SHA-256 of the three release jars; a publish job, the only one
that reads the four publish secrets, rebuilds the jars under a new
release profile that refuses unless the sums match, signs them with
the Bouncy Castle signer and deploys through the Central Portal
plugin. A re-run of the publish job alone after a published upload
compares the listed jars and goes green.

changelog.d/README.md states the fragment rule, and CLAUDE.md now
describes the workflows on main.

Refs: uxjv-19l
@johnnyt
johnnyt merged commit 75b625d into main Oct 21, 2026
4 checks passed
@johnnyt
johnnyt deleted the uxjv-19l-ci-and-release-workflow branch October 21, 2026 21:27
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.

1 participant