Skip to content

Commit 4a1d3ca

Browse files
authored
update build version calc (#159)
Maven version order specification: https://maven.apache.org/pom.html#Version_Order_Specification This PR updates the build version calculation to do the following: * Calculate major/minor/patch from tag, defaulting to 0.1.0 if no tag is found * calculate commit count from most recent tag, from start of repo if no tag is foudn * For main branch, the version is $Major.$Minor + 1.$Patch-m$CommitCount * in maven, the m stands for "milestone" which seemed the most reasonable choice out of the pre release choices: alpha/beta/milestone/release candidate * For release branch, version is $Major.$Minor.$Patch * Additionally, we check to make sure the branch name matches the calculated version and that the branch itself has the tag * We might want to enforce these constraints in the publish task, not in the build version calculation * for any other branch, the version is $Major.$Minor + 1.$Patch-a$CommitCount-gGitHash fixes #74
1 parent bb1ff4c commit 4a1d3ca

6 files changed

Lines changed: 164 additions & 32 deletions

File tree

.github/workflows/on_push.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ on:
99
jobs:
1010
test:
1111
uses: ./.github/workflows/test.yml
12-
publish:
13-
needs: test
14-
uses: ./.github/workflows/publish.yml
15-
secrets:
16-
USERNAME_MAVEN: ${{ secrets.USERNAME_MAVEN }}
17-
TOKEN_MAVEN: ${{ secrets.TOKEN_MAVEN }}
12+
# publish:
13+
# needs: test
14+
# uses: ./.github/workflows/publish.yml
15+
# secrets:
16+
# USERNAME_MAVEN: ${{ secrets.USERNAME_MAVEN }}
17+
# TOKEN_MAVEN: ${{ secrets.TOKEN_MAVEN }}

.github/workflows/publish.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ on:
77
required: true
88
TOKEN_MAVEN:
99
required: true
10+
workflow_dispatch:
1011

1112
jobs:
12-
build:
13+
public:
1314
runs-on: ubuntu-latest
15+
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/v')
1416
steps:
1517
- name: Checkout code
1618
uses: actions/checkout@v4

DEVELOPING.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,52 @@ If build fails because of format violations, you can update the code with the `s
4949
Add to your build.gradle.kts
5050

5151
```kotlin
52-
implementation("dev.dbos:transact:1.0-SNAPSHOT")
52+
implementation("dev.dbos:transact")
5353
implementation("ch.qos.logback:logback-classic:1.5.6")
5454
```
5555

56-
Annotations @Workflow, @Transaction, @Step need to be on implementation class methods.
56+
57+
## Release Versioning
58+
59+
DBOS Transact for Java follows the [Maven version order algorithm](https://maven.apache.org/pom.html#Version_Order_Specification).
60+
61+
### Creating a Release
62+
63+
Release branch builds are published to Maven Central.
64+
65+
To create a new release, run
66+
67+
```shell
68+
./gradlew createRelease -PreleaseVersion=1.2.3
69+
```
70+
71+
This command tags the latest commit with the version number and creates a release branch for it.
72+
If a version number is not supplied, it is generated by incrementing the last released minor version.
73+
74+
### Patching a release
75+
76+
Release branch patch builds are published to Maven Central.
77+
To patch a release, push the patch as a commit to the appropriate release branch.
78+
Then, tag it with a version number:
79+
80+
```shell
81+
git tag <version-number>
82+
git push --tags
83+
```
84+
85+
This version number should increment the patch number by one, as per the Maven version order algorithm.
86+
87+
### Preview Versions
88+
89+
Main branch builds may be published to Maven Central.
90+
To facilitate publishing, main branch builds carry the automatically generated version number (i.e.incremented minor version )
91+
as well as a prerelease tag `-m<git-commit-count>.
92+
The git commit count is the number of commits since the last release.
93+
94+
### Feature Branch Versions
95+
96+
Feature branch builds are not designed to be published to Maven Central.
97+
Like main branch builds, feature branch builds carry the automatically generated version number
98+
and a prerelease tag `-a<git-commit-count>.
99+
In Maven version order algorithm, the `-a` prerelease prefix is lower priority than the `-m` prefix.
100+
Feature branch builds also carry an additional `-g<git-commit-hash>` prerelease tag.

build.gradle.kts

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,127 @@
1-
// Get the short Git hash
1+
fun Project.runCommand(vararg args: String): String {
2+
val process = ProcessBuilder(*args)
3+
.directory(projectDir)
4+
.redirectErrorStream(true)
5+
.start()
6+
7+
val output = process.inputStream.bufferedReader().readText()
8+
val exitCode = process.waitFor()
9+
10+
if (exitCode != 0) {
11+
throw GradleException("Command failed with exit code $exitCode: ${args.joinToString(" ")}")
12+
}
13+
14+
return output.trim()
15+
}
16+
217
val gitHash: String by lazy {
3-
providers.exec {
4-
commandLine("git", "rev-parse", "--short", "HEAD")
5-
}.standardOutput.asText.get().trim()
18+
runCommand("git", "rev-parse", "--short", "HEAD")
19+
}
20+
21+
val gitTag: String? by lazy {
22+
runCatching {
23+
runCommand("git", "describe", "--abbrev=0", "--tags")
24+
}.getOrNull()
625
}
726

8-
// Get the commit count
927
val commitCount: String by lazy {
10-
providers.exec {
11-
commandLine("git", "rev-list", "--count", "HEAD")
12-
}.standardOutput.asText.get().trim()
28+
val range = if (gitTag.isNullOrEmpty()) "HEAD" else "$gitTag..HEAD"
29+
runCommand("git", "rev-list", "--count", range)
1330
}
1431

15-
// Get the current branch name
16-
val branchName: String by lazy {
32+
val branch: String by lazy {
1733
// First, try GitHub Actions environment variable
1834
val githubBranch = System.getenv("GITHUB_REF_NAME")
1935
if (!githubBranch.isNullOrBlank()) githubBranch
2036

2137
// Fallback to local git command
2238
else {
23-
providers.exec {
24-
commandLine("git", "rev-parse", "--abbrev-ref", "HEAD")
25-
}.standardOutput.asText.get().trim()
39+
runCommand("git", "rev-parse", "--abbrev-ref", "HEAD")
2640
}
2741
}
2842

29-
// Note, this versioning scheme is fine for preview releases
30-
// but we'll want something more robust once we want to bump
31-
// the major or minor version number
32-
val baseVersion = System.getenv("BASE_VERSION") ?: "0.5"
33-
val safeBranchName = if (branchName == "main" || branchName == "HEAD") "" else ".${branchName.replace("/", "-")}"
34-
version = "$baseVersion.$commitCount-preview+g$gitHash$safeBranchName"
43+
val isGitDirty: Boolean by lazy {
44+
providers.exec {
45+
commandLine("git", "status", "--porcelain")
46+
}.standardOutput.toString().isNotBlank()
47+
}
48+
49+
fun hasTag(tag: String): Boolean {
50+
return providers.exec {
51+
commandLine("git", "tag", "-l", tag)
52+
}.standardOutput.toString().trim().isNotEmpty()
53+
}
54+
55+
fun parseTag(tag: String): Triple<Int, Int, Int>? {
56+
val regex = Regex("""v?(\d+)\.(\d+)\.(\d+)""")
57+
val match = regex.matchEntire(tag.trim()) ?: return null
58+
val (major, minor, patch) = match.destructured
59+
return Triple(major.toInt(), minor.toInt(), patch.toInt())
60+
}
61+
62+
fun calcVersion(): String {
63+
var (major, minor, patch) = parseTag(gitTag ?: "") ?: Triple(0, 1, 0)
64+
65+
if (branch == "main") {
66+
return "$major.${minor + 1}.$patch-m$commitCount"
67+
}
68+
69+
if (branch.startsWith("release/v")) {
70+
return "$major.$minor.$patch"
71+
}
3572

73+
return "$major.${minor + 1}.$patch-a$commitCount-g$gitHash"
74+
}
75+
76+
version = calcVersion()
3677
println("Project version: $version") // prints when Gradle evaluates the build
3778

79+
tasks.register("printGitStatus") {
80+
doLast {
81+
val status = project.runCommand("git", "status", "--porcelain")
82+
println("Git status:\n$status")
83+
}
84+
}
85+
86+
tasks.register("createRelease") {
87+
group = "release"
88+
description = "Create a release branch and git tag"
89+
90+
if (isGitDirty) {
91+
throw GradleException("Local git repository is not clean")
92+
}
93+
if (branch != "main") {
94+
throw GradleException("Can only make a release from main")
95+
}
96+
97+
val local = runCommand("git", "rev-parse", "HEAD")
98+
val remote = runCommand("git", "rev-parse", "origin/$branch")
99+
if (local != remote) {
100+
throw GradleException("your local branch $branch is not up to date with origin")
101+
}
102+
103+
val (major, minor, patch) = parseTag(gitTag ?: "") ?: Triple(0, 1, 0)
104+
val releaseVersion = project.findProperty("releaseVersion")?.toString() ?: "$major.${minor + 1}.$patch"
105+
val releaseBranch = "release/v$releaseVersion"
106+
107+
if (!Regex("""\d+\.\d+\.\d+""").matches(releaseVersion)) {
108+
throw GradleException("Invalid version numbe: $releaseVersion")
109+
}
110+
111+
doLast {
112+
runCommand("git", "tag", releaseVersion)
113+
runCommand("git", "push", "origin", releaseVersion)
114+
runCommand("git", "branch", releaseBranch)
115+
runCommand("git", "push", "origin", releaseBranch)
116+
}
117+
}
118+
38119
plugins {
39120
id("java")
40121
id("java-library")
41122
id("maven-publish")
42123
id("pmd")
43-
id("com.diffplug.spotless") version "6.25.0"
124+
id("com.diffplug.spotless") version "8.0.0"
44125
}
45126

46127
group = "dev.dbos"

src/main/java/dev/dbos/transact/admin/AdminServer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ public void close() {
105105
}
106106

107107
private void healthCheck(HttpExchange exchange) throws IOException {
108-
sendJson(exchange, 200, """
108+
sendJson(
109+
exchange,
110+
200,
111+
"""
109112
{"status":"healthy"}""");
110113
}
111114

src/test/java/dev/dbos/transact/admin/AdminServerTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ public void garbageCollect() throws IOException {
230230
given()
231231
.port(port)
232232
.contentType("application/json")
233-
.body("""
233+
.body(
234+
"""
234235
{ "cutoff_epoch_timestamp_ms": 42, "rows_threshold": 37 } """)
235236
.when()
236237
.post("/dbos-garbage-collect")
@@ -250,7 +251,8 @@ public void globalTimeout() throws IOException {
250251
given()
251252
.port(port)
252253
.contentType("application/json")
253-
.body("""
254+
.body(
255+
"""
254256
{ "cutoff_epoch_timestamp_ms": 42 } """)
255257
.when()
256258
.post("/dbos-global-timeout")

0 commit comments

Comments
 (0)