hiero-ledger / hiero-ledger/hiero-sdk-java

version.txt on main must always contain a -SNAPSHOT version between releases

Open
#2,884 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
264
Forks
192
Avg merge
2d
Merged PRs (30d)
39

Description

Today the release process sets `version.txt` to the version that is about to be released (e.g. `2.76.0`, commit `ab3fcb9`, "chore: release 2.76.0" #2880) and then leaves it there. As a result, `main` permanently carries a version number that has **already been published to Maven Central**. Every commit merged after a release — up to and including the day before the next release — builds artifacts that claim to be `com.hedera.hashgraph:sdk:2.76.0`, even though they are not that release.

This was the motivation for #2648, which changed `version.txt` to `2.68.0-SNAPSHOT`. The intent of that PR was apparently not clear, so this issue describes the underlying problem and the concrete fix.

## Why this is a problem

1. **Local development builds silently overwrite the real release.** `./gradlew publishToMavenLocal` on `main` writes `sdk-2.76.0.jar` into `~/.m2/repository`. From that point on, *every* project on that machine that depends on `com.hedera.hashgraph:sdk:2.76.0` — including projects that have nothing to do with SDK development — resolves an unreviewed local build instead of the official release. This is invisible and produces bug reports that cannot be reproduced.

2. **Release versions are immutable by contract; SNAPSHOT versions are not.** Maven and Gradle treat a non-SNAPSHOT version as immutable and cache it forever: once `2.76.0` is in the local cache, a rebuild of `main` is not picked up. A `-SNAPSHOT` version is explicitly defined as mutable and is re-resolved (`changing = true`, configurable update interval). Without SNAPSHOT versions, iterating on the SDK from a consuming application means manually deleting cache entries.

3. **There is no way to consume "the current state of `main`".** Downstream consumers (`examples`, `tck`, `example-android`, integration tests in other Hiero repos, users who want to verify a fix before a release) currently have no coordinate that unambiguously refers to unreleased code. `2.76.0` is not that coordinate — it is the release.

4. **Publishing pre-release/nightly artifacts is impossible.** Publishing snapshots to a snapshot repository (Central Portal snapshots, GitHub Packages) requires a `-SNAPSHOT` version by definition. As long as `main` carries a release version, we cannot offer nightly builds at all, and any attempt would be an attempt to overwrite a released coordinate.

5. **Version numbers become ambiguous in issue reports.** "I'm on 2.76.0" can mean the release or any commit on `main` after it. With `2.77.0-SNAPSHOT` the two states are distinguishable on sight.

This is not a stylistic preference: it is the standard Maven/Gradle release convention, and the repository already follows it elsewhere — `examples/version.txt` contains `0.1.0-SNAPSHOT`.

## Proposed solution

Adopt the standard rule, explicitly:

> **The version in `version.txt` on `main` is always a `-SNAPSHOT` version. A non-SNAPSHOT version exists only on the release commit that is tagged and published.**

Concrete release flow:

1. Release PR sets `version.txt` from `X.Y.Z-SNAPSHOT` to `X.Y.Z` (as today) and is merged.
2. Tag `vX.Y.Z` is created **on that release commit** and pushed; `release-artifacts.yml` validates tag vs. project version and publishes to Maven Central (unchanged behaviour).
3. Immediately afterwards, a follow-up commit on `main` sets `version.txt` to the next development version, e.g. `X.(Y+1).0-SNAPSHOT`.

Steps 1–3 can be a single automated sequence in the release workflow, or two PRs — that is an implementation detail. The invariant is that `main` never stays on a published version.

Note: this does **not** change what gets published. `release-artifacts.yml` only publishes on `v*.*.*` tag pushes, so a `-SNAPSHOT` on `main` can never be released to Maven Central by accident. The `validate-release` check keeps working, because the tag points at the release commit whose `version.txt` contains the exact release version.

## Acceptance criteria

- [ ] `version.txt` on `main` contains `2.77.0-SNAPSHOT` (i.e. the next development version, not the last released one).
- [ ] The release process (documented and/or automated) contains an explicit post-release step that restores the `-SNAPSHOT` version on `main`.
- [ ] The rule is documented for contributors (`CONTRIBUTING.md` / release runbook / `MAINTAINERS.md`): release versions live on tags only, `main` is always SNAPSHOT.
- [ ] `./gradlew publishToMavenLocal` on `main` produces `-SNAPSHOT` artifacts that cannot shadow a published release.

## Optional follow-ups (not required for this issue)

- CI guard on `main`: fail the build if `version.txt` does not end in `-SNAPSHOT` (outside of the release commit), so the post-release step can never be forgotten again.
- Publish snapshots from `main` to a snapshot repository so consumers can test unreleased fixes without building locally.

## References

- PR #2648 — "fix: Version number need to be changed after releases" (the original attempt to fix this)
- `.github/workflows/release-artifacts.yml` — tag-triggered publishing and the tag/version consistency check
- `examples/version.txt` — already uses `0.1.0-SNAPSHOT`, i.e. the convention this issue asks for

Contributor guide

Open the contributing guide

Research direction

Start with version.txt and .github/workflows/release-artifacts.yml, then read the contributor or release documentation named in the acceptance criteria. Trace how the release tag and project version are validated, and verify the post-release development version is restored on main. Done means main uses the next -SNAPSHOT version, the process is documented or automated, and local publishing cannot shadow a released coordinate.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions, java
Domain
build-system, documentation, release
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.