This document defines the release process for MarketDataApp/sdk-java, including the pre-release workflow we use before cutting a tag.
Use this process for:
- patch releases (
vX.Y.Z) - minor releases (
vX.Y.0) - major releases (
vX.0.0)
Before starting, confirm:
- target release version
X.Y.Z - release tag format:
vX.Y.Z - release title format:
Version X.Y.Z - release owner
- included PRs/issues
- intended release date/time
Our pre-release gate artifacts live in release-readiness/ and are reviewed as a package before tag cut.
Required gate docs:
release-readiness/01-api-contract.mdrelease-readiness/02-quality-and-tests.mdrelease-readiness/03-compatibility.mdrelease-readiness/04-security.mdrelease-readiness/05-docs-dx.mdrelease-readiness/06-release-rollback.mdrelease-readiness/final-go-no-go.md
Gate execution checklist:
- API contract gate:
- Confirm intended API/signature changes and migration impact.
- Record pass/fail in
01-api-contract.md.
- Quality/test gate:
./gradlew build(runs unit tests + Spotless formatting check + JaCoCo coverage).- Forward-compat matrix:
./gradlew test -PtestJdk=<17|21|25>for each target JDK. - Integration tests against the live API:
MARKETDATA_RUN_INTEGRATION_TESTS=true ./gradlew integrationTest -PtestJdk=<N>(a validMARKETDATA_TOKENand network-enabled context required). - Record evidence paths and pass/fail in
02-quality-and-tests.md.
- Compatibility gate:
- Confirm the
Mainworkflow (.github/workflows/main.yml) is green for the release commit — it runs the full{17, 21, 25}unit + integration matrix on every push tomain. - Record results in
03-compatibility.md.
- Confirm the
- Security gate:
- Review transitive dependencies (e.g.
./gradlew dependencies) and confirm no unexpected runtime additions slipped in. - Confirm token handling stays header-based (
Authorization: Bearer, redacted in logs via the SDK'sTokensutility) and that TLS verification is never disabled. - Record results in
04-security.md.
- Review transitive dependencies (e.g.
- Docs/DX gate:
- Verify
README.md,CHANGELOG.md,build.gradle.kts(default version), anddocs/installation.mdversion/support messaging align. - Run the executable examples in
examples/consumer-test(theexamples/commonandexamples/resourcessample apps, and the KotlinQuickstart.kt). - Record results in
05-docs-dx.md.
- Verify
- Release/rollback gate:
- Confirm no open blockers.
- Update rollback path for a patch follow-up release.
- Record in
06-release-rollback.md.
- Final decision:
- Set
GOorNO-GOinfinal-go-no-go.md. - No tag is cut unless status is
GOand P0 blockers are empty.
- Set
-
Ensure
mainis current and CI is green. -
Update version numbers in the following files:
File Location Example README.mdTitle header # Market Data Java & Kotlin SDK v1.0build.gradle.ktsversion = ... ?: "X.Y.Z-SNAPSHOT"default1.0.0-SNAPSHOTdocs/installation.mdGradle/Maven coordinates app.marketdata:marketdata-sdk-java:X.Y.ZNote: The published artifact version is injected at publish time via
-PsdkVersion=X.Y.Z. The version committed inbuild.gradle.ktsintentionally stays a-SNAPSHOTdefault — it is overridden by the release and publish workflows, not by hand-editing for each release. -
Update CHANGELOG.md with final release notes (Keep a Changelog bracket format):
- Add a new
## [X.Y.Z] - YYYY-MM-DDsection (move items out of## [Unreleased]; do not use a## vX.Y.Zheading — the release workflow matches## [X.Y.Z]). - Update the compare-link references at the bottom of the file (e.g. set
[Unreleased]tocompare/vX.Y.Z...HEADand add a[X.Y.Z]link). - Verify all breaking changes have migration guides.
- Ensure highlights, breaking changes, and migration notes are complete.
- Add a new
-
Commit and push all changes to
main. -
Confirm target tag does not already exist.
Important: The release workflow extracts release notes directly from CHANGELOG.md. The
## [X.Y.Z]section must be present and complete before triggering the release.
One workflow drives the whole release. Tag and Release (tag-and-release.yml) runs the test gate, cuts the tag and GitHub Release, and then — unless you opt out — chains directly into the Maven Central publish. Each stage gates the next, so a red test or a non-green main.yml stops the release before anything is pushed.
Go to Actions → "Tag and Release", click "Run workflow", and fill in:
- version:
X.Y.Z(withoutvprefix) - ref:
main(or specific commit SHA) - prerelease:
false(unless it's a prerelease) - publish_to_central:
true(default — chain into Maven Central; setfalseto stop after the GitHub Release) - confirm:
RELEASE(exactly, to confirm)
The run proceeds through three gated jobs:
gate— JDK{17, 21, 25}matrix (./gradlew build -PtestJdk=<N> -PsdkVersion=X.Y.Z). Must pass before anything else.release— verifies the tagvX.Y.Zis new, extracts release notes from CHANGELOG.md (the## [X.Y.Z]section), creates the tagvX.Y.Zand the GitHub Release "Version X.Y.Z".publish-central(only whenpublish_to_centralistrue) — callspublish.yml, which independently re-checks thatmain.ymlis green for the commit, rebuilds + tests, then pushes the artifact (app.marketdata:marketdata-sdk-java) to Maven Central.
Stopping before Central. Set publish_to_central to
falseto cut only the tag + GitHub Release. You can then publish later by running the Publish to Maven Central workflow (publish.yml) directly: version =X.Y.Z, release =true. Running that workflow with release =falseuploads to the Sonatype Portal and stops atVALIDATEDfor manual review — useful for inspecting the staged artifact before promoting it.
- Verify the GitHub Release was created with correct notes from CHANGELOG.
- Confirm the artifact is visible on Maven Central (https://central.sonatype.com/artifact/app.marketdata/marketdata-sdk-java) — note that Central indexing can lag a few minutes after publish.
- Smoke-test resolution in a clean project by adding the dependency and resolving it:
// build.gradle.kts
dependencies {
implementation("app.marketdata:marketdata-sdk-java:X.Y.Z")
}<!-- pom.xml -->
<dependency>
<groupId>app.marketdata</groupId>
<artifactId>marketdata-sdk-java</artifactId>
<version>X.Y.Z</version>
</dependency>If release issues are discovered:
- Stop promotion messaging.
- Publish corrective note in release/changelog.
- Ship a patch release (
vX.Y.(Z+1)) frommainwith targeted fix. - Document root cause and remediation in next changelog entry.