diff --git a/src/main/java/io/quarkus/develocity/project/Log.java b/src/main/java/io/quarkus/develocity/project/Log.java index 0028285..8c3e399 100644 --- a/src/main/java/io/quarkus/develocity/project/Log.java +++ b/src/main/java/io/quarkus/develocity/project/Log.java @@ -19,10 +19,18 @@ public static void error(String message) { LOGGER.error(message); } + public static void error(String message, Throwable e) { + LOGGER.error(message, e); + } + public static void warn(String message) { LOGGER.warn(message); } + public static void warn(String message, Throwable e) { + LOGGER.warn(message, e); + } + public static void info(String message) { LOGGER.info(message); } @@ -39,10 +47,18 @@ public static void error(String pluginName, String message) { LOGGER.error("[" + pluginName + "] " + message); } + public static void error(String pluginName, String message, Throwable e) { + LOGGER.error("[" + pluginName + "] " + message, e); + } + public static void warn(String pluginName, String message) { LOGGER.warn("[" + pluginName + "] " + message); } + public static void warn(String pluginName, String message, Throwable e) { + LOGGER.warn("[" + pluginName + "] " + message, e); + } + public static void info(String pluginName, String message) { LOGGER.info("[" + pluginName + "] " + message); } diff --git a/src/main/java/io/quarkus/develocity/project/QuarkusProjectBuildCacheGradleEnterpriseListener.java b/src/main/java/io/quarkus/develocity/project/QuarkusProjectBuildCacheGradleEnterpriseListener.java index b8f71c5..ef2a7f3 100644 --- a/src/main/java/io/quarkus/develocity/project/QuarkusProjectBuildCacheGradleEnterpriseListener.java +++ b/src/main/java/io/quarkus/develocity/project/QuarkusProjectBuildCacheGradleEnterpriseListener.java @@ -1,5 +1,8 @@ package io.quarkus.develocity.project; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -9,18 +12,21 @@ import com.gradle.maven.extension.api.GradleEnterpriseApi; import com.gradle.maven.extension.api.GradleEnterpriseListener; import com.gradle.maven.extension.api.cache.BuildCacheApi; - -import io.quarkus.develocity.project.goals.CompilerConfiguredPlugin; -import io.quarkus.develocity.project.goals.EnforcerConfiguredPlugin; -import io.quarkus.develocity.project.goals.FailsafeConfiguredPlugin; -import io.quarkus.develocity.project.goals.FormatterConfiguredPlugin; -import io.quarkus.develocity.project.goals.ImpsortConfiguredPlugin; -import io.quarkus.develocity.project.goals.KotlinConfiguredPlugin; -import io.quarkus.develocity.project.goals.QuarkusConfiguredPlugin; -import io.quarkus.develocity.project.goals.SourceConfiguredPlugin; -import io.quarkus.develocity.project.goals.SpotlessConfiguredPlugin; -import io.quarkus.develocity.project.goals.SurefireConfiguredPlugin; -import io.quarkus.develocity.project.util.Matchers; +import com.gradle.maven.scan.extension.internal.api.BuildScanApiInternal; + +import io.quarkus.develocity.project.normalization.Normalization; +import io.quarkus.develocity.project.plugins.CompilerConfiguredPlugin; +import io.quarkus.develocity.project.plugins.EnforcerConfiguredPlugin; +import io.quarkus.develocity.project.plugins.FailsafeConfiguredPlugin; +import io.quarkus.develocity.project.plugins.FormatterConfiguredPlugin; +import io.quarkus.develocity.project.plugins.ImpsortConfiguredPlugin; +import io.quarkus.develocity.project.plugins.KotlinConfiguredPlugin; +import io.quarkus.develocity.project.plugins.QuarkusConfiguredPlugin; +import io.quarkus.develocity.project.plugins.SourceConfiguredPlugin; +import io.quarkus.develocity.project.plugins.SpotlessConfiguredPlugin; +import io.quarkus.develocity.project.plugins.SurefireConfiguredPlugin; +import io.quarkus.develocity.project.scan.BuildScanMetadata; +import io.quarkus.develocity.project.scan.MavenVersionChecker; @SuppressWarnings("deprecation") @Component(role = GradleEnterpriseListener.class, hint = "quarkus-project-build-cache", description = "Configures the build cache of the Quarkus project") @@ -29,60 +35,48 @@ public class QuarkusProjectBuildCacheGradleEnterpriseListener implements GradleE private static final String QUICKLY = "-Dquickly"; private static final String DASH = "-"; + private static final List NESTED_PROJECTS_PATHS = List.of( + File.separator + "target" + File.separator + "codestart-test" + File.separator, + File.separator + "target" + File.separator + "it" + File.separator, + File.separator + "target" + File.separator + "test-classes" + File.separator, + File.separator + "target" + File.separator + "test-project" + File.separator); + @Override public void configure(GradleEnterpriseApi gradleEnterpriseApi, MavenSession mavenSession) throws Exception { + if (ignoreProject(mavenSession)) { + // do not publish a build scan for test builds + Log.debug("Disabling build scan publication and build cache for nested project: " + + mavenSession.getRequest().getBaseDirectory()); + + gradleEnterpriseApi.getBuildScan().publishAlwaysIf(false); + gradleEnterpriseApi.getBuildScan().publishOnFailureIf(false); + gradleEnterpriseApi.getBuildCache().getLocal().setEnabled(false); + gradleEnterpriseApi.getBuildCache().getLocal().setStoreEnabled(false); + gradleEnterpriseApi.getBuildCache().getRemote().setEnabled(false); + gradleEnterpriseApi.getBuildCache().getRemote().setStoreEnabled(false); + + if (System.getenv("GITHUB_ACTIONS") != null) { + try { + Path storageLocationTmpDir = Files.createTempDirectory(Path.of(System.getenv("RUNNER_TEMP")), + "buildScanTmp"); + Log.debug("Update storage location to " + storageLocationTmpDir); + gradleEnterpriseApi.setStorageDirectory(storageLocationTmpDir); + } catch (IOException e) { + Log.error("Temporary storage location directory cannot be created, the Build Scan will be published", e); + } + } + + return; + } + + gradleEnterpriseApi.getBuildScan().publishAlways(); + ((BuildScanApiInternal) gradleEnterpriseApi.getBuildScan()).publishIfAuthenticated(); + BuildScanMetadata.addMetadataToBuildScan(gradleEnterpriseApi.getBuildScan()); + MavenVersionChecker.checkRuntimeMavenVersion(gradleEnterpriseApi.getBuildScan(), mavenSession); + workaroundQuickly(gradleEnterpriseApi.getBuildCache()); - // System properties - gradleEnterpriseApi.getBuildCache().registerNormalizationProvider( - context -> context.configureSystemPropertiesNormalization(s -> { - s.addIgnoredKeys("maven.repo.local", "maven.settings"); - - if (Matchers.directory(context, Path.of("docs"))) { - s.addIgnoredKeys("vale.dir", "git.dir"); - } - - if (Matchers.directory(context, Path.of("independent-projects", "arc", "tcks", "cdi-tck-runner"))) { - s.addIgnoredKeys("org.jboss.cdi.tck.libraryDirectory"); - } - - if (Matchers.directory(context, Path.of("integration-tests"))) { - s.addIgnoredKeys("native.image.path", "quarkus.kubernetes-service-binding.root"); - } - - if (Matchers.module(context, "quarkus-integration-test-rest-client")) { - s.addIgnoredKeys("javax.net.ssl.trustStore", "rest-client.trustStore"); - } - - if (Matchers.module(context, "quarkus-integration-test-test-extension")) { - s.addIgnoredKeys("classpathEntriesRecordingFile"); - } - })); - - // Application.properties - gradleEnterpriseApi.getBuildCache().registerNormalizationProvider( - context -> context.configureRuntimeClasspathNormalization(c -> { - c.addIgnoredFiles("META-INF/ide-deps/**"); - - if (Matchers.module(context, "quarkus-integration-test-rest-client-reactive")) { - c.addPropertiesNormalization("application.properties", "quarkus.rest-client.self-signed.trust-store", - "quarkus.rest-client.wrong-host.trust-store", - "quarkus.rest-client.wrong-host-rejected.trust-store"); - } - - if (Matchers.module(context, "quarkus-integration-test-oidc-client-reactive")) { - c.addPropertiesNormalization("application.properties", "quarkus.keycloak.devservices.realm-path"); - } - - if (Matchers.module(context, "quarkus-integration-test-test-extension")) { - c.addPropertiesNormalization("application.properties", "quarkus.bt.classpath-recording.record-file", - "%test.quarkus.bt.classpath-recording.record-file"); - } - - if (Matchers.module(context, "quarkus-integration-test-gradle-plugin")) { - c.addIgnoredFiles(".quarkus/config.yml"); - } - })); + Normalization.configureNormalization(gradleEnterpriseApi.getBuildCache()); List configuredGoals = List.of( new CompilerConfiguredPlugin(), @@ -145,4 +139,18 @@ private static void workaroundQuickly(BuildCacheApi buildCacheApi) { buildCacheApi.setRequireClean(false); } } + + private static boolean ignoreProject(MavenSession mavenSession) { + if (mavenSession == null || mavenSession.getRequest() == null || mavenSession.getRequest().getBaseDirectory() == null) { + return false; + } + + for (String nestedProjectsPath : NESTED_PROJECTS_PATHS) { + if (mavenSession.getRequest().getBaseDirectory().contains(nestedProjectsPath)) { + return true; + } + } + + return false; + } } diff --git a/src/main/java/io/quarkus/develocity/project/SimpleQuarkusConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/SimpleQuarkusConfiguredPlugin.java index 7fec6ff..9da80c9 100644 --- a/src/main/java/io/quarkus/develocity/project/SimpleQuarkusConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/SimpleQuarkusConfiguredPlugin.java @@ -18,19 +18,6 @@ public abstract class SimpleQuarkusConfiguredPlugin implements ConfiguredPlugin @Override public void configureBuildCache(GradleEnterpriseApi gradleEnterpriseApi, MavenSession mavenSession) { - NormalizationProvider normalizationProvider = getNormalizationProvider(); - - if (normalizationProvider != null) { - gradleEnterpriseApi.getBuildCache().registerNormalizationProvider(context -> { - if (!isBuildCacheEnabled(context.getProject())) { - Log.debug(getPluginName(), "Build cache is disabled."); - return; - } else { - Log.debug(getPluginName(), "Build cache is enabled. Configuring normalization provider."); - } - normalizationProvider.configureNormalization(context); - }); - } gradleEnterpriseApi.getBuildCache().registerMojoMetadataProvider(context -> { context.withPlugin(getPluginName(), () -> { if (!isBuildCacheEnabled(context.getProject())) { @@ -58,10 +45,6 @@ protected boolean isBuildCacheEnabled(MavenProject project) { return true; } - protected NormalizationProvider getNormalizationProvider() { - return null; - } - protected abstract Map getGoalMetadataProviders(); protected static void dependsOnGav(MojoMetadataProvider.Context.Inputs inputs, MojoMetadataProvider.Context context) { diff --git a/src/main/java/io/quarkus/develocity/project/normalization/Normalization.java b/src/main/java/io/quarkus/develocity/project/normalization/Normalization.java new file mode 100644 index 0000000..c59cd2b --- /dev/null +++ b/src/main/java/io/quarkus/develocity/project/normalization/Normalization.java @@ -0,0 +1,66 @@ +package io.quarkus.develocity.project.normalization; + +import java.nio.file.Path; + +import com.gradle.maven.extension.api.cache.BuildCacheApi; + +import io.quarkus.develocity.project.util.Matchers; + +public final class Normalization { + + private Normalization() { + } + + public static void configureNormalization(BuildCacheApi buildCacheApi) { + // System properties + buildCacheApi.registerNormalizationProvider( + context -> context.configureSystemPropertiesNormalization(s -> { + s.addIgnoredKeys("maven.repo.local", "maven.settings"); + + if (Matchers.directory(context, Path.of("docs"))) { + s.addIgnoredKeys("vale.dir", "git.dir"); + } + + if (Matchers.directory(context, Path.of("independent-projects", "arc", "tcks", "cdi-tck-runner"))) { + s.addIgnoredKeys("org.jboss.cdi.tck.libraryDirectory"); + } + + if (Matchers.directory(context, Path.of("integration-tests"))) { + s.addIgnoredKeys("native.image.path", "quarkus.kubernetes-service-binding.root"); + } + + if (Matchers.module(context, "quarkus-integration-test-rest-client")) { + s.addIgnoredKeys("javax.net.ssl.trustStore", "rest-client.trustStore"); + } + + if (Matchers.module(context, "quarkus-integration-test-test-extension")) { + s.addIgnoredKeys("classpathEntriesRecordingFile"); + } + })); + + // Application.properties + buildCacheApi.registerNormalizationProvider( + context -> context.configureRuntimeClasspathNormalization(c -> { + c.addIgnoredFiles("META-INF/ide-deps/**"); + + if (Matchers.module(context, "quarkus-integration-test-rest-client-reactive")) { + c.addPropertiesNormalization("application.properties", "quarkus.rest-client.self-signed.trust-store", + "quarkus.rest-client.wrong-host.trust-store", + "quarkus.rest-client.wrong-host-rejected.trust-store"); + } + + if (Matchers.module(context, "quarkus-integration-test-oidc-client-reactive")) { + c.addPropertiesNormalization("application.properties", "quarkus.keycloak.devservices.realm-path"); + } + + if (Matchers.module(context, "quarkus-integration-test-test-extension")) { + c.addPropertiesNormalization("application.properties", "quarkus.bt.classpath-recording.record-file", + "%test.quarkus.bt.classpath-recording.record-file"); + } + + if (Matchers.module(context, "quarkus-integration-test-gradle-plugin")) { + c.addIgnoredFiles(".quarkus/config.yml"); + } + })); + } +} diff --git a/src/main/java/io/quarkus/develocity/project/goals/CompilerConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/CompilerConfiguredPlugin.java similarity index 97% rename from src/main/java/io/quarkus/develocity/project/goals/CompilerConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/CompilerConfiguredPlugin.java index bc02c81..b94ca3f 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/CompilerConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/CompilerConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.nio.file.Path; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/EnforcerConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/EnforcerConfiguredPlugin.java similarity index 97% rename from src/main/java/io/quarkus/develocity/project/goals/EnforcerConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/EnforcerConfiguredPlugin.java index 49f8d97..8a0680f 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/EnforcerConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/EnforcerConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/io/quarkus/develocity/project/goals/FailsafeConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/FailsafeConfiguredPlugin.java similarity index 97% rename from src/main/java/io/quarkus/develocity/project/goals/FailsafeConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/FailsafeConfiguredPlugin.java index e2c5c06..4e5629e 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/FailsafeConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/FailsafeConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.nio.file.Path; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/FormatterConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/FormatterConfiguredPlugin.java similarity index 98% rename from src/main/java/io/quarkus/develocity/project/goals/FormatterConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/FormatterConfiguredPlugin.java index 12944dc..58aad34 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/FormatterConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/FormatterConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/ImpsortConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/ImpsortConfiguredPlugin.java similarity index 98% rename from src/main/java/io/quarkus/develocity/project/goals/ImpsortConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/ImpsortConfiguredPlugin.java index 88d07fb..04856e0 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/ImpsortConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/ImpsortConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/KotlinConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/KotlinConfiguredPlugin.java similarity index 99% rename from src/main/java/io/quarkus/develocity/project/goals/KotlinConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/KotlinConfiguredPlugin.java index a6c5afa..0870098 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/KotlinConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/KotlinConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/QuarkusConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/QuarkusConfiguredPlugin.java similarity index 99% rename from src/main/java/io/quarkus/develocity/project/goals/QuarkusConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/QuarkusConfiguredPlugin.java index 16bc0f2..9cd41a5 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/QuarkusConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/QuarkusConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/io/quarkus/develocity/project/goals/QuarkusExtensionConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/QuarkusExtensionConfiguredPlugin.java similarity index 98% rename from src/main/java/io/quarkus/develocity/project/goals/QuarkusExtensionConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/QuarkusExtensionConfiguredPlugin.java index 1724afc..3f528bf 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/QuarkusExtensionConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/QuarkusExtensionConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/SourceConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/SourceConfiguredPlugin.java similarity index 97% rename from src/main/java/io/quarkus/develocity/project/goals/SourceConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/SourceConfiguredPlugin.java index a4e50fe..f36b2a1 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/SourceConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/SourceConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; import java.util.stream.Collectors; diff --git a/src/main/java/io/quarkus/develocity/project/goals/SpotlessConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/SpotlessConfiguredPlugin.java similarity index 98% rename from src/main/java/io/quarkus/develocity/project/goals/SpotlessConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/SpotlessConfiguredPlugin.java index bd182e5..21e71b3 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/SpotlessConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/SpotlessConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/goals/SurefireConfiguredPlugin.java b/src/main/java/io/quarkus/develocity/project/plugins/SurefireConfiguredPlugin.java similarity index 97% rename from src/main/java/io/quarkus/develocity/project/goals/SurefireConfiguredPlugin.java rename to src/main/java/io/quarkus/develocity/project/plugins/SurefireConfiguredPlugin.java index df0885e..e399c5f 100644 --- a/src/main/java/io/quarkus/develocity/project/goals/SurefireConfiguredPlugin.java +++ b/src/main/java/io/quarkus/develocity/project/plugins/SurefireConfiguredPlugin.java @@ -1,4 +1,4 @@ -package io.quarkus.develocity.project.goals; +package io.quarkus.develocity.project.plugins; import java.nio.file.Path; import java.util.Map; diff --git a/src/main/java/io/quarkus/develocity/project/scan/BuildScanMetadata.java b/src/main/java/io/quarkus/develocity/project/scan/BuildScanMetadata.java new file mode 100644 index 0000000..c9c0313 --- /dev/null +++ b/src/main/java/io/quarkus/develocity/project/scan/BuildScanMetadata.java @@ -0,0 +1,109 @@ +package io.quarkus.develocity.project.scan; + +import static io.quarkus.develocity.project.util.Strings.isBlank; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; + +import com.gradle.maven.extension.api.scan.BuildScanApi; + +import io.quarkus.develocity.project.Log; + +public final class BuildScanMetadata { + + private BuildScanMetadata() { + } + + public static void addMetadataToBuildScan(BuildScanApi buildScanApi) { + // Add mvn command line + final String mavenCommandLine = System.getenv("MAVEN_CMD_LINE_ARGS") != null ? "mvn " + System.getenv("MAVEN_CMD_LINE_ARGS") : ""; + if (!isBlank(mavenCommandLine)) { + buildScanApi.value("Maven command line", "mvn " + mavenCommandLine); + } + + //Add github action information + if (System.getenv("GITHUB_ACTIONS") != null) { + String jobId = System.getenv("GITHUB_JOB"); + + buildScanApi.value("gh-job-id", jobId); + buildScanApi.value("gh-event-name", System.getenv("GITHUB_EVENT_NAME")); + buildScanApi.value("gh-ref-name", System.getenv("GITHUB_REF_NAME")); + buildScanApi.value("gh-actor", System.getenv("GITHUB_ACTOR")); + buildScanApi.value("gh-workflow", System.getenv("GITHUB_WORKFLOW")); + String jobCustomValues = System.getenv("GE_CUSTOM_VALUES"); + if (!isBlank(jobCustomValues)) { + for (String jobCustomValue : jobCustomValues.split(",")) { + int index = jobCustomValue.indexOf('='); + if (index <= 0) { + continue; + } + buildScanApi.value(jobCustomValue.substring(0, index).trim(), jobCustomValue.substring(index + 1).trim()); + } + } + + List similarBuildsTags = new ArrayList<>(); + + buildScanApi.tag(jobId); + similarBuildsTags.add(jobId); + + buildScanApi.tag(System.getenv("GITHUB_EVENT_NAME")); + similarBuildsTags.add(System.getenv("GITHUB_EVENT_NAME")); + + buildScanApi.tag(System.getenv("GITHUB_WORKFLOW")); + similarBuildsTags.add(System.getenv("GITHUB_WORKFLOW")); + + String jobTags = System.getenv("GE_TAGS"); + if (!isBlank(jobTags)) { + for (String tag : jobTags.split(",")) { + buildScanApi.tag(tag.trim()); + similarBuildsTags.add(tag.trim()); + } + } + + buildScanApi.link("Workflow run", System.getenv("GITHUB_SERVER_URL") + "/" + System.getenv("GITHUB_REPOSITORY") + + "/actions/runs/" + System.getenv("GITHUB_RUN_ID")); + + String prNumber = System.getenv("PULL_REQUEST_NUMBER"); + if (!isBlank(prNumber)) { + buildScanApi.value("gh-pr", prNumber); + buildScanApi.tag("pr-" + prNumber); + similarBuildsTags.add("pr-" + prNumber); + + buildScanApi.link("Pull request", + System.getenv("GITHUB_SERVER_URL") + "/" + System.getenv("GITHUB_REPOSITORY") + "/pull/" + prNumber); + } + + similarBuildsTags.add(System.getenv("RUNNER_OS")); + + buildScanApi.link("Similar builds", "https://ge.quarkus.io/scans?search.tags=" + + URLEncoder.encode(String.join(",", similarBuildsTags), StandardCharsets.UTF_8).replace("+", "%20")); + + buildScanApi.buildScanPublished(publishedBuildScan -> { + File target = new File("target"); + if (!target.exists()) { + target.mkdir(); + } + + try { + Path gradleBuildScanUrlFile = Path.of("target/gradle-build-scan-url.txt"); + if (!Files.exists(gradleBuildScanUrlFile)) { + Files.writeString(gradleBuildScanUrlFile, publishedBuildScan.getBuildScanUri().toString()); + } + + Files.writeString(Path.of(System.getenv("GITHUB_STEP_SUMMARY")), + "\n[Build scan](" + publishedBuildScan.getBuildScanUri() + ")\n`" + mavenCommandLine + "`\n\n", + StandardOpenOption.APPEND); + } catch (IOException e) { + Log.warn("Unable to write build scan information to files", e); + } + }); + } + } +} diff --git a/src/main/java/io/quarkus/develocity/project/scan/MavenVersionChecker.java b/src/main/java/io/quarkus/develocity/project/scan/MavenVersionChecker.java new file mode 100644 index 0000000..c781469 --- /dev/null +++ b/src/main/java/io/quarkus/develocity/project/scan/MavenVersionChecker.java @@ -0,0 +1,65 @@ +package io.quarkus.develocity.project.scan; + +import static io.quarkus.develocity.project.util.Strings.isBlank; + +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.rtinfo.RuntimeInformation; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +import com.gradle.maven.extension.api.scan.BuildScanApi; + +import io.quarkus.develocity.project.Log; + +public final class MavenVersionChecker { + + private static final Pattern MAVEN_WRAPPER_VERSION_PATTERN = Pattern.compile(".*/apache-maven-(.*)-bin\\.zip"); + + private MavenVersionChecker() { + } + + public static void checkRuntimeMavenVersion(BuildScanApi buildScanApi, MavenSession mavenSession) { + // Check runtime Maven version and Maven Wrapper version are aligned + RuntimeInformation runtimeInfo; + try { + runtimeInfo = (RuntimeInformation) mavenSession.lookup(RuntimeInformation.class.getName()); + } catch (ComponentLookupException e) { + return; + } + + if (runtimeInfo == null) { + return; + } + + String runtimeMavenVersion = runtimeInfo.getMavenVersion(); + Properties mavenWrapperProperties = new Properties(); + Path mavenWrapperPropertiesPath = Path.of(".mvn/wrapper/maven-wrapper.properties"); + if (Files.isReadable(mavenWrapperPropertiesPath)) { + try (Reader reader = Files.newBufferedReader(mavenWrapperPropertiesPath)) { + mavenWrapperProperties.load(reader); + // assuming the wrapper properties contains: + // distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/VERSION/apache-maven-VERSION-bin.zip + Matcher matcher = MAVEN_WRAPPER_VERSION_PATTERN.matcher(mavenWrapperProperties.getProperty("distributionUrl")); + if (matcher.matches()) { + String wrapperMavenVersion = matcher.group(1); + if (!isBlank(runtimeMavenVersion) && !isBlank(wrapperMavenVersion) + && !wrapperMavenVersion.equals(runtimeMavenVersion)) { + Log.warn("Maven Wrapper is configured with a different version (" + wrapperMavenVersion + + ") than the runtime version (" + runtimeMavenVersion + + "). This will negatively impact build consistency and build caching."); + buildScanApi.tag("misaligned-maven-version"); + buildScanApi.value("wrapper-maven-version", wrapperMavenVersion); + } + } + } catch (Exception e) { + Log.warn("Unable to determine Maven wrapper version", e); + } + } + } +} diff --git a/src/main/java/io/quarkus/develocity/project/util/Matchers.java b/src/main/java/io/quarkus/develocity/project/util/Matchers.java index 0f00756..7d5695e 100644 --- a/src/main/java/io/quarkus/develocity/project/util/Matchers.java +++ b/src/main/java/io/quarkus/develocity/project/util/Matchers.java @@ -38,6 +38,10 @@ public static boolean module(NormalizationProvider.Context context, String group } private static boolean directory(MavenSession session, MavenProject project, Path directory) { + if (project == null || project.getBasedir() == null) { + return false; + } + Path rootProject = session.getRequest().getMultiModuleProjectDirectory().toPath(); Path currentProject = project.getBasedir().toPath(); diff --git a/src/main/java/io/quarkus/develocity/project/util/Strings.java b/src/main/java/io/quarkus/develocity/project/util/Strings.java new file mode 100644 index 0000000..4746120 --- /dev/null +++ b/src/main/java/io/quarkus/develocity/project/util/Strings.java @@ -0,0 +1,15 @@ +package io.quarkus.develocity.project.util; + +public final class Strings { + + private Strings() { + } + + public static boolean isBlank(String string) { + if (string == null) { + return true; + } + + return string.isBlank(); + } +}