This document describes how a new version of the library is released to Maven Central, and how version numbers flow through the repository afterwards.
- The library follows Semantic Versioning (
MAJOR.MINOR.PATCH). - On the
mainbranch,java-does-usb/pom.xmlalways carries the next, unreleased version with a-SNAPSHOTsuffix (e.g.1.2.2-SNAPSHOT). This makes it obvious that a build frommainis a development build, not something published to Central. README.mdand the example projects underexamples/intentionally do not track this SNAPSHOT. They pin the latest released version, because they double as user-facing documentation: a user reading the README or copying an example'spom.xml/build.gradle.ktsshould see the version they can actuallymvn installfrom Central today.- Continuous integration overrides the pinned example version at build time so it still compiles
the examples against
main's HEAD (see "How CI stays honest" below). No file needs to be edited for this to work.
-
Drop the
-SNAPSHOTsuffix. Injava-does-usb/pom.xml, set<version>to the release version, e.g.:cd java-does-usb ./mvnw versions:set -DnewVersion=1.3.1 -DgenerateBackupPoms=false -
Update the version everywhere it's pinned for users. This means:
README.md— the Maven (<version>...</version>) and Gradle (version: '...') snippets under "Getting Started", and the version history table if you're adding an entry.- Every example's dependency on
java-does-usb, pinned via a single property so it's one edit per file (java-does-usb.versionin the Maven examples,javaDoesUsbVersionin the Gradle one):examples/enumerate/pom.xmlexamples/bulk_transfer/pom.xmlexamples/monitor/pom.xmlexamples/monitor_kotlin/pom.xmlexamples/stm_dfu/pom.xmlexamples/epaper_display/pom.xmlexamples/enumerate_native/pom.xmlexamples/monitor_native/pom.xmlexamples/enumerate_kotlin/build.gradle.kts
- The example's own project version (its
<version>/version = "...", separate from thejava-does-usb.version/javaDoesUsbVersionproperty), which by convention tracks the library release it was last verified against, forenumerate,bulk_transfer,monitor,monitor_kotlin,stm_dfu,epaper_display, andenumerate_kotlin. (enumerate_nativeandmonitor_nativeversion themselves independently as1.0-SNAPSHOTand don't need this.) - The sample console output hardcoded in each example's own
README.md(e.g. build log lines like[INFO] Building enumerate 1.2.1or jar filenames likestm_dfu-1.2.1.jar), which embeds the example's own project version from the point above.
A simple search for the previous version number across
README.mdandexamples/will locate every occurrence listed above. -
Commit, tag, and publish.
git add -A git commit -m "Release 1.2.2" git tag v1.2.2 git push origin main v1.2.2 cd java-does-usb ./mvnw clean install # GPG passphrase from password store ./mvnw clean deploy
-
Prepare
mainfor the next development iteration.cd java-does-usb ./mvnw versions:set -DnewVersion=1.2.3-SNAPSHOT -DgenerateBackupPoms=false git add pom.xml git commit -m "Prepare for next development iteration" git push origin main
Deliberately do not touch
README.mdor the examples in this step — they should keep pointing at the release just made (1.2.2) until the next release checklist run.
Because the examples pin the released version, a naive CI setup would silently compile them
against whatever is available on Maven Central instead of the code actually being tested — i.e.
after step 4 above, main might contain a breaking change that no CI run would ever catch until
the next release.
To prevent that, .github/workflows/continuous-integration.yaml:
- Builds and
installs the library from the checked-outpom.xml(whatever version — released or-SNAPSHOT— is on HEAD) into the local Maven repository. - Reads that exact version back out with
mvn help:evaluate -Dexpression=project.version. - Passes it to each example build as an override:
- Maven examples:
-Djava-does-usb.version=<version> - The Gradle example (
enumerate_kotlin):-PjavaDoesUsbVersion=<version>
- Maven examples:
This means CI always compiles every example against the exact commit under test, while the committed example files keep showing users the last real release.
If you add a new example, give its java-does-usb dependency the same treatment: introduce a
java-does-usb.version property (Maven) or an overridable javaDoesUsbVersion val (Gradle)
defaulting to the current released version, add a CI step following the existing pattern, and add
it to the list in step 2 of the release checklist above.