Skip to content

[CI] Release workflow: publish to Maven Central from GitHub Actions - #33

Merged
PetrHeinz merged 3 commits into
mainfrom
claude/release-workflow
Sep 25, 2026
Merged

PetrHeinz merged 3 commits into
mainfrom
claude/release-workflow

Conversation

@PetrHeinz

@PetrHeinz PetrHeinz commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Adds .github/workflows/release.yml, the counterpart of the Release workflows in logtail-js and logtail-python: dispatch it from main with patch or minor, approve the maven-central environment prompt, and it bumps the version in pom.xml and the two example projects, builds, commits vX.Y.Z, tags, pushes, deploys the signed bundle to the Central Portal, waits until the Portal reports it published and creates a GitHub release with generated notes. retry finishes a release that failed after the version commit was pushed. The header comment in the file is the runbook.

Maven Central has no trusted publishing, so unlike npm and PyPI the publish job reads real credentials: the Portal user token and the signing key live as secrets on the maven-central environment, and the job restores nothing from the Actions cache. Two plugin bumps in the pom make the runner flow work and are worth having anyway:

  • maven-gpg-plugin 3.0.1 → 3.2.8, which reads the passphrase from the MAVEN_GPG_PASSPHRASE environment variable that actions/setup-java v6 hands it. The gpg.passphrase property from the manual runbook still works, with a deprecation warning.
  • central-publishing-maven-plugin 0.6.0 → 0.11.0, with waitUntil: published in its configuration: mvn deploy now returns only once the Portal has published the deployment (or after 30 minutes), so the workflow, and a manual release, get a real success signal instead of "go watch the Deployments page". It also brings ignorePublishedComponents, which is what makes retry safe against Central's immutability: components the Portal already published are left out of the bundle rather than re-uploaded.

The dry run is the part that proves the setup without publishing. It uploads a real deployment with auto-publish off, which the Portal validates like any other (credentials, every signature, the key on a keyserver, javadoc and sources jars, pom metadata) and then stops at VALIDATED; the workflow reads the deployment id from the plugin output and drops it through the Publisher API's DELETE /api/v1/publisher/deployment/<id>. Every push that touches the workflow file runs this dry run on its own branch, so this PR's checks are the rehearsal for the change it makes, before it reaches main. A dry run can also be dispatched from any branch.

Rehearsed locally with a throwaway key on JDK 21 (the JDK the last manual release was built with): the release profile with both plugin bumps produces the same bundle layout as 0.3.6 on repo1, signs with the passphrase from the environment, and -DautoPublish=false stops at validated even though the pom asks for published (the plugin downgrades it with a warning, by design). The bump step was exercised on clones at an untagged HEAD and at v0.3.6 for patch, minor, retry and dry run.

What the first push on this branch taught: its dry run published 0.3.7 for real. The pom had <autoPublish>true</autoPublish> as a literal in the plugin configuration, and a literal in a plugin configuration wins over a -D flag, so -DautoPublish=false was ignored and the Portal auto-published a valid, signed build of main as it was (functionally 0.3.6, nothing had merged since) with this branch's pom. Central is immutable, so 0.3.7 stays. The second commit here, v0.3.7, is the version commit that run would have made, and its pom.xml is byte-for-byte the pom the Portal published, so the tag v0.3.7 and its GitHub release can be created on it if you want the repo to account for the version; the third commit moves autoPublish into a pom property that the flag can override, and adds a step that reads the effective pom and refuses to upload unless the plugin's autoPublish is false. The dry run on the third push targets 0.3.8 and must end with the deployment dropped.

Environment settings worth checking before the first real release: required reviewers on maven-central (currently off), and the deployment branch policy left unrestricted, because the push-triggered dry runs come from feature branches; the "releases run from main only" check lives in the workflow. Not automated: the dependency snippet in the docs article, which still says 0.3.4, and the Notion runbook.

🤖 Generated with Claude Code

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PetrHeinz and others added 2 commits September 25, 2026 17:04
The first push-triggered dry run on this branch published 0.3.7 to Maven Central instead of stopping at
validated: the <autoPublish>true</autoPublish> literal in the plugin configuration overrode the
-DautoPublish=false flag. This is the version commit that run would have made; the published pom is this
pom.xml at this commit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ploading

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@PetrHeinz
PetrHeinz deployed to maven-central September 25, 2026 15:11 — with GitHub Actions Active
@PetrHeinz
PetrHeinz marked this pull request as ready for review September 25, 2026 15:24
@PetrHeinz
PetrHeinz merged commit 5eef6fd into main Sep 25, 2026
9 checks passed
@PetrHeinz
PetrHeinz deleted the claude/release-workflow branch September 25, 2026 15:24

This branch was successfully deployed

1 active deployment
maven-central — d13d529f Deployed Sep 25, 2026 by PetrHeinz via Publish #2
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