Skip to content

Commit 62c308d

Browse files
authored
Fix snapshot version naming and trim build hygiene (#1772)
* Make snapshot version names reflect the next planned release. Previously the build appended "-SNAPSHOT" to git-describe output, so all snapshots between releases were named after the *previous* release (e.g. "4.3.0-3-gabcdef0-SNAPSHOT"), the opposite of Maven convention where SNAPSHOTs are previews of the next release. The fix: declare a `nextVersionBump` ("x" / "x.x" / "x.x.x") at the top of build.gradle, and compute the next semver from the most recent release tag plus that bump. Snapshots are then named "<nextVersion>-<shortHash>-SNAPSHOT" (e.g. "5.0.0-23c681a8dc-SNAPSHOT"); including the hash makes each snapshot a distinct, pinnable artifact. Release builds (-Drelease=true) require HEAD to be on a semver tag and the working tree to be clean; the tag is the version (nextVersionBump is ignored on release — the tag is authoritative). nextVersionBump is set to "x" since the next release will be a major one. * Remove dead Ant build and Travis CI config.
1 parent 23c681a commit 62c308d

6 files changed

Lines changed: 123 additions & 136 deletions

File tree

.github/workflows/tests.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ jobs:
2121
name: Java ${{ matrix.Java }} build and test
2222
steps:
2323
- uses: actions/checkout@v3
24+
with:
25+
fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag
2426
- name: Set up java ${{ matrix.Java }}
2527
uses: actions/setup-java@v3
2628
with:
@@ -49,6 +51,8 @@ jobs:
4951
name: Tests that require external APIs
5052
steps:
5153
- uses: actions/checkout@v3
54+
with:
55+
fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag
5256
- name: Set up java 17
5357
uses: actions/setup-java@v3
5458
with:
@@ -72,6 +76,8 @@ jobs:
7276
name: SpotBugs
7377
steps:
7478
- uses: actions/checkout@v3
79+
with:
80+
fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag
7581
- name: Set up java 17
7682
uses: actions/setup-java@v3
7783
with:

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
htsjdk.iws
22
.command_tmp
33
atlassian-ide-plugin.xml
4-
/htsjdk.version.properties
54
/test-output/
65
.DS_Store
76

.travis.yml

Lines changed: 0 additions & 56 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,44 @@ export GPG_TTY=$(tty)
148148

149149
### Version Numbering
150150

151-
The version is derived automatically from git tags using the
152-
[palantir git-version](https://github.com/palantir/gradle-git-version) plugin:
151+
The build computes the version from git state plus a single declaration in
152+
`build.gradle`:
153153

154-
- On a release tag (e.g. `4.3.0`): version is `4.3.0`
155-
- On a commit after a tag: version includes the commit distance and hash
156-
- Without `-Drelease=true`: `-SNAPSHOT` is appended
154+
```groovy
155+
final nextVersionBump = "x" // "x" major, "x.x" minor, "x.x.x" patch
156+
```
157+
158+
`nextVersionBump` declares the *shape* of the next planned release relative to
159+
the most recent semver tag (e.g. `4.3.0`):
160+
161+
| Bump | Most recent tag | Computed next version |
162+
| ------- | --------------- | --------------------- |
163+
| `x` | `4.3.0` | `5.0.0` |
164+
| `x.x` | `4.3.0` | `4.4.0` |
165+
| `x.x.x` | `4.3.0` | `4.3.1` |
166+
167+
What the build actually publishes:
168+
169+
- **Release** (`-Drelease=true`): HEAD must be on a semver-tagged commit; the
170+
tag itself is the version (e.g. `5.0.0`). `nextVersionBump` is ignored on
171+
release — the tag is authoritative.
172+
- **Snapshot** (default): `<computedNextVersion>-<shortHash>-SNAPSHOT`
173+
(e.g. `5.0.0-23c681a-SNAPSHOT`).
174+
175+
The short hash in snapshot versions makes each snapshot a distinct, pinnable
176+
artifact rather than the usual moving-target Maven SNAPSHOT — consumers can
177+
lock to a specific commit. Trade-off: there is no plain `5.0.0-SNAPSHOT` to
178+
depend on for "always latest."
179+
180+
To see the version the build will produce:
181+
182+
```bash
183+
./gradlew -q printVersion
184+
```
185+
186+
After cutting a release, update `nextVersionBump` if the *next* planned release
187+
is a different shape (e.g. switch from `x` to `x.x` once you start shipping
188+
minor releases on a stable major line).
157189

158190
### Publishing a Snapshot
159191

@@ -163,9 +195,6 @@ Snapshots are published from any state of the repository without signing:
163195
./gradlew publishAllPublicationsToCentralPortalSnapshots
164196
```
165197

166-
The version will be whatever `git describe` produces with `-SNAPSHOT` appended
167-
(e.g. `4.3.0-1-gabcdef0-SNAPSHOT`).
168-
169198
**Note:** Snapshot publishing to Central Portal requires that SNAPSHOT support is enabled
170199
on the `com.github.samtools` namespace in the Central Portal settings.
171200

@@ -175,9 +204,20 @@ Releases are published from a git tag. The full process:
175204

176205
#### Step 1: Tag the Release
177206

207+
Make sure `nextVersionBump` in `build.gradle` matches the kind of release you
208+
intend to ship (major / minor / patch). Then check the version and tag the
209+
release commit:
210+
211+
```bash
212+
./gradlew -q printVersion # prints e.g. "5.0.0-23c681a-SNAPSHOT"
213+
```
214+
215+
Strip the `-<hash>-SNAPSHOT` suffix to get the tag string. For the example
216+
above, that's `5.0.0`:
217+
178218
```bash
179-
git tag X.Y.Z
180-
git push origin X.Y.Z
219+
git tag 5.0.0
220+
git push origin 5.0.0
181221
```
182222

183223
#### Step 2: Verify Locally (Dry Run)

build.gradle

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,75 @@ java {
6060
withSourcesJar()
6161
}
6262

63-
// Version is derived from git tags via the palantir git-version plugin.
64-
// On a tagged commit (e.g. tag "4.3.0") the version is "4.3.0".
65-
// On a later commit it includes the distance and hash, e.g. "4.3.0-3-gabcdef0".
66-
// Without -Drelease=true, "-SNAPSHOT" is appended (e.g. "4.3.0-3-gabcdef0-SNAPSHOT").
63+
// Versioning
64+
// ----------
65+
// The version of the *next* planned release is computed from the most recent
66+
// release tag plus a "bump shape" declared below:
67+
// "x" -> bump the major component (e.g. 4.3.0 -> 5.0.0)
68+
// "x.x" -> bump the minor component (e.g. 4.3.0 -> 4.4.0)
69+
// "x.x.x" -> bump the patch component (e.g. 4.3.0 -> 4.3.1)
70+
//
71+
// Release builds (-Drelease=true) require HEAD to be tagged exactly with the
72+
// computed next version, and the published version is just that string (e.g. "5.0.0").
73+
//
74+
// Snapshot builds (the default) publish "<nextVersion>-<shortHash>-SNAPSHOT"
75+
// (e.g. "5.0.0-abc1234-SNAPSHOT"). Including the short hash means each snapshot
76+
// is a distinct, pinnable artifact rather than the typical Maven "moving target"
77+
// SNAPSHOT, so consumers can lock to a specific commit.
78+
//
79+
// To change the planned bump (e.g. after a release lands), update nextVersionBump
80+
// below and commit.
81+
final nextVersionBump = "x"
82+
6783
final isRelease = Boolean.getBoolean("release")
68-
final gitVersion = gitVersion().replaceAll("\\.dirty", "")
69-
version = isRelease ? gitVersion : gitVersion + "-SNAPSHOT"
84+
final details = versionDetails()
85+
final lastTag = details.lastTag
86+
if (lastTag == null) {
87+
throw new GradleException("No release tags found; cannot determine version.")
88+
}
89+
final semverPattern = /^(\d+)\.(\d+)\.(\d+)$/
90+
final tagMatcher = lastTag =~ semverPattern
91+
if (!tagMatcher.matches()) {
92+
throw new GradleException(
93+
"Most recent tag '${lastTag}' is not in MAJOR.MINOR.PATCH form.")
94+
}
95+
96+
if (isRelease) {
97+
// Release: HEAD must be exactly on a semver-tagged commit AND the working tree
98+
// must be clean; the tag IS the version. (nextVersionBump is informational/for
99+
// snapshots only — the tag is authoritative.)
100+
if (details.commitDistance != 0) {
101+
throw new GradleException(
102+
"Release requested but HEAD is not on a tagged commit " +
103+
"(lastTag=${lastTag}, commitDistance=${details.commitDistance}).")
104+
}
105+
if (!details.isCleanTag) {
106+
throw new GradleException(
107+
"Release requested but the working tree has uncommitted changes; " +
108+
"commit, stash, or reset before publishing.")
109+
}
110+
version = lastTag
111+
} else {
112+
// Snapshot: compute the next planned version from the most recent tag + bump shape.
113+
final lastMajor = tagMatcher.group(1).toInteger()
114+
final lastMinor = tagMatcher.group(2).toInteger()
115+
final lastPatch = tagMatcher.group(3).toInteger()
116+
final String nextVersion
117+
switch (nextVersionBump) {
118+
case "x": nextVersion = "${lastMajor + 1}.0.0"; break
119+
case "x.x": nextVersion = "${lastMajor}.${lastMinor + 1}.0"; break
120+
case "x.x.x": nextVersion = "${lastMajor}.${lastMinor}.${lastPatch + 1}"; break
121+
default:
122+
throw new GradleException(
123+
"Unrecognized nextVersionBump '${nextVersionBump}'; expected 'x', 'x.x', or 'x.x.x'.")
124+
}
125+
version = "${nextVersion}-${details.gitHash.substring(0, 7)}-SNAPSHOT"
126+
}
70127

71-
logger.info("build for version:" + version)
128+
logger.info("build for version: ${version}")
129+
// Note: the palantir git-version plugin already provides a 'printVersion' task
130+
// that prints the resolved project.version — useful for CI scripts and for
131+
// figuring out what tag to apply for a release.
72132
group = 'com.github.samtools'
73133

74134
defaultTasks 'jar'

build.xml

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)