javachanges GitHub Actions Release Flow
1. Overview
This repository now includes a GitHub Actions release pipeline built on javachanges itself.
This page is repository-specific. For broader GitHub Actions integration patterns, see GitHub Actions Usage Guide.
The intended flow is:
- feature branches merge into
main maincontains one or more.changesets/*.mdfiles- GitHub Actions generates or updates a release PR
- the release PR is merged
- GitHub Actions can publish snapshots from
snapshot - GitHub Actions tags the release, publishes to Maven Central, and creates a GitHub Release
1.1 Workflow graph
2. Workflows
The repository contains four workflows:
| File | Purpose |
|---|---|
.github/workflows/ci.yml | Regular CI for Java 8 build and publish-profile verification |
.github/workflows/release-plan.yml | Scans pending changesets on main and generates a release PR |
.github/workflows/publish-snapshot.yml | Publishes the current snapshot branch build to the configured snapshot repository |
.github/workflows/publish-release.yml | Publishes after the release PR is merged |
3. Release PR workflow
The core command in release-plan.yml is:
mvn -B -DskipTests exec:java -Dexec.args="github-release-plan --directory $GITHUB_WORKSPACE --write-plan-files false --execute true"It:
| Action | Meaning |
|---|---|
Reads .changesets/*.md | Collects pending release intent |
| Computes release versions | Produces releaseVersion and nextSnapshotVersion |
| Applies the plan | Updates <revision> and CHANGELOG.md without committing generated plan files |
| Deletes consumed changesets | Prevents duplicate releases |
The workflow then commits those changes to:
changeset-release/mainand creates or updates a pull request.
4. Snapshot publish workflow
publish-snapshot.yml runs on pushes to snapshot and on manual workflow_dispatch.
It:
- validates snapshot repository variables and credentials
- derives a stable snapshot build stamp for the workflow run
- runs
javachanges preflight --snapshot - runs
javachanges publish --snapshot --execute true
The workflow publishes a unique snapshot revision such as:
1.3.1-20260420.154500.abc1234-SNAPSHOTIn this repository, the workflow explicitly passes a build stamp based on:
<github.run_id>.<github.run_attempt>.<git short sha>so reruns remain distinguishable even when they target the same root snapshot line on the snapshot branch.
Configure these GitHub Actions secrets for snapshot publishing:
| Type | Name | Required |
|---|---|---|
| Secret | MAVEN_CENTRAL_USERNAME | Yes |
| Secret | MAVEN_CENTRAL_PASSWORD | Yes |
| Secret | MAVEN_GPG_PRIVATE_KEY | Yes |
| Secret | MAVEN_GPG_PASSPHRASE | Yes |
The snapshot workflow in this repository now uses central-publishing-maven-plugin with a -SNAPSHOT revision and the same Central Portal token pair used for releases, instead of publishing through distributionManagement with a separate maven-snapshots server id.
After the workflow succeeds, the primary snapshot verification addresses are:
https://central.sonatype.com/repository/maven-snapshots/https://central.sonatype.com/repository/maven-snapshots/io/github/sonofmagic/javachanges/<resolved-snapshot-version>/maven-metadata.xmlhttps://central.sonatype.com/repository/maven-snapshots/io/github/sonofmagic/javachanges/<resolved-snapshot-version>/javachanges-<timestamped-version>.jar
The repository root itself is not directly browseable for hosted snapshots, so verification should rely on metadata URLs, concrete artifact URLs, or a real Maven/Gradle resolve.
5. Release publish workflow
publish-release.yml runs in two modes:
- automatically after a merged release PR
- manually through
workflow_dispatchwhen you need to retry publishing for an existing merged release commit
Automatic mode only runs when all of these are true:
| Condition | Meaning |
|---|---|
| the PR was merged | not just closed |
the base branch is main | only the mainline is released |
the head branch is changeset-release/main | only release PRs trigger publishing |
It then:
- checks out the merged release commit
- runs
github-tag-from-plan --execute true - runs
github-release-from-planto generatetarget/release-notes.mdand exportreleaseVersion - publishes to Maven Central with the
central-publishprofile - runs
github-release-from-plan --execute trueto create or update the GitHub Release
5.1 Release retry behavior
Publish Release is designed to be safe to rerun for the same merged release commit.
If a previous run created the release tag but failed before Maven Central publishing or GitHub Release creation, rerun Publish Release with the same merged release commit SHA. github-release-publish-state continues when no GitHub Release exists and the remote tag points at that commit. github-tag-from-plan then treats the existing tag as a recoverable state instead of trying to recreate it.
If the remote tag exists but points at a different commit, the workflow fails before publishing. In that case, inspect the tag and rerun the workflow for the tagged commit, or move the tag only after confirming the previous tag target was wrong.
6. Required repository secrets
Configure these in Settings > Secrets and variables > Actions:
| Secret | Purpose |
|---|---|
MAVEN_CENTRAL_USERNAME | Sonatype Central Portal token username |
MAVEN_CENTRAL_PASSWORD | Sonatype Central Portal token password |
MAVEN_GPG_PRIVATE_KEY | ASCII-armored GPG private key |
MAVEN_GPG_PASSPHRASE | GPG private key passphrase |
publish-release.yml validates these secrets before it prepares Java, Maven settings, or GPG. If any secret is missing, the workflow stops immediately with a direct error that names the missing secret.
After actions/setup-java imports the private key, both publishing workflows now run the javachanges ensure-gpg-public-key command. That step:
- extracts the imported signing key fingerprint
- attempts to upload the public key to
hkps://keyserver.ubuntu.comandhkps://keys.openpgp.org - waits until the fingerprint becomes discoverable from at least one supported keyserver
This prevents Maven Central from failing later with an error like Invalid signature for file ... Could not find a public key by the key fingerprint.
For the failed run at Actions > Publish Release, the practical recovery path is:
- add the missing secrets
- rerun the failed workflow or failed job
- if the previous failure mentioned an undiscoverable GPG key fingerprint, rerun after this repository change so the workflow can publish and verify the public key before
deploy - confirm the rerun reaches the
Publish to Maven Centralstep
7. Recommended usage
Typical development flow:
- create a branch
- change code
- add a changeset
- open a PR
- merge into
main
Example:
mvn -q -DskipTests compile exec:java -Dexec.args="add --directory $PWD --summary 'add GitHub Actions release automation' --release minor"That command writes a changeset file in the official package-map format, for example:
```md
---
"javachanges": minor
---
add GitHub Actions release automation
```8. Versioning model
To support “merge release PR first, publish the real release afterwards,” this repository now uses:
<version>${revision}</version>and maintains development state with:
<revision>1.0.0-SNAPSHOT</revision>That means:
| Stage | Version |
|---|---|
| Published version | Derived with manifest-field --fresh true, for example 1.0.0 |
| Main branch version | Already advanced to the next snapshot, for example 1.0.1-SNAPSHOT |
The publish workflow uses:
-Drevision=<releaseVersion>so it publishes the real release version instead of the current snapshot revision on main.
The snapshot workflow uses:
-Drevision=<baseVersion>-<snapshotBuildStamp>-SNAPSHOTso repeated snapshot publishes do not overwrite one another under the same visible revision line.
In this repository, the intended developer path is:
- merge release work into
main - merge work that should produce a published snapshot into
snapshot - let
publish-snapshot.ymlpublish from thesnapshotbranch head
9. Manual triggers
If you need to rerun one of the workflows manually:
| Workflow | Supports workflow_dispatch |
|---|---|
Release Plan | Yes |
Publish Snapshot | Yes |
Publish Release | Yes, with release_commit_sha set to the merged release commit |
If a merged release PR already triggered a failed Publish Release run, you usually do not need a new release PR. Trigger Publish Release manually and pass the original merged release commit SHA through release_commit_sha.
10. Local validation
Before relying on the automation, you can validate locally:
mvn -B verify
mvn -B -Pcentral-publish -Dgpg.skip=true verify
mvn -B -DskipTests compile exec:java -Dexec.args="status --directory $PWD"
mvn -B -DskipTests compile exec:java -Dexec.args="preflight --directory $PWD --snapshot --snapshot-build-stamp local.dev.001"11. Summary
The standard release path for this repository is now:
| Stage | Entry point |
|---|---|
| Regular validation | CI workflow |
| Snapshot publishing | Publish Snapshot workflow |
| Release PR generation | Release Plan workflow |
| Real publishing | Publish Release workflow |
For reusable workflow patterns outside this repository, continue with GitHub Actions Usage Guide.