Releasing¶
How a version of JODConverter is released. The steps need write access to the repository, the Maven Central
credentials and the signing key, which live in the repository secrets; the rest is done by the release workflow.
Before the release¶
- Labels. Every pull request merged and every issue closed since the last tag has a label (
enhancement,bug,documentation,dependencies): the release notes that GitHub generates are grouped by label (.github/release.yml). - Release notes page. Write
docs/release-notes/release-notes-X.Y.Z.mdand link it fromdocs/release-notes/index.mdand the navigation inzensical.toml. Every version, a patch release too, has its migration guidedocs/migration-guides/migration-guide-X.Y.Z.md, linked the same way: what users have to check or change, if anything. - CHANGELOG.md. Add the
X.Y.Zblock, one line per pull request with its number, from:gh pr list --state merged --base develop --search "merged:>YYYY-MM-DD" --json number,title --jq '.[] | "- \(.title) (#\(.number))"' - Version. Set the version everywhere at once:
The task writes
./gradlew setVersion -PnewVersion=X.Y.Zversioningradle.propertiesand, for a release version, replaces the previous released version in the pages of the documentation that show dependency coordinates. - Full build and integration tests, locally. The continuous integration runs them on Linux, Windows and macOS,
but the two last ones do not block a merge; a release deserves a run on the release machine too:
./gradlew clean build integrationTest - Release commit. On a
release/X.Y.Zbranch, commit with the messageRelease X.Y.Zand open its pull request todevelop, which only takes pull requests. Once it is merged, open the pull request fromdeveloptomaster, let the checks pass, merge it with a merge commit.
The release¶
- Tag. On
master, after the merge:Thegit checkout master && git pull && git tag -a vX.Y.Z -m "Release X.Y.Z" && git push origin vX.Y.Zreleaseworkflow then builds the tag, publishes every module on Maven Central (signed, released automatically once the portal validates them) and creates the GitHub releasevX.Y.Zwith the generated notes and the command line tool archives. Thedeploy-docsworkflow, run by the push tomaster, publishes the documentation of the version with thelatestalias. - Check the release, the artifacts on Maven Central (they appear within a few hours) and the documentation.
- Javadoc. javadoc.io does not publish a new version by itself: on the versions page of
a module, such as https://javadoc.io/versions/org.jodconverter/jodconverter-local, select the new version and
click Upload selected. It then reads the Javadoc jar from Maven Central, and the Javadoc badge follows. Each
published module has its own page;
jodconverter-localis the one the badge and the documentation link to. - Announce on Gitter:
JODConverter X.Y.Z is out! * Release Notes: https://jodconverter.github.io/jodconverter/latest/release-notes/release-notes-X.Y.Z/ * Migration Guide: https://jodconverter.github.io/jodconverter/latest/migration-guides/migration-guide-X.Y.Z/
After the release¶
- Next snapshot. On a branch from
develop:Commit./gradlew setVersion -PnewVersion=X.Y.Z+1-SNAPSHOTPost release X.Y.Zand open its pull request todevelop. - Merge
masterback. The merge commit of the release leavesmasterone commit ahead ofdevelop. It changes no file, but GitHub counts it, and the count grows at each release. On a branch fromdevelop:Open its pull request togit merge --no-ff origin/master -m "Merge master back into develop after the release of X.Y.Z"develop, whose diff is empty, and merge it with a merge commit: a squash would make a new commit thatmasterdoes not know, andmasterwould stay ahead. - Milestone. Close the milestone of the release and create the next one.
Secrets of the release workflow¶
| Secret | Content |
|---|---|
MAVEN_CENTRAL_USERNAME |
The user name of the Maven Central portal token. |
MAVEN_CENTRAL_PASSWORD |
The password of the Maven Central portal token. |
SIGNING_KEY |
The armored private GPG key (gpg --armor --export-secret-keys KEY_ID). |
SIGNING_KEY_ID |
The last 8 characters of the key id. |
SIGNING_PASSWORD |
The passphrase of the key. |
The build workflow uses one more secret, COVERALLS_REPO_TOKEN, the repository token shown on the Coveralls page of
the project, to send the coverage of the Linux job.
The secrets are checked without a release by running the release workflow by hand from the Actions tab (the
"Run workflow" button, on any branch): it builds, signs the publications with the key of the secrets and checks the
Maven Central credentials against the portal, without publishing anything.
The signing key¶
The key must not be expired when the portal validates the signatures. gpg --list-secret-keys --keyid-format long
shows the expiry; gpg --edit-key KEY_ID with the expire command (then save) extends it, for the primary key and,
after key 1, for the subkey. The public key must be known by the key servers the portal queries, with the current
expiry:
gpg --keyserver keyserver.ubuntu.com --send-keys KEY_ID
gpg --keyserver keys.openpgp.org --send-keys KEY_ID
The SIGNING_KEY secret is set without pasting the key anywhere:
gpg --armor --export-secret-keys KEY_ID | gh secret set SIGNING_KEY --repo jodconverter/jodconverter
A release can still be done from a workstation with the same values in ~/.gradle/gradle.properties
(mavenCentralUsername, mavenCentralPassword, signing.keyId, signing.password, signing.secretKeyRingFile) and
./gradlew publishToMavenCentral, then the GitHub release created by hand from the tag.