From fc139f1eca754188ebc1c9ec2edaeecbd58467be Mon Sep 17 00:00:00 2001 From: Alexis Tual Date: Fri, 15 Jul 2022 12:40:13 +0200 Subject: [PATCH] Get branch name from env var (#74) --- build.gradle | 7 ++ .../gradle/CustomBuildScanEnhancements.java | 77 +++++++------------ .../java/com/gradle/GitMetadataResolver.java | 27 +++++++ src/main/java/com/gradle/Utils.java | 4 +- .../com/gradle/GitMetadataResolverTest.groovy | 31 ++++++++ 5 files changed, 95 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/gradle/GitMetadataResolver.java create mode 100644 src/test/groovy/com/gradle/GitMetadataResolverTest.groovy diff --git a/build.gradle b/build.gradle index 87f0ab12..609c376b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java-gradle-plugin' + id 'groovy' id 'maven-publish' id 'signing' id 'com.gradle.plugin-publish' version '1.0.0' @@ -16,6 +17,8 @@ repositories { dependencies { compileOnly 'com.gradle:gradle-enterprise-gradle-plugin:3.10.3' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" } wrapperUpgrade { @@ -32,6 +35,10 @@ java { } } +test { + useJUnitPlatform() +} + gradlePlugin { automatedPublishing = true diff --git a/src/main/java/com/gradle/CustomBuildScanEnhancements.java b/src/main/java/com/gradle/CustomBuildScanEnhancements.java index 2463528f..e751f35d 100644 --- a/src/main/java/com/gradle/CustomBuildScanEnhancements.java +++ b/src/main/java/com/gradle/CustomBuildScanEnhancements.java @@ -14,15 +14,12 @@ import java.util.Map; import java.util.Optional; import java.util.Properties; -import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import static com.gradle.Utils.appendIfMissing; import static com.gradle.Utils.execAndCheckSuccess; -import static com.gradle.Utils.execAndGetStdOut; -import static com.gradle.Utils.isNotEmpty; import static com.gradle.Utils.redactUserInfo; import static com.gradle.Utils.urlEncode; @@ -216,7 +213,7 @@ private void captureCiMetadata() { customValueSearchLinker.addCustomValueAndSearchLink("CI stage", value)); } - if(isAzurePipelines()) { + if (isAzurePipelines()) { Optional azureServerUrl = envVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"); Optional azureProject = envVariable("SYSTEM_TEAMPROJECT"); Optional buildId = envVariable("BUILD_BUILDID"); @@ -302,44 +299,35 @@ private CaptureGitMetadataAction(ProviderFactory providers, CustomValueSearchLin @Override public void execute(BuildScanExtension buildScan) { - if (!isGitInstalled()) { - return; - } - - String gitRepo = execAndGetStdOut("git", "config", "--get", "remote.origin.url"); - String gitCommitId = execAndGetStdOut("git", "rev-parse", "--verify", "HEAD"); - String gitCommitShortId = execAndGetStdOut("git", "rev-parse", "--short=8", "--verify", "HEAD"); - String gitBranchName = getGitBranchName(() -> execAndGetStdOut("git", "rev-parse", "--abbrev-ref", "HEAD")); - String gitStatus = execAndGetStdOut("git", "status", "--porcelain"); - - if (isNotEmpty(gitRepo)) { - buildScan.value("Git repository", redactUserInfo(gitRepo)); - } - if (isNotEmpty(gitCommitId)) { - buildScan.value("Git commit id", gitCommitId); - } - if (isNotEmpty(gitCommitShortId)) { - customValueSearchLinker.addCustomValueAndSearchLink("Git commit id", "Git commit id short", gitCommitShortId); - } - if (isNotEmpty(gitBranchName)) { - buildScan.tag(gitBranchName); - buildScan.value("Git branch", gitBranchName); - } - if (isNotEmpty(gitStatus)) { + GitMetadataResolver gitMetadataResolver = new GitMetadataResolver(isGitInstalled()); + Optional gitRepo = gitMetadataResolver.resolve(() -> Utils.execAndGetStdOut("git", "config", "--get", "remote.origin.url")); + Optional gitCommitId = gitMetadataResolver.resolve(() -> Utils.execAndGetStdOut("git", "rev-parse", "--verify", "HEAD")); + Optional gitCommitShortId = gitMetadataResolver.resolve(() -> Utils.execAndGetStdOut("git", "rev-parse", "--short=8", "--verify", "HEAD")); + Optional gitStatus = gitMetadataResolver.resolve(() -> Utils.execAndGetStdOut("git", "status", "--porcelain")); + Optional gitBranchName = gitMetadataResolver.resolve(this::getGitBranchNameFromEnv, () -> Utils.execAndGetStdOut("git", "rev-parse", "--abbrev-ref", "HEAD")); + + gitRepo.ifPresent(s -> buildScan.value("Git repository", redactUserInfo(s))); + gitCommitId.ifPresent(s -> buildScan.value("Git commit id", s)); + gitCommitShortId.ifPresent(s -> customValueSearchLinker.addCustomValueAndSearchLink("Git commit id", "Git commit id short", s)); + gitBranchName.ifPresent(s -> { + buildScan.tag(s); + buildScan.value("Git branch", s); + }); + gitStatus.ifPresent(s -> { buildScan.tag("Dirty"); - buildScan.value("Git status", gitStatus); - } + buildScan.value("Git status", s); + }); - if (isNotEmpty(gitRepo) && isNotEmpty(gitCommitId)) { - if (gitRepo.contains("github.com/") || gitRepo.contains("github.com:")) { - Matcher matcher = Pattern.compile("(.*)github\\.com[/|:](.*)").matcher(gitRepo); + if (gitRepo.isPresent() && gitCommitId.isPresent()) { + if (gitRepo.get().contains("github.com/") || gitRepo.get().contains("github.com:")) { + Matcher matcher = Pattern.compile("(.*)github\\.com[/|:](.*)").matcher(gitRepo.get()); if (matcher.matches()) { String rawRepoPath = matcher.group(2); String repoPath = rawRepoPath.endsWith(".git") ? rawRepoPath.substring(0, rawRepoPath.length() - 4) : rawRepoPath; buildScan.link("Github source", "https://github.com/" + repoPath + "/tree/" + gitCommitId); } - } else if (gitRepo.contains("gitlab.com/") || gitRepo.contains("gitlab.com:")) { - Matcher matcher = Pattern.compile("(.*)gitlab\\.com[/|:](.*)").matcher(gitRepo); + } else if (gitRepo.get().contains("gitlab.com/") || gitRepo.get().contains("gitlab.com:")) { + Matcher matcher = Pattern.compile("(.*)gitlab\\.com[/|:](.*)").matcher(gitRepo.get()); if (matcher.matches()) { String rawRepoPath = matcher.group(2); String repoPath = rawRepoPath.endsWith(".git") ? rawRepoPath.substring(0, rawRepoPath.length() - 4) : rawRepoPath; @@ -353,24 +341,15 @@ private boolean isGitInstalled() { return execAndCheckSuccess("git", "--version"); } - private String getGitBranchName(Supplier gitCommand) { + private Optional getGitBranchNameFromEnv() { if (isJenkins() || isHudson()) { - Optional branch = Utils.envVariable("BRANCH_NAME", providers); - if (branch.isPresent()) { - return branch.get(); - } + return Utils.envVariable("BRANCH_NAME", providers); } else if (isGitLab()) { - Optional branch = Utils.envVariable("CI_COMMIT_REF_NAME", providers); - if (branch.isPresent()) { - return branch.get(); - } + return Utils.envVariable("CI_COMMIT_REF_NAME", providers); } else if (isAzurePipelines()) { - Optional branch = Utils.envVariable("BUILD_SOURCEBRANCH", providers); - if (branch.isPresent()) { - return branch.get(); - } + return Utils.envVariable("BUILD_SOURCEBRANCH", providers); } - return gitCommand.get(); + return Optional.empty(); } private boolean isJenkins() { diff --git a/src/main/java/com/gradle/GitMetadataResolver.java b/src/main/java/com/gradle/GitMetadataResolver.java new file mode 100644 index 00000000..0d9292d2 --- /dev/null +++ b/src/main/java/com/gradle/GitMetadataResolver.java @@ -0,0 +1,27 @@ +package com.gradle; + +import java.util.Optional; +import java.util.function.Supplier; + +class GitMetadataResolver { + private final boolean isGitInstalled; + + GitMetadataResolver(boolean isGitInstalled) { + this.isGitInstalled = isGitInstalled; + } + + Optional resolve(Supplier> fromGit) { + return resolve(null, fromGit); + } + + Optional resolve(Supplier> fromEnv, Supplier> fromGit) { + Optional resolved = Optional.empty(); + if (fromEnv != null) { + resolved = fromEnv.get().flatMap(str -> str.isEmpty() ? Optional.empty() : Optional.of(str)); + } + if (isGitInstalled && fromGit != null && !resolved.isPresent()) { + resolved = fromGit.get().flatMap(str -> str.isEmpty() ? Optional.empty() : Optional.of(str)); + } + return resolved; + } +} diff --git a/src/main/java/com/gradle/Utils.java b/src/main/java/com/gradle/Utils.java index a388e995..4985d8e4 100644 --- a/src/main/java/com/gradle/Utils.java +++ b/src/main/java/com/gradle/Utils.java @@ -162,7 +162,7 @@ static boolean execAndCheckSuccess(String... args) { } } - static String execAndGetStdOut(String... args) { + static Optional execAndGetStdOut(String... args) { Runtime runtime = Runtime.getRuntime(); Process process; try { @@ -177,7 +177,7 @@ static String execAndGetStdOut(String... args) { String ignore = readFully(error); boolean finished = process.waitFor(10, TimeUnit.SECONDS); - return finished && process.exitValue() == 0 ? trimAtEnd(standardText) : null; + return finished && process.exitValue() == 0 ? Optional.of(trimAtEnd(standardText)) : Optional.empty(); } } catch (IOException | InterruptedException e) { throw new RuntimeException(e); diff --git a/src/test/groovy/com/gradle/GitMetadataResolverTest.groovy b/src/test/groovy/com/gradle/GitMetadataResolverTest.groovy new file mode 100644 index 00000000..8e3e085a --- /dev/null +++ b/src/test/groovy/com/gradle/GitMetadataResolverTest.groovy @@ -0,0 +1,31 @@ +package com.gradle + +import spock.lang.Specification + +class GitMetadataResolverTest extends Specification { + def "Resolve from #label"() { + given: + def resolver = new GitMetadataResolver(isGitInstalled) + + when: + def resolved = fromEnv ? resolver.resolve(fromEnv, fromGit) : resolver.resolve(fromGit) + + then: + resolved == expected + + where: + label | isGitInstalled | fromGit | fromEnv | expected + 'nothing' | true | null | null | Optional.empty() + 'nothing, no CLI' | false | null | null | Optional.empty() + 'git only' | true | (() -> Optional.of('fromGit')) | null | Optional.of('fromGit') + 'git only, no CLI' | false | (() -> Optional.of('whatever')) | null | Optional.empty() + 'git blank' | true | (() -> Optional.of('')) | null | Optional.empty() + 'env only' | true | null | (() -> Optional.of('fromEnv')) | Optional.of('fromEnv') + 'env, git' | true | (() -> Optional.of('fromGit')) | (() -> Optional.of('fromEnv')) | Optional.of('fromEnv') + 'env, git, no CLI' | false | (() -> Optional.of('whatever')) | (() -> Optional.of('fromEnv')) | Optional.of('fromEnv') + 'env empty, git' | true | (() -> Optional.of('fromGit')) | (() -> Optional.empty()) | Optional.of('fromGit') + 'env empty, git, no CLI' | false | (() -> Optional.of('whatever')) | (() -> Optional.empty()) | Optional.empty() + 'env blank, git' | true | (() -> Optional.of('fromGit')) | (() -> Optional.of('')) | Optional.of('fromGit') + 'env blank, git, no CLI' | false | (() -> Optional.of('whatever')) | (() -> Optional.of('')) | Optional.empty() + } +}