|
| 1 | +# Releasing Java Does USB |
| 2 | + |
| 3 | +This document describes how a new version of the library is released to Maven Central, and how |
| 4 | +version numbers flow through the repository afterwards. |
| 5 | + |
| 6 | +## Versioning scheme |
| 7 | + |
| 8 | +- The library follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`). |
| 9 | +- On the `main` branch, `java-does-usb/pom.xml` always carries the *next*, unreleased version |
| 10 | + with a `-SNAPSHOT` suffix (e.g. `1.2.2-SNAPSHOT`). This makes it obvious that a build from `main` |
| 11 | + is a development build, not something published to Central. |
| 12 | +- `README.md` and the example projects under `examples/` intentionally do **not** track this |
| 13 | + SNAPSHOT. They pin the latest *released* version, because they double as user-facing |
| 14 | + documentation: a user reading the README or copying an example's `pom.xml`/`build.gradle.kts` |
| 15 | + should see the version they can actually `mvn install` from Central today. |
| 16 | +- Continuous integration overrides the pinned example version at build time so it still compiles |
| 17 | + the examples against `main`'s HEAD (see "How CI stays honest" below). No file needs to be edited |
| 18 | + for this to work. |
| 19 | + |
| 20 | +## Release checklist |
| 21 | + |
| 22 | +1. **Drop the `-SNAPSHOT` suffix.** |
| 23 | + In `java-does-usb/pom.xml`, set `<version>` to the release version, e.g.: |
| 24 | + ```bash |
| 25 | + cd java-does-usb |
| 26 | + ./mvnw versions:set -DnewVersion=1.2.2 -DgenerateBackupPoms=false |
| 27 | + ``` |
| 28 | + |
| 29 | +2. **Update the version everywhere it's pinned for users.** This means: |
| 30 | + - `README.md` — the Maven (`<version>...</version>`) and Gradle (`version: '...'`) snippets |
| 31 | + under "Getting Started", and the version history table if you're adding an entry. |
| 32 | + - Every example's dependency on `java-does-usb`, pinned via a single property so it's one edit |
| 33 | + per file (`java-does-usb.version` in the Maven examples, `javaDoesUsbVersion` in the Gradle |
| 34 | + one): |
| 35 | + - `examples/enumerate/pom.xml` |
| 36 | + - `examples/bulk_transfer/pom.xml` |
| 37 | + - `examples/monitor/pom.xml` |
| 38 | + - `examples/monitor_kotlin/pom.xml` |
| 39 | + - `examples/stm_dfu/pom.xml` |
| 40 | + - `examples/epaper_display/pom.xml` |
| 41 | + - `examples/enumerate_native/pom.xml` |
| 42 | + - `examples/monitor_native/pom.xml` |
| 43 | + - `examples/enumerate_kotlin/build.gradle.kts` |
| 44 | + - The example's *own* project version (its `<version>` / `version = "..."`, separate from the |
| 45 | + `java-does-usb.version`/`javaDoesUsbVersion` property), which by convention tracks the library |
| 46 | + release it was last verified against, for `enumerate`, `bulk_transfer`, `monitor`, |
| 47 | + `monitor_kotlin`, `stm_dfu`, `epaper_display`, and `enumerate_kotlin`. (`enumerate_native` and |
| 48 | + `monitor_native` version themselves independently as `1.0-SNAPSHOT` and don't need this.) |
| 49 | + - The sample console output hardcoded in each example's own `README.md` (e.g. build log lines |
| 50 | + like `[INFO] Building enumerate 1.2.1` or jar filenames like `stm_dfu-1.2.1.jar`), which |
| 51 | + embeds the example's own project version from the point above. |
| 52 | + |
| 53 | + A simple search for the previous version number across `README.md` and `examples/` will locate |
| 54 | + every occurrence listed above. |
| 55 | + |
| 56 | +3. **Commit, tag, and publish.** |
| 57 | + ```bash |
| 58 | + git add -A |
| 59 | + git commit -m "Release 1.2.2" |
| 60 | + git tag v1.2.2 |
| 61 | + git push origin main v1.2.2 |
| 62 | + cd java-does-usb |
| 63 | + ./mvnw clean deploy -Prelease # or whatever profile/flags drive maven-gpg-plugin + central-publishing-maven-plugin |
| 64 | + ``` |
| 65 | + (Adjust to however signing/publishing is actually invoked locally today — this step is manual |
| 66 | + and not run by CI.) |
| 67 | + |
| 68 | +4. **Prepare `main` for the next development iteration.** |
| 69 | + ```bash |
| 70 | + cd java-does-usb |
| 71 | + ./mvnw versions:set -DnewVersion=1.2.3-SNAPSHOT -DgenerateBackupPoms=false |
| 72 | + git add pom.xml |
| 73 | + git commit -m "Prepare for next development iteration" |
| 74 | + git push origin main |
| 75 | + ``` |
| 76 | + Deliberately do **not** touch `README.md` or the examples in this step — they should keep |
| 77 | + pointing at the release just made (1.2.2) until the *next* release checklist run. |
| 78 | + |
| 79 | +## How CI stays honest |
| 80 | + |
| 81 | +Because the examples pin the released version, a naive CI setup would silently compile them |
| 82 | +against whatever is available on Maven Central instead of the code actually being tested — i.e. |
| 83 | +after step 4 above, `main` might contain a breaking change that no CI run would ever catch until |
| 84 | +the next release. |
| 85 | + |
| 86 | +To prevent that, `.github/workflows/continuous-integration.yaml`: |
| 87 | + |
| 88 | +1. Builds and `install`s the library from the checked-out `pom.xml` (whatever version — released |
| 89 | + or `-SNAPSHOT` — is on HEAD) into the local Maven repository. |
| 90 | +2. Reads that exact version back out with `mvn help:evaluate -Dexpression=project.version`. |
| 91 | +3. Passes it to each example build as an override: |
| 92 | + - Maven examples: `-Djava-does-usb.version=<version>` |
| 93 | + - The Gradle example (`enumerate_kotlin`): `-PjavaDoesUsbVersion=<version>` |
| 94 | + |
| 95 | +This means CI always compiles every example against the exact commit under test, while the |
| 96 | +committed example files keep showing users the last real release. |
| 97 | + |
| 98 | +If you add a new example, give its `java-does-usb` dependency the same treatment: introduce a |
| 99 | +`java-does-usb.version` property (Maven) or an overridable `javaDoesUsbVersion` val (Gradle) |
| 100 | +defaulting to the current released version, add a CI step following the existing pattern, and add |
| 101 | +it to the list in step 2 of the release checklist above. |
0 commit comments