diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 64fe051ba9..e336d3c9fa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,6 +21,8 @@ jobs: name: Java ${{ matrix.Java }} build and test steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag - name: Set up java ${{ matrix.Java }} uses: actions/setup-java@v3 with: @@ -49,6 +51,8 @@ jobs: name: Tests that require external APIs steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag - name: Set up java 17 uses: actions/setup-java@v3 with: @@ -72,6 +76,8 @@ jobs: name: SpotBugs steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 # full history + tags so palantir/git-version sees the latest release tag - name: Set up java 17 uses: actions/setup-java@v3 with: diff --git a/.gitignore b/.gitignore index 03a8d6d509..606b65033a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ htsjdk.iws .command_tmp atlassian-ide-plugin.xml -/htsjdk.version.properties /test-output/ .DS_Store diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f00fe8b27e..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ -language: java -dist: trusty -sudo: true -services: - - docker -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - - $HOME/.m2 -env: - global: - - HTSJDK_SAMTOOLS_BIN=/usr/bin/samtools -jdk: - - oraclejdk8 - - openjdk8 - - openjdk11 -matrix: - fast_finish: true - allow_failures: - - env: TEST_TYPE=EXTERNAL_APIS - - env: TEST_TYPE=FTP - include: - - jdk: oraclejdk8 - env: TEST_TYPE=EXTERNAL_APIS - - jdk: oraclejdk8 - env: TEST_TYPE=FTP - - jdk: openjdk8 - env: SPOT_BUGS=true - -before_install: - - scripts/install-samtools.sh - - scripts/htsget-scripts/start-htsget-test-server.sh - -script: - - if [[ $SPOT_BUGS == "true" ]]; then - ./gradlew spotBugsMain spotBugsTest; - elif [[ $TEST_TYPE == "FTP" ]]; then - ./gradlew testFTP jacocoTestReport; - elif [[ $TEST_TYPE == "EXTERNAL_APIS" ]]; then - ./gradlew testExternalApis jacocoTestReport; - else - ./gradlew test jacocoTestReport; - fi - -after_success: - - bash <(curl -s https://raw.githubusercontent.com/broadinstitute/codecov-bash-uploader/main/codecov-verified.bash) - - echo "TRAVIS_BRANCH='$TRAVIS_BRANCH'"; - echo "JAVA_HOME='$JAVA_HOME'"; - if [ "$TRAVIS_BRANCH" == "master" ]; then - if [[ $JAVA_HOME = *java-8-openjdk* ]]; then - ./gradlew publish; - fi; - fi; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea46e2d43d..40ec5a95ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -148,12 +148,44 @@ export GPG_TTY=$(tty) ### Version Numbering -The version is derived automatically from git tags using the -[palantir git-version](https://github.com/palantir/gradle-git-version) plugin: +The build computes the version from git state plus a single declaration in +`build.gradle`: -- On a release tag (e.g. `4.3.0`): version is `4.3.0` -- On a commit after a tag: version includes the commit distance and hash -- Without `-Drelease=true`: `-SNAPSHOT` is appended +```groovy +final nextVersionBump = "x" // "x" major, "x.x" minor, "x.x.x" patch +``` + +`nextVersionBump` declares the *shape* of the next planned release relative to +the most recent semver tag (e.g. `4.3.0`): + +| Bump | Most recent tag | Computed next version | +| ------- | --------------- | --------------------- | +| `x` | `4.3.0` | `5.0.0` | +| `x.x` | `4.3.0` | `4.4.0` | +| `x.x.x` | `4.3.0` | `4.3.1` | + +What the build actually publishes: + +- **Release** (`-Drelease=true`): HEAD must be on a semver-tagged commit; the + tag itself is the version (e.g. `5.0.0`). `nextVersionBump` is ignored on + release — the tag is authoritative. +- **Snapshot** (default): `--SNAPSHOT` + (e.g. `5.0.0-23c681a-SNAPSHOT`). + +The short hash in snapshot versions makes each snapshot a distinct, pinnable +artifact rather than the usual moving-target Maven SNAPSHOT — consumers can +lock to a specific commit. Trade-off: there is no plain `5.0.0-SNAPSHOT` to +depend on for "always latest." + +To see the version the build will produce: + +```bash +./gradlew -q printVersion +``` + +After cutting a release, update `nextVersionBump` if the *next* planned release +is a different shape (e.g. switch from `x` to `x.x` once you start shipping +minor releases on a stable major line). ### Publishing a Snapshot @@ -163,9 +195,6 @@ Snapshots are published from any state of the repository without signing: ./gradlew publishAllPublicationsToCentralPortalSnapshots ``` -The version will be whatever `git describe` produces with `-SNAPSHOT` appended -(e.g. `4.3.0-1-gabcdef0-SNAPSHOT`). - **Note:** Snapshot publishing to Central Portal requires that SNAPSHOT support is enabled on the `com.github.samtools` namespace in the Central Portal settings. @@ -175,9 +204,20 @@ Releases are published from a git tag. The full process: #### Step 1: Tag the Release +Make sure `nextVersionBump` in `build.gradle` matches the kind of release you +intend to ship (major / minor / patch). Then check the version and tag the +release commit: + +```bash +./gradlew -q printVersion # prints e.g. "5.0.0-23c681a-SNAPSHOT" +``` + +Strip the `--SNAPSHOT` suffix to get the tag string. For the example +above, that's `5.0.0`: + ```bash -git tag X.Y.Z -git push origin X.Y.Z +git tag 5.0.0 +git push origin 5.0.0 ``` #### Step 2: Verify Locally (Dry Run) diff --git a/build.gradle b/build.gradle index e359d9df5e..f83371d7bf 100644 --- a/build.gradle +++ b/build.gradle @@ -60,15 +60,75 @@ java { withSourcesJar() } -// Version is derived from git tags via the palantir git-version plugin. -// On a tagged commit (e.g. tag "4.3.0") the version is "4.3.0". -// On a later commit it includes the distance and hash, e.g. "4.3.0-3-gabcdef0". -// Without -Drelease=true, "-SNAPSHOT" is appended (e.g. "4.3.0-3-gabcdef0-SNAPSHOT"). +// Versioning +// ---------- +// The version of the *next* planned release is computed from the most recent +// release tag plus a "bump shape" declared below: +// "x" -> bump the major component (e.g. 4.3.0 -> 5.0.0) +// "x.x" -> bump the minor component (e.g. 4.3.0 -> 4.4.0) +// "x.x.x" -> bump the patch component (e.g. 4.3.0 -> 4.3.1) +// +// Release builds (-Drelease=true) require HEAD to be tagged exactly with the +// computed next version, and the published version is just that string (e.g. "5.0.0"). +// +// Snapshot builds (the default) publish "--SNAPSHOT" +// (e.g. "5.0.0-abc1234-SNAPSHOT"). Including the short hash means each snapshot +// is a distinct, pinnable artifact rather than the typical Maven "moving target" +// SNAPSHOT, so consumers can lock to a specific commit. +// +// To change the planned bump (e.g. after a release lands), update nextVersionBump +// below and commit. +final nextVersionBump = "x" + final isRelease = Boolean.getBoolean("release") -final gitVersion = gitVersion().replaceAll("\\.dirty", "") -version = isRelease ? gitVersion : gitVersion + "-SNAPSHOT" +final details = versionDetails() +final lastTag = details.lastTag +if (lastTag == null) { + throw new GradleException("No release tags found; cannot determine version.") +} +final semverPattern = /^(\d+)\.(\d+)\.(\d+)$/ +final tagMatcher = lastTag =~ semverPattern +if (!tagMatcher.matches()) { + throw new GradleException( + "Most recent tag '${lastTag}' is not in MAJOR.MINOR.PATCH form.") +} + +if (isRelease) { + // Release: HEAD must be exactly on a semver-tagged commit AND the working tree + // must be clean; the tag IS the version. (nextVersionBump is informational/for + // snapshots only — the tag is authoritative.) + if (details.commitDistance != 0) { + throw new GradleException( + "Release requested but HEAD is not on a tagged commit " + + "(lastTag=${lastTag}, commitDistance=${details.commitDistance}).") + } + if (!details.isCleanTag) { + throw new GradleException( + "Release requested but the working tree has uncommitted changes; " + + "commit, stash, or reset before publishing.") + } + version = lastTag +} else { + // Snapshot: compute the next planned version from the most recent tag + bump shape. + final lastMajor = tagMatcher.group(1).toInteger() + final lastMinor = tagMatcher.group(2).toInteger() + final lastPatch = tagMatcher.group(3).toInteger() + final String nextVersion + switch (nextVersionBump) { + case "x": nextVersion = "${lastMajor + 1}.0.0"; break + case "x.x": nextVersion = "${lastMajor}.${lastMinor + 1}.0"; break + case "x.x.x": nextVersion = "${lastMajor}.${lastMinor}.${lastPatch + 1}"; break + default: + throw new GradleException( + "Unrecognized nextVersionBump '${nextVersionBump}'; expected 'x', 'x.x', or 'x.x.x'.") + } + version = "${nextVersion}-${details.gitHash.substring(0, 7)}-SNAPSHOT" +} -logger.info("build for version:" + version) +logger.info("build for version: ${version}") +// Note: the palantir git-version plugin already provides a 'printVersion' task +// that prints the resolved project.version — useful for CI scripts and for +// figuring out what tag to apply for a release. group = 'com.github.samtools' defaultTasks 'jar' diff --git a/build.xml b/build.xml deleted file mode 100755 index 59bebded33..0000000000 --- a/build.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - ANT IS DEPRECATED FOR BUILDING HTSJDK - - Please switch to using gradlew - - Examples: - compile htsjdk or it's tests - ./gradlew compileJava - ./gradlew compileTest - - build a jar - ./gradlew jar - - build a jar, along with source and document jars - ./gradlew build - - build a jar that packages all of htsjdk's dependencies in a single jar - ./gradlew shadowJar - - run tests, or a single test, or run a test and wait for the debugger - ./gradlew test - ./gradlew test --tests "*AlleleUnitTest" - ./gradlew test --tests "*AlleleUnitTest" --debug-jvm - - clean the project directory - ./gradlew clean - - see an exhaustive list of all available targets - ./gradlew tasks - - -