|
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 | + |
2 | 17 | 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() |
6 | 25 | } |
7 | 26 |
|
8 | | -// Get the commit count |
9 | 27 | 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) |
13 | 30 | } |
14 | 31 |
|
15 | | -// Get the current branch name |
16 | | -val branchName: String by lazy { |
| 32 | +val branch: String by lazy { |
17 | 33 | // First, try GitHub Actions environment variable |
18 | 34 | val githubBranch = System.getenv("GITHUB_REF_NAME") |
19 | 35 | if (!githubBranch.isNullOrBlank()) githubBranch |
20 | 36 |
|
21 | 37 | // Fallback to local git command |
22 | 38 | 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") |
26 | 40 | } |
27 | 41 | } |
28 | 42 |
|
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 | + } |
35 | 72 |
|
| 73 | + return "$major.${minor + 1}.$patch-a$commitCount-g$gitHash" |
| 74 | +} |
| 75 | + |
| 76 | +version = calcVersion() |
36 | 77 | println("Project version: $version") // prints when Gradle evaluates the build |
37 | 78 |
|
| 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 | + |
38 | 119 | plugins { |
39 | 120 | id("java") |
40 | 121 | id("java-library") |
41 | 122 | id("maven-publish") |
42 | 123 | id("pmd") |
43 | | - id("com.diffplug.spotless") version "6.25.0" |
| 124 | + id("com.diffplug.spotless") version "8.0.0" |
44 | 125 | } |
45 | 126 |
|
46 | 127 | group = "dev.dbos" |
|
0 commit comments