From e830ee87bddf2908a6fb790c4caa1a4635eed1f3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 5 Apr 2024 15:57:11 +0100 Subject: [PATCH] Support com.gradle.develocity plugin in place of com.gradle.enterprise Closes gh-74 --- README.md | 8 +- build.gradle | 21 +-- gradle.properties | 2 +- ...nymousPublicationBuildScanConventions.java | 16 +- .../gradle/BuildScanConventions.java | 59 +++---- .../GradleEnterpriseConventionsPlugin.java | 20 +-- ...sPublicationBuildScanConventionsTests.java | 15 +- .../gradle/BuildScanConventionsTests.java | 71 ++++---- ...riseConventionsPluginIntegrationTests.java | 8 +- ...n.java => TestBuildScanConfiguration.java} | 164 ++++++------------ .../gradle/TestDevelocityConfiguration.java | 70 ++++++++ .../ge/conventions/gradle/TestProperty.java | 116 +++++++++++++ 12 files changed, 340 insertions(+), 230 deletions(-) rename src/test/java/io/spring/ge/conventions/gradle/{TestBuildScanExtension.java => TestBuildScanConfiguration.java} (51%) create mode 100644 src/test/java/io/spring/ge/conventions/gradle/TestDevelocityConfiguration.java create mode 100644 src/test/java/io/spring/ge/conventions/gradle/TestProperty.java diff --git a/README.md b/README.md index fc498a6..ae6d046 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The username and password environment variables should be set using the `gradle_ ## Build scan conventions -When applied alongside the [Gradle Enterprise Plugin](https://plugins.gradle.org/plugin/com.gradle.enterprise), the plugin will configure publishing of build scans to [ge.spring.io](https://ge.spring.io) when authenticated. +When applied alongside the [Develocity Plugin](https://plugins.gradle.org/plugin/com.gradle.develocity), the plugin will configure publishing of build scans to [ge.spring.io](https://ge.spring.io) when authenticated. The build scans will be customized to: - Add tags: @@ -59,7 +59,7 @@ The build scans will be customized to: - Add links: - `CI build` when building on Bamboo, GitHub Actions, or Jenkins, linking to the build on the CI server. - `Git commit build scans`, linking to scans for other builds of the same git commit. - - Enable capturing of task (Gradle) or goal (Maven) input files + - Enable capturing of file fingerprints - Upload build scans in the foreground when running on CI ### Build scan publishing credentials @@ -125,12 +125,12 @@ pluginManagement { In the example above, `gradlePluginPortal()` is declared to allow other plugins to continue to be resolved from the portal. -Now apply the plugin in `settings.gradle`, alongside the `com.gradle.enterprise` plugin: +Now apply the plugin in `settings.gradle`, alongside the `com.gradle.develocity` plugin: ```groovy plugins { // … - id "com.gradle.enterprise" version "<>" + id "com.gradle.develocity" version "<>" id "io.spring.ge.conventions" version "<>" // … } diff --git a/build.gradle b/build.gradle index d2fb1c1..432a701 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,6 @@ plugins { id "io.spring.javaformat" version "$javaFormatVersion" id "java-gradle-plugin" id "maven-publish" - id "io.spring.compatibility-test" version "0.0.2" } description = "Gradle Enterprise Conventions Gradle plugin" @@ -17,16 +16,12 @@ repositories { gradlePluginPortal() } -configurations { - compatibilityTestImplementation -} - dependencies { checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}") - compileOnly("com.gradle:gradle-enterprise-gradle-plugin:${gradleEnterprisePluginVersion}") + compileOnly("com.gradle:develocity-gradle-plugin:${gradleEnterprisePluginVersion}") - testImplementation("com.gradle:gradle-enterprise-gradle-plugin:${gradleEnterprisePluginVersion}") + testImplementation("com.gradle:develocity-gradle-plugin:${gradleEnterprisePluginVersion}") testImplementation("org.assertj:assertj-core:3.24.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testImplementation("org.mockito:mockito-core:4.11.0") @@ -43,18 +38,6 @@ gradlePlugin { } } -compatibilityTest { - useJUnitPlatform() - dependency('Gradle Enterprise Plugin') { gePlugin -> - gePlugin.groupId = 'com.gradle' - gePlugin.artifactId = 'gradle-enterprise-gradle-plugin' - gePlugin.versions = [ - '3.15.1', - '3.14.1' - ] - } -} - tasks.withType(Test) { testTask -> if (testTask.name.startsWith("compatibilityTest_")) { testTask.filter { diff --git a/gradle.properties b/gradle.properties index 75a2e5d..2cd7561 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ version=0.0.17-SNAPSHOT -gradleEnterprisePluginVersion=3.16.1 +gradleEnterprisePluginVersion=3.17 javaFormatVersion=0.0.39 diff --git a/src/main/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventions.java b/src/main/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventions.java index fd90e0d..3131146 100644 --- a/src/main/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventions.java +++ b/src/main/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventions.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,8 @@ import java.util.Map; -import com.gradle.scan.plugin.BuildScanExtension; +import com.gradle.develocity.agent.gradle.DevelocityConfiguration; +import com.gradle.develocity.agent.gradle.scan.BuildScanConfiguration; /** * Conventions for build scans that are published anonymously to @@ -28,16 +29,17 @@ */ public class AnonymousPublicationBuildScanConventions extends BuildScanConventions { - public AnonymousPublicationBuildScanConventions(ProcessRunner processRunner, Map env) { - super(processRunner, env); + public AnonymousPublicationBuildScanConventions(DevelocityConfiguration develocity, ProcessRunner processRunner, + Map env) { + super(develocity, processRunner, env); } - public AnonymousPublicationBuildScanConventions(ProcessRunner processRunner) { - super(processRunner); + public AnonymousPublicationBuildScanConventions(DevelocityConfiguration develocity, ProcessRunner processRunner) { + super(develocity, processRunner); } @Override - protected void configurePublishing(BuildScanExtension buildScan) { + protected void configurePublishing(BuildScanConfiguration buildScan) { // Use Gradle's defaults } diff --git a/src/main/java/io/spring/ge/conventions/gradle/BuildScanConventions.java b/src/main/java/io/spring/ge/conventions/gradle/BuildScanConventions.java index 243bf83..49f382e 100644 --- a/src/main/java/io/spring/ge/conventions/gradle/BuildScanConventions.java +++ b/src/main/java/io/spring/ge/conventions/gradle/BuildScanConventions.java @@ -23,30 +23,34 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import com.gradle.scan.plugin.BuildScanExtension; +import com.gradle.develocity.agent.gradle.DevelocityConfiguration; +import com.gradle.develocity.agent.gradle.scan.BuildScanConfiguration; import org.gradle.api.Action; /** - * {@link Action} that configures the {@link BuildScanExtension build scan} with Spring - * conventions. + * {@link Action} that configures the {@link BuildScanConfiguration build scan} with + * Spring conventions. * * @author Andy Wilkinson */ -class BuildScanConventions implements Action { +class BuildScanConventions implements Action { private static final String BAMBOO_RESULTS_ENV_VAR = "bamboo_resultsUrl"; private static final String CIRCLECI_BUILD_URL_ENV_VAR = "CIRCLE_BUILD_URL"; - private final Map env; + private final DevelocityConfiguration develocity; private final ProcessRunner processRunner; - BuildScanConventions(ProcessRunner processRunner) { - this(processRunner, System.getenv()); + private final Map env; + + BuildScanConventions(DevelocityConfiguration develocity, ProcessRunner processRunner) { + this(develocity, processRunner, System.getenv()); } - BuildScanConventions(ProcessRunner processRunner, Map env) { + BuildScanConventions(DevelocityConfiguration develocity, ProcessRunner processRunner, Map env) { + this.develocity = develocity; this.processRunner = processRunner; this.env = env; } @@ -56,21 +60,15 @@ class BuildScanConventions implements Action { * @param buildScan build scan to be configured */ @Override - @SuppressWarnings("deprecation") - public void execute(BuildScanExtension buildScan) { + public void execute(BuildScanConfiguration buildScan) { buildScan.obfuscation((obfuscation) -> obfuscation .ipAddresses((addresses) -> addresses.stream().map((address) -> "0.0.0.0").collect(Collectors.toList()))); configurePublishing(buildScan); tagBuildScan(buildScan); buildScan.background(this::addGitMetadata); addCiMetadata(buildScan); - buildScan.setUploadInBackground(!isCi()); - try { - buildScan.capture((settings) -> settings.setTaskInputFiles(true)); - } - catch (NoSuchMethodError ex) { - buildScan.setCaptureTaskInputFiles(true); - } + buildScan.getUploadInBackground().set(!isCi()); + buildScan.capture((settings) -> settings.getFileFingerprints().set(true)); } /** @@ -79,24 +77,18 @@ public void execute(BuildScanExtension buildScan) { * {@code https://ge.spring.io}. * @param buildScan build scan to configure */ - protected void configurePublishing(BuildScanExtension buildScan) { - buildScan.publishAlways(); - try { - buildScan.getClass().getMethod("publishIfAuthenticated").invoke(buildScan); - } - catch (Exception ex) { - throw new RuntimeException("Failed to invoke publishIfAuthenticated()", ex); - } - buildScan.setServer("https://ge.spring.io"); + protected void configurePublishing(BuildScanConfiguration buildScan) { + buildScan.publishing((publishing) -> publishing.onlyIf((context) -> context.isAuthenticated())); + this.develocity.getServer().set("https://ge.spring.io"); } - private void tagBuildScan(BuildScanExtension buildScan) { + private void tagBuildScan(BuildScanConfiguration buildScan) { tagCiOrLocal(buildScan); tagJdk(buildScan); tagOperatingSystem(buildScan); } - private void tagCiOrLocal(BuildScanExtension buildScan) { + private void tagCiOrLocal(BuildScanConfiguration buildScan) { buildScan.tag(isCi() ? "CI" : "Local"); } @@ -127,7 +119,7 @@ private boolean isGitHubActions() { return this.env.containsKey("GITHUB_ACTIONS"); } - private void tagJdk(BuildScanExtension buildScan) { + private void tagJdk(BuildScanConfiguration buildScan) { buildScan.tag("JDK-" + getJdkVersion()); } @@ -135,15 +127,16 @@ protected String getJdkVersion() { return System.getProperty("java.specification.version"); } - private void tagOperatingSystem(BuildScanExtension buildScan) { + private void tagOperatingSystem(BuildScanConfiguration buildScan) { buildScan.tag(System.getProperty("os.name")); } - private void addGitMetadata(BuildScanExtension buildScan) { + private void addGitMetadata(BuildScanConfiguration buildScan) { run("git", "rev-parse", "--short=8", "--verify", "HEAD").standardOut((gitCommitId) -> { String commitIdLabel = "Git commit"; buildScan.value(commitIdLabel, gitCommitId); - String server = buildScan.getServer(); + + String server = this.develocity.getServer().getOrNull(); if (server != null) { buildScan.link("Git commit build scans", server + createSearchUrl(commitIdLabel, gitCommitId)); } @@ -158,7 +151,7 @@ private void addGitMetadata(BuildScanExtension buildScan) { }); } - private void addCiMetadata(BuildScanExtension buildScan) { + private void addCiMetadata(BuildScanConfiguration buildScan) { if (isBamboo()) { buildScan.link("CI build", this.env.get(BAMBOO_RESULTS_ENV_VAR)); } diff --git a/src/main/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPlugin.java b/src/main/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPlugin.java index a6a3b24..02c8499 100644 --- a/src/main/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPlugin.java +++ b/src/main/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPlugin.java @@ -20,9 +20,9 @@ import javax.inject.Inject; -import com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension; -import com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin; -import com.gradle.scan.plugin.BuildScanExtension; +import com.gradle.develocity.agent.gradle.DevelocityConfiguration; +import com.gradle.develocity.agent.gradle.DevelocityPlugin; +import com.gradle.develocity.agent.gradle.scan.BuildScanConfiguration; import org.gradle.StartParameter; import org.gradle.api.Plugin; import org.gradle.api.initialization.Settings; @@ -45,9 +45,9 @@ public GradleEnterpriseConventionsPlugin(ProcessOperations processOperations) { @Override public void apply(Settings settings) { - settings.getPlugins().withType(GradleEnterprisePlugin.class, (plugin) -> { - GradleEnterpriseExtension extension = settings.getExtensions().getByType(GradleEnterpriseExtension.class); - configureBuildScanConventions(extension.getBuildScan(), settings.getStartParameter(), + settings.getPlugins().withType(DevelocityPlugin.class, (plugin) -> { + DevelocityConfiguration extension = settings.getExtensions().getByType(DevelocityConfiguration.class); + configureBuildScanConventions(extension, extension.getBuildScan(), settings.getStartParameter(), settings.getRootDir()); }); if (settings.getStartParameter().isBuildCacheEnabled()) { @@ -56,15 +56,15 @@ public void apply(Settings settings) { } } - private void configureBuildScanConventions(BuildScanExtension buildScan, StartParameter startParameter, - File rootDir) { + private void configureBuildScanConventions(DevelocityConfiguration develocity, BuildScanConfiguration buildScan, + StartParameter startParameter, File rootDir) { if (startParameter.isNoBuildScan() || containsPropertiesTask(startParameter)) { return; } ProcessOperationsProcessRunner processRunner = new ProcessOperationsProcessRunner( new WorkingDirectoryProcessOperations(this.processOperations, rootDir)); if (startParameter.isBuildScan()) { - new AnonymousPublicationBuildScanConventions(processRunner) { + new AnonymousPublicationBuildScanConventions(develocity, processRunner) { @Override protected String getJdkVersion() { @@ -75,7 +75,7 @@ protected String getJdkVersion() { }.execute(buildScan); } else { - new BuildScanConventions(processRunner) { + new BuildScanConventions(develocity, processRunner) { @Override protected String getJdkVersion() { diff --git a/src/test/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventionsTests.java b/src/test/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventionsTests.java index fc3238c..c869a13 100644 --- a/src/test/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventionsTests.java +++ b/src/test/java/io/spring/ge/conventions/gradle/AnonymousPublicationBuildScanConventionsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,19 +29,20 @@ class AnonymousPublicationBuildScanConventionsTests { private final TestProcessRunner processRunner = new TestProcessRunner(); - private final TestBuildScanExtension buildScan = new TestBuildScanExtension(); + private final TestDevelocityConfiguration develocity = new TestDevelocityConfiguration(); + + private final TestBuildScanConfiguration buildScan = new TestBuildScanConfiguration(); @Test void buildScansAreConfiguredToUseDefaultPublicationBehaviour() { - new AnonymousPublicationBuildScanConventions(this.processRunner).execute(this.buildScan); - assertThat(this.buildScan.publishAlways).isFalse(); - assertThat(this.buildScan.publishIfAuthenticated).isFalse(); + new AnonymousPublicationBuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); + assertThat(this.buildScan.publishing.predicate).isNull(); } @Test void buildScansAreConfiguredToPublishToDefaultServer() { - new AnonymousPublicationBuildScanConventions(this.processRunner).execute(this.buildScan); - assertThat(this.buildScan.server).isNull(); + new AnonymousPublicationBuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); + assertThat(this.develocity.getServer().getOrNull()).isNull(); } } diff --git a/src/test/java/io/spring/ge/conventions/gradle/BuildScanConventionsTests.java b/src/test/java/io/spring/ge/conventions/gradle/BuildScanConventionsTests.java index 47b4b7d..beff197 100644 --- a/src/test/java/io/spring/ge/conventions/gradle/BuildScanConventionsTests.java +++ b/src/test/java/io/spring/ge/conventions/gradle/BuildScanConventionsTests.java @@ -24,9 +24,12 @@ import java.util.List; import java.util.Map; +import com.gradle.develocity.agent.gradle.scan.BuildScanPublishingConfiguration.PublishingContext; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; /** * Tests for {@link BuildScanConventions}. @@ -37,17 +40,19 @@ class BuildScanConventionsTests { private final TestProcessRunner processRunner = new TestProcessRunner(); - private final TestBuildScanExtension buildScan = new TestBuildScanExtension(); + private final TestDevelocityConfiguration develocity = new TestDevelocityConfiguration(); + + private final TestBuildScanConfiguration buildScan = new TestBuildScanConfiguration(); @Test - void capturingOfTaskInputsIsEnabled() { - new BuildScanConventions(this.processRunner).execute(this.buildScan); - assertThat(this.buildScan.captureSettings.isTaskInputFiles()).isTrue(); + void capturingOfFileFingerprintsIsEnabled() { + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); + assertThat(this.buildScan.captureSettings.getFileFingerprints().get()).isTrue(); } @Test void ipAddressesAreObfuscated() throws UnknownHostException { - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.obfuscation.ipAddressesObfuscator).isNotNull(); List obfuscatedAddresses = this.buildScan.obfuscation.ipAddressesObfuscator .apply(Arrays.asList(InetAddress.getByName("10.0.0.1"), InetAddress.getByName("10.0.0.2"))); @@ -56,20 +61,23 @@ void ipAddressesAreObfuscated() throws UnknownHostException { @Test void buildScansAreConfiguredToAlwaysPublishWhenAuthenticated() { - new BuildScanConventions(this.processRunner).execute(this.buildScan); - assertThat(this.buildScan.publishAlways).isTrue(); - assertThat(this.buildScan.publishIfAuthenticated).isTrue(); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); + PublishingContext context = mock(PublishingContext.class); + given(context.isAuthenticated()).willReturn(true); + assertThat(this.buildScan.publishing.predicate.isSatisfiedBy(context)).isTrue(); + given(context.isAuthenticated()).willReturn(false); + assertThat(this.buildScan.publishing.predicate.isSatisfiedBy(context)).isFalse(); } @Test void buildScansAreConfiguredToPublishToGeSpringIo() { - new BuildScanConventions(this.processRunner).execute(this.buildScan); - assertThat(this.buildScan.server).isEqualTo("https://ge.spring.io"); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); + assertThat(this.develocity.getServer().get()).isEqualTo("https://ge.spring.io"); } @Test void whenBambooResultEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { - new BuildScanConventions(this.processRunner, + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("bamboo_resultsUrl", "https://bamboo.exampl.com")) .execute(this.buildScan); assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local"); @@ -77,7 +85,7 @@ void whenBambooResultEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { @Test void whenBambooResultEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() { - new BuildScanConventions(this.processRunner, + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("bamboo_resultsUrl", "https://bamboo.example.com")) .execute(this.buildScan); assertThat(this.buildScan.links).containsEntry("CI build", "https://bamboo.example.com"); @@ -85,7 +93,7 @@ void whenBambooResultEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() { @Test void whenCircleBuildUrlEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() { - new BuildScanConventions(this.processRunner, + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("CIRCLE_BUILD_URL", "https://circleci.example.com/gh/org/project/123")) .execute(this.buildScan); assertThat(this.buildScan.links).containsEntry("CI build", "https://circleci.example.com/gh/org/project/123"); @@ -96,19 +104,20 @@ void whenJenkinsUrlAndBuildUrlEnvVarsArePresentThenBuildScanHasACiBuildLinkToBui Map env = new HashMap<>(); env.put("JENKINS_URL", "https://jenkins.example.com"); env.put("BUILD_URL", "https://jenkins.example.com/builds/123"); - new BuildScanConventions(this.processRunner, env).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner, env).execute(this.buildScan); assertThat(this.buildScan.links).containsEntry("CI build", "https://jenkins.example.com/builds/123"); } @Test void whenCiEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { - new BuildScanConventions(this.processRunner, Collections.singletonMap("CI", null)).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("CI", null)) + .execute(this.buildScan); assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local"); } @Test void whenJenkinsUrlEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { - new BuildScanConventions(this.processRunner, + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("JENKINS_URL", "https://jenkins.example.com")) .execute(this.buildScan); assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local"); @@ -116,7 +125,8 @@ void whenJenkinsUrlEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { @Test void whenGitHubActionsEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() { - new BuildScanConventions(this.processRunner, Collections.singletonMap("GITHUB_ACTIONS", "true")) + new BuildScanConventions(this.develocity, this.processRunner, + Collections.singletonMap("GITHUB_ACTIONS", "true")) .execute(this.buildScan); assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local"); } @@ -128,32 +138,32 @@ void whenGitHubActionsEnvVarsArePresentThenBuildScanHasACiBuildLinkToIt() { env.put("GITHUB_SERVER_URL", "https://github.com"); env.put("GITHUB_REPOSITORY", "spring-projects/spring-boot"); env.put("GITHUB_RUN_ID", "1234567890"); - new BuildScanConventions(this.processRunner, env).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner, env).execute(this.buildScan); assertThat(this.buildScan.links).containsEntry("CI build", "https://github.com/spring-projects/spring-boot/actions/runs/1234567890"); } @Test void whenNoCiIndicatorsArePresentThenBuildScanIsTaggedWithLocalNotCi() { - new BuildScanConventions(this.processRunner, Collections.emptyMap()).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner, Collections.emptyMap()).execute(this.buildScan); assertThat(this.buildScan.tags).contains("Local").doesNotContain("CI"); } @Test void buildScanIsTaggedWithJdkVersion() { - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.tags).contains("JDK-" + System.getProperty("java.specification.version")); } @Test void buildScanIsTaggedWithOperatingSystem() { - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.tags).contains(System.getProperty("os.name")); } @Test void whenBranchEnvVarIsPresentThenBuildScanIsTaggedAndConfiguredWithCustomValue() { - new BuildScanConventions(this.processRunner, Collections.singletonMap("BRANCH", "1.1.x")) + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("BRANCH", "1.1.x")) .execute(this.buildScan); assertThat(this.buildScan.tags).contains("1.1.x"); assertThat(this.buildScan.values).containsEntry("Git branch", "1.1.x"); @@ -162,7 +172,7 @@ void whenBranchEnvVarIsPresentThenBuildScanIsTaggedAndConfiguredWithCustomValue( @Test void whenBranchEnvVarIsNotPresentThenBuildScanIsTaggedWithBranchFromGit() { this.processRunner.commandLineOutput.put(Arrays.asList("git", "rev-parse", "--abbrev-ref", "HEAD"), "1.2.x"); - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.tags).contains("1.2.x"); assertThat(this.buildScan.values).containsEntry("Git branch", "1.2.x"); } @@ -171,7 +181,7 @@ void whenBranchEnvVarIsNotPresentThenBuildScanIsTaggedWithBranchFromGit() { void buildScanHasGitCommitIdCustomValueAndLinkToBuildScansForTheSameCommit() { this.processRunner.commandLineOutput.put(Arrays.asList("git", "rev-parse", "--short=8", "--verify", "HEAD"), "79ce52f8"); - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.values).containsEntry("Git commit", "79ce52f8"); assertThat(this.buildScan.links).containsEntry("Git commit build scans", "https://ge.spring.io/scans?search.names=Git+commit&search.values=79ce52f8"); @@ -180,7 +190,7 @@ void buildScanHasGitCommitIdCustomValueAndLinkToBuildScansForTheSameCommit() { @Test void whenGitStatusIsCleanThenBuildScanIsNotTaggedDirtyAndHasNotGitStatusCustomValue() { this.processRunner.commandLineOutput.put(Arrays.asList("git", "status", "--porcelain"), ""); - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.tags).doesNotContain("dirty"); assertThat(this.buildScan.values).doesNotContainKey("Git status"); } @@ -188,21 +198,22 @@ void whenGitStatusIsCleanThenBuildScanIsNotTaggedDirtyAndHasNotGitStatusCustomVa @Test void whenGitStatusIsDirtyThenBuildScanIsTaggedDirtyAndHasGitStatusCustomValue() { this.processRunner.commandLineOutput.put(Arrays.asList("git", "status", "--porcelain"), " M build.gradle"); - new BuildScanConventions(this.processRunner).execute(this.buildScan); + new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan); assertThat(this.buildScan.tags).contains("dirty"); assertThat(this.buildScan.values).containsEntry("Git status", "M build.gradle"); } @Test void whenBuildingLocallyThenBackgroundUploadIsEnabled() { - new BuildScanConventions(this.processRunner, Collections.emptyMap()).execute(this.buildScan); - assertThat(this.buildScan.uploadInBackground).isTrue(); + new BuildScanConventions(this.develocity, this.processRunner, Collections.emptyMap()).execute(this.buildScan); + assertThat(this.buildScan.uploadInBackground.get()).isTrue(); } @Test void whenBuildingOnCiThenBackgroundUploadIsDisabled() { - new BuildScanConventions(this.processRunner, Collections.singletonMap("CI", null)).execute(this.buildScan); - assertThat(this.buildScan.uploadInBackground).isFalse(); + new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("CI", null)) + .execute(this.buildScan); + assertThat(this.buildScan.uploadInBackground.get()).isFalse(); } } diff --git a/src/test/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPluginIntegrationTests.java b/src/test/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPluginIntegrationTests.java index d189117..85d5cd2 100644 --- a/src/test/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPluginIntegrationTests.java +++ b/src/test/java/io/spring/ge/conventions/gradle/GradleEnterpriseConventionsPluginIntegrationTests.java @@ -27,7 +27,7 @@ import java.util.Properties; import java.util.function.Consumer; -import com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin; +import com.gradle.develocity.agent.gradle.DevelocityPlugin; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; import org.junit.jupiter.api.Test; @@ -102,7 +102,7 @@ private void prepareProject(File projectDir) { write(new File(projectDir, "gradle.properties"), (writer) -> writer.println("org.gradle.caching=true")); write(new File(projectDir, "settings.gradle"), (writer) -> { writer.println("plugins {"); - writer.println(" id 'com.gradle.enterprise'"); + writer.println(" id 'com.gradle.develocity'"); writer.println(" id 'io.spring.ge.conventions' version '" + version() + "'"); writer.println("}"); writer.println("gradle.afterProject { project -> project.ext['settings'] = settings }"); @@ -127,7 +127,7 @@ private void prepareMultiModuleProject(File projectDir) { write(new File(projectDir, "gradle.properties"), (writer) -> writer.println("org.gradle.caching=true")); write(new File(projectDir, "settings.gradle"), (writer) -> { writer.println("plugins {"); - writer.println(" id 'com.gradle.enterprise'"); + writer.println(" id 'com.gradle.develocity'"); writer.println(" id 'io.spring.ge.conventions' version '" + version() + "'"); writer.println("}"); writer.println("include 'sub'"); @@ -173,7 +173,7 @@ private String version() { private BuildResult build(File projectDir, String gradleVersion, String... arguments) { List classpath = Arrays.asList(new File("bin/main"), new File("build/classes/java/main"), new File("build/resources/main"), - new File(GradleEnterprisePlugin.class.getProtectionDomain().getCodeSource().getLocation().getFile())); + new File(DevelocityPlugin.class.getProtectionDomain().getCodeSource().getLocation().getFile())); return GradleRunner.create() .withGradleVersion(gradleVersion) .withProjectDir(projectDir) diff --git a/src/test/java/io/spring/ge/conventions/gradle/TestBuildScanExtension.java b/src/test/java/io/spring/ge/conventions/gradle/TestBuildScanConfiguration.java similarity index 51% rename from src/test/java/io/spring/ge/conventions/gradle/TestBuildScanExtension.java rename to src/test/java/io/spring/ge/conventions/gradle/TestBuildScanConfiguration.java index d2fff2b..3ee1115 100644 --- a/src/test/java/io/spring/ge/conventions/gradle/TestBuildScanExtension.java +++ b/src/test/java/io/spring/ge/conventions/gradle/TestBuildScanConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,19 +23,22 @@ import java.util.Map; import java.util.function.Function; -import com.gradle.scan.plugin.BuildResult; -import com.gradle.scan.plugin.BuildScanCaptureSettings; -import com.gradle.scan.plugin.BuildScanDataObfuscation; -import com.gradle.scan.plugin.BuildScanExtension; -import com.gradle.scan.plugin.PublishedBuildScan; +import com.gradle.develocity.agent.gradle.scan.BuildResult; +import com.gradle.develocity.agent.gradle.scan.BuildScanCaptureConfiguration; +import com.gradle.develocity.agent.gradle.scan.BuildScanConfiguration; +import com.gradle.develocity.agent.gradle.scan.BuildScanDataObfuscationConfiguration; +import com.gradle.develocity.agent.gradle.scan.BuildScanPublishingConfiguration; +import com.gradle.develocity.agent.gradle.scan.PublishedBuildScan; import org.gradle.api.Action; +import org.gradle.api.provider.Property; +import org.gradle.api.specs.Spec; /** - * A {@link BuildScanExtension} used for unit testing. + * A {@link BuildScanConfiguration} used for unit testing. * * @author Andy Wilkinson */ -public final class TestBuildScanExtension implements BuildScanExtension { +public final class TestBuildScanConfiguration implements BuildScanConfiguration { final TestBuildScanDataObfuscation obfuscation = new TestBuildScanDataObfuscation(); @@ -47,59 +50,9 @@ public final class TestBuildScanExtension implements BuildScanExtension { final TestBuildScanCaptureSettings captureSettings = new TestBuildScanCaptureSettings(); - boolean publishAlways; + final TestBuildScanPublishingConfiguration publishing = new TestBuildScanPublishingConfiguration(); - boolean publishIfAuthenticated; - - String server; - - boolean uploadInBackground = true; - - @Override - public void background(Action action) { - action.execute(this); - } - - @Override - public void buildFinished(Action action) { - throw new UnsupportedOperationException(); - } - - @Override - public void buildScanPublished(Action action) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getAllowUntrustedServer() { - throw new UnsupportedOperationException(); - } - - @Override - public BuildScanDataObfuscation getObfuscation() { - return this.obfuscation; - } - - @Override - public String getServer() { - return this.server; - } - - @Override - public String getTermsOfServiceAgree() { - throw new UnsupportedOperationException(); - } - - @Override - public String getTermsOfServiceUrl() { - throw new UnsupportedOperationException(); - } - - @Override - @Deprecated - public boolean isCaptureTaskInputFiles() { - return this.captureSettings.isTaskInputFiles(); - } + final Property uploadInBackground = new TestProperty<>(); @Override public void link(String name, String url) { @@ -107,91 +60,76 @@ public void link(String name, String url) { } @Override - public void obfuscation(Action action) { - action.execute(this.obfuscation); - } - - @Override - public void publishAlways() { - this.publishAlways = true; - } - - public void publishIfAuthenticated() { - this.publishIfAuthenticated = true; + public void tag(String tag) { + this.tags.add(tag); } @Override - public void publishAlwaysIf(boolean condition) { - throw new UnsupportedOperationException(); + public void value(String name, String value) { + this.values.put(name, value); } @Override - public void publishOnFailure() { - throw new UnsupportedOperationException(); + public void background(Action action) { + action.execute(this); } @Override - public void publishOnFailureIf(boolean condition) { + public void buildFinished(Action action) { throw new UnsupportedOperationException(); } @Override - public void setAllowUntrustedServer(boolean allow) { + public void buildScanPublished(Action action) { throw new UnsupportedOperationException(); } @Override - @Deprecated - public void setCaptureTaskInputFiles(boolean capture) { - this.captureSettings.setTaskInputFiles(capture); - } - - @Override - public void setServer(String server) { - this.server = server; + public void capture(Action action) { + action.execute(this.captureSettings); } @Override - public void setTermsOfServiceAgree(String agree) { + public BuildScanCaptureConfiguration getCapture() { throw new UnsupportedOperationException(); } @Override - public void setTermsOfServiceUrl(String termsOfServiceUrl) { + public BuildScanDataObfuscationConfiguration getObfuscation() { throw new UnsupportedOperationException(); } @Override - public void tag(String tag) { - this.tags.add(tag); + public TestBuildScanPublishingConfiguration getPublishing() { + return this.publishing; } @Override - public void value(String name, String value) { - this.values.put(name, value); + public Property getTermsOfUseAgree() { + throw new UnsupportedOperationException(); } @Override - public boolean isUploadInBackground() { + public Property getTermsOfUseUrl() { throw new UnsupportedOperationException(); } @Override - public void setUploadInBackground(boolean uploadInBackground) { - this.uploadInBackground = uploadInBackground; + public Property getUploadInBackground() { + return this.uploadInBackground; } @Override - public void capture(Action action) { - action.execute(this.captureSettings); + public void obfuscation(Action action) { + action.execute(this.obfuscation); } @Override - public BuildScanCaptureSettings getCapture() { - throw new UnsupportedOperationException(); + public void publishing(Action action) { + action.execute(this.publishing); } - static final class TestBuildScanDataObfuscation implements BuildScanDataObfuscation { + static final class TestBuildScanDataObfuscation implements BuildScanDataObfuscationConfiguration { Function, ? extends List> ipAddressesObfuscator; @@ -212,38 +150,34 @@ public void username(Function obfuscator) { } - static final class TestBuildScanCaptureSettings implements BuildScanCaptureSettings { + static final class TestBuildScanCaptureSettings implements BuildScanCaptureConfiguration { - private boolean taskInputFiles; + final Property fileFingerprints = new TestProperty<>(); @Override - public boolean isBuildLogging() { + public Property getBuildLogging() { throw new UnsupportedOperationException(); } @Override - public boolean isTaskInputFiles() { - return this.taskInputFiles; + public Property getFileFingerprints() { + return this.fileFingerprints; } @Override - public boolean isTestLogging() { + public Property getTestLogging() { throw new UnsupportedOperationException(); } - @Override - public void setBuildLogging(boolean capture) { - throw new UnsupportedOperationException(); - } + } - @Override - public void setTaskInputFiles(boolean capture) { - this.taskInputFiles = capture; - } + static final class TestBuildScanPublishingConfiguration implements BuildScanPublishingConfiguration { + + Spec predicate; @Override - public void setTestLogging(boolean capture) { - throw new UnsupportedOperationException(); + public void onlyIf(Spec predicate) { + this.predicate = predicate; } } diff --git a/src/test/java/io/spring/ge/conventions/gradle/TestDevelocityConfiguration.java b/src/test/java/io/spring/ge/conventions/gradle/TestDevelocityConfiguration.java new file mode 100644 index 0000000..de5e2a7 --- /dev/null +++ b/src/test/java/io/spring/ge/conventions/gradle/TestDevelocityConfiguration.java @@ -0,0 +1,70 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.ge.conventions.gradle; + +import com.gradle.develocity.agent.gradle.DevelocityConfiguration; +import com.gradle.develocity.agent.gradle.buildcache.DevelocityBuildCache; +import com.gradle.develocity.agent.gradle.scan.BuildScanConfiguration; +import org.gradle.api.Action; +import org.gradle.api.provider.Property; + +/** + * {@link DevelocityConfiguration} implementation used for unit testing. + * + * @author Andy Wilkinson + */ +class TestDevelocityConfiguration implements DevelocityConfiguration { + + final TestProperty server = new TestProperty<>(); + + @Override + public void buildScan(Action action) { + throw new UnsupportedOperationException(); + } + + @Override + public Property getAccessKey() { + throw new UnsupportedOperationException(); + } + + @Override + public Property getAllowUntrustedServer() { + throw new UnsupportedOperationException(); + } + + @Override + public Class getBuildCache() { + throw new UnsupportedOperationException(); + } + + @Override + public BuildScanConfiguration getBuildScan() { + throw new UnsupportedOperationException(); + } + + @Override + public Property getProjectId() { + throw new UnsupportedOperationException(); + } + + @Override + public Property getServer() { + return this.server; + + } + +} diff --git a/src/test/java/io/spring/ge/conventions/gradle/TestProperty.java b/src/test/java/io/spring/ge/conventions/gradle/TestProperty.java new file mode 100644 index 0000000..44df004 --- /dev/null +++ b/src/test/java/io/spring/ge/conventions/gradle/TestProperty.java @@ -0,0 +1,116 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.ge.conventions.gradle; + +import org.gradle.api.Transformer; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; + +/** + * {@link Property} implementation for use in unit tests. + * + * @param type of the value of the property + * @author Andy Wilkinson + */ +public class TestProperty implements Property { + + private T value; + + @Override + public Provider flatMap(Transformer, ? super T> arg0) { + throw new UnsupportedOperationException(); + } + + @Override + public T get() { + if (this.value != null) { + return this.value; + } + throw new IllegalStateException(); + } + + @Override + public T getOrElse(T fallback) { + throw new UnsupportedOperationException(); + } + + @Override + public T getOrNull() { + return this.value; + } + + @Override + public boolean isPresent() { + throw new UnsupportedOperationException(); + } + + @Override + public Provider map(Transformer transformer) { + throw new UnsupportedOperationException(); + } + + @Override + public Provider orElse(T fallback) { + throw new UnsupportedOperationException(); + } + + @Override + public Provider orElse(Provider fallback) { + throw new UnsupportedOperationException(); + } + + @Override + public void disallowChanges() { + throw new UnsupportedOperationException(); + } + + @Override + public Property convention(T convention) { + throw new UnsupportedOperationException(); + } + + @Override + public Property convention(Provider convention) { + throw new UnsupportedOperationException(); + } + + @Override + public void finalizeValue() { + throw new UnsupportedOperationException(); + } + + @Override + public void set(T value) { + this.value = value; + } + + @Override + public void set(Provider value) { + throw new UnsupportedOperationException(); + } + + @Override + public Property value(T value) { + throw new UnsupportedOperationException(); + } + + @Override + public Property value(Provider value) { + throw new UnsupportedOperationException(); + } + +}