Good setup—this is a classic “3-layer override model”:
1. CLI (`-P`) → highest priority
2. `version.properties` → controlled release source
3. defaults → fallback safety net
Here’s a clean **Gradle 7.2 / Java 8 compatible** way to do it.
---
# ✅ `build.gradle` solution
groovy id="g3k9v2"
import java.util.Properties
// -----------------------------
// 1. Defaults (lowest priority)
// -----------------------------
def defaultVersion = "0.0.0"
def defaultRelease = "0"
// -----------------------------
// 2. Load version.properties
// -----------------------------
def versionProps = new Properties()
def versionFile = file("version.properties")
if (versionFile.exists()) {
versionFile.withInputStream { stream ->
versionProps.load(stream)
}
}
// -----------------------------
// 3. CLI overrides (-PpkgVersion / -PpkgRelease)
// -----------------------------
def cliVersion = project.findProperty("pkgVersion")
def cliRelease = project.findProperty("pkgRelease")
// -----------------------------
// 4. Resolve final values (priority order)
// CLI > file > default
// -----------------------------
ext.pkgVersion = cliVersion ?:
versionProps.getProperty("pkgVersion") ?:
defaultVersion
ext.pkgRelease = cliRelease ?:
versionProps.getProperty("pkgRelease") ?:
defaultRelease
// -----------------------------
// 5. Optional: combined version
// -----------------------------
ext.fullVersion = "${pkgVersion}-${pkgRelease}"
// -----------------------------
// 6. Validation (optional but recommended)
// -----------------------------
task printVersionInfo {
doLast {
println "Resolved version:"
println " pkgVersion = ${pkgVersion}"
println " pkgRelease = ${pkgRelease}"
println " fullVersion = ${fullVersion}"
}
}
---
# 📦 `version.properties` example
properties id="d8qk2n"
pkgVersion=1.4.0
pkgRelease=17
---
# ⚙️ How resolution works
| Source | Priority | Example |
| ----------------------- | -------- | ------------------ |
| `-PpkgVersion=2.0.0` | highest | CI override |
| `version.properties` | medium | release-controlled |
| default in build.gradle | lowest | fallback safety |
---
# 🚀 Usage examples
## 1. Normal CI / Tekton build
bash id="n9m2qp"
./gradlew build
👉 uses `version.properties`
---
## 2. Override from pipeline
bash id="t1xk7q"
./gradlew build -PpkgVersion=2.0.0 -PpkgRelease=99
👉 ignores file completely
---
## 3. Broken/missing config fallback
If both are missing:
properties
pkgVersion = 0.0.0
pkgRelease = 0
👉 build still works safely
---
# 🧠 Why this design is solid
### ✔ Clear override hierarchy
No ambiguity about what wins.
### ✔ Safe CI behavior
No hard failure if file missing.
### ✔ Release governance ready
`version.properties` becomes controlled artifact.
### ✔ CI flexibility preserved
LightSpeed/Tekton can still override via `-P`.
---
# 💡 Optional improvement (recommended in your setup)
Add strict validation for release branches:
groovy id="r7k3lm"
task validateVersion {
doLast {
if (!pkgVersion || !pkgRelease) {
throw new GradleException("Version not defined")
}
if (!pkgVersion.matches("\\d+\\.\\d+\\.\\d+")) {
throw new GradleException("pkgVersion must be semantic (x.y.z)")
}
}
}
build.dependsOn validateVersion
---
# 🏁 Result
You now have:
* ✔ release-controlled versioning (`version.properties`)
* ✔ CI override capability (`-P`)
* ✔ safe fallback defaults
* ✔ Gradle 7.2 compatible implementation
* ✔ no dependency on LightSpeed internals
---
If you want next step, I can show you how to:
👉 auto-bump `pkgRelease` per build number in Tekton
👉 or enforce “version must increase vs Git tags” (strong release governance pattern)
Top comments (0)