From c1128e99b463f03a4e9fef8b14affef8f338063e Mon Sep 17 00:00:00 2001 From: Hunter Mellema <124718352+hpmellema@users.noreply.github.com> Date: Fri, 12 Jan 2024 07:34:37 -0700 Subject: [PATCH] Refactor to use convention plugins for common configuration (#117) Refactor project to use buildSrc plugins for common configuration rather than looping through subprojects. --- build.gradle.kts | 203 +----------------- buildSrc/build.gradle.kts | 20 ++ ...-gradle-plugin.java-conventions.gradle.kts | 52 +++++ ...radle-plugin.plugin-conventions.gradle.kts | 131 +++++++++++ config/spotbugs/filter.xml | 5 + integ-test-utils/build.gradle.kts | 4 + .../software/amazon/smithy/gradle/Utils.java | 9 +- smithy-base/build.gradle.kts | 6 +- smithy-jar/build.gradle.kts | 4 + 9 files changed, 226 insertions(+), 208 deletions(-) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/smithy-gradle-plugin.java-conventions.gradle.kts create mode 100644 buildSrc/src/main/kotlin/smithy-gradle-plugin.plugin-conventions.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index 7aeae3c..2a22398 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,23 +13,13 @@ * permissions and limitations under the License. */ -import com.github.spotbugs.snom.Effort -import com.github.spotbugs.snom.SpotBugsTask -import com.adarshr.gradle.testlogger.TestLoggerExtension import org.jreleaser.model.Active plugins { - `java-library` - jacoco - id("com.github.spotbugs") version "5.0.14" - id("com.adarshr.test-logger") version "3.2.0" - id("com.gradle.plugin-publish") version "1.2.1" apply false + base id("org.jreleaser") version "1.9.0" } -// The root project doesn't produce a JAR. -tasks["jar"].enabled = false - val pluginVersion = project.file("VERSION").readText().replace(System.lineSeparator(), "") allprojects { group = "software.amazon.smithy.gradle" @@ -37,190 +27,6 @@ allprojects { } println("Smithy Gradle version: '${pluginVersion}'") -// JReleaser publishes artifacts from a local staging repository, rather than maven local. -// https://jreleaser.org/guide/latest/examples/maven/staging-artifacts.html#_gradle -val stagingDirectory = "$buildDir/staging" - -subprojects { - val subproject = this - - if (subproject.name != "integ-test-utils") { - apply(plugin = "java-gradle-plugin") - apply(plugin = "com.gradle.plugin-publish") - } else { - apply(plugin = "java-library") - } - - /* - * Java - * ==================================================== - */ - - java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - // Use Junit5's test runner. - tasks.withType { - useJUnitPlatform() - } - - // Suppress warnings in javadocs - tasks.withType { - (options as StandardJavadocDocletOptions).addStringOption("Xdoclint:-html", "-quiet") - } - - apply(plugin = "com.adarshr.test-logger") - configure { - showExceptions = true - showStackTraces = true - showFullStackTraces = false - showCauses = true - showSummary = true - showPassed = true - showSkipped = true - showFailed = true - showOnlySlow = false - showStandardStreams = true - showPassedStandardStreams = false - showSkippedStandardStreams = false - showFailedStandardStreams = true - logLevel = LogLevel.LIFECYCLE - } - - dependencies { - implementation("software.amazon.smithy:smithy-model:[1.0, 2.0[") - implementation("software.amazon.smithy:smithy-build:[1.0, 2.0[") - implementation("software.amazon.smithy:smithy-cli:[1.0, 2.0[") - - testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.0") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.0") - testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.0") - testImplementation("org.hamcrest:hamcrest:2.1") - testImplementation(project(":integ-test-utils")) - } - - // Reusable license copySpec - val licenseSpec = copySpec { - from("${project.rootDir}/LICENSE") - from("${project.rootDir}/NOTICE") - } - - if (subproject.name != "integ-test-utils") { - // Configure all jars to include license info - tasks.withType() { - metaInf.with(licenseSpec) - } - - /* - * Configure integration tests - * ==================================================== - */ - sourceSets { - create("it") { - compileClasspath += sourceSets["main"].output + configurations["testRuntimeClasspath"] - runtimeClasspath += output + compileClasspath + sourceSets["test"].runtimeClasspath - } - } - - tasks.register("integTest") { - useJUnitPlatform() - testClassesDirs = sourceSets["it"].output.classesDirs - classpath = sourceSets["it"].runtimeClasspath - maxParallelForks = Runtime.getRuntime().availableProcessors() / 2 - } - - afterEvaluate { - tasks["integTest"].dependsOn("publishToMavenLocal") - - // Always run javadoc and integration tests after build. - tasks["assemble"].dependsOn("javadoc") - tasks["build"].finalizedBy(tasks["integTest"]) - } - - /* - * Common plugin settings - * ==================================================== - */ - apply(plugin = "com.gradle.plugin-publish") - configure { - website.set("https://smithy.io") - vcsUrl.set("https://github.com/smithy-lang/smithy-gradle-plugin") - } - - /* - * Staging repository - * ==================================================== - * - * Configure publication to staging repo for jreleaser - */ - configure { - repositories { - maven { - name = "stagingRepository" - url = uri(stagingDirectory) - } - } - } - - /* - * CheckStyle - * ==================================================== - * - * Apply CheckStyle to source files but not tests. - */ - apply(plugin = "checkstyle") - tasks["checkstyleTest"].enabled = false - tasks["checkstyleIt"].enabled = false - - /* - * Code coverage - * ==================================================== - * - * Create code coverage reports after running tests. - */ - apply(plugin = "jacoco") - // Always run the jacoco test report after testing. - tasks["test"].finalizedBy(tasks["jacocoTestReport"]) - // Configure jacoco to generate an HTML report. - tasks.jacocoTestReport { - reports { - xml.required.set(false) - csv.required.set(false) - html.outputLocation.set(file("$buildDir/reports/jacoco")) - } - } - - /* - * Spotbugs - * ==================================================== - * - * Run spotbugs against source files and configure suppressions. - */ - apply(plugin = "com.github.spotbugs") - // We don't need to lint tests. - tasks["spotbugsTest"].enabled = false - tasks["spotbugsIt"].enabled = false - - // Configure the bug filter for spotbugs. - tasks.withType().configureEach { - effort.set(Effort.MAX) - excludeFilter.set(project.file("${project.rootDir}/config/spotbugs/filter.xml")) - } - } - - /* - * Repositories - * ==================================================== - */ - repositories { - mavenLocal() - mavenCentral() - } -} - - /* * Jreleaser (https://jreleaser.org) config. */ @@ -262,14 +68,9 @@ jreleaser { snapshotUrl = "https://aws.oss.sonatype.org/content/repositories/snapshots" closeRepository.set(false) releaseRepository.set(false) - stagingRepositories.add(stagingDirectory) + stagingRepositories.add("${rootProject.buildDir}/staging") } } } } } - -repositories { - mavenLocal() - mavenCentral() -} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..20c0c23 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + // Support convention plugins written in Kotlin. Convention plugins are + // build scripts in 'src/main' that automatically become available as + // plugins in the main build. + `kotlin-dsl` +} + +repositories { + // Use the plugin portal to apply community plugins in convention plugins. + gradlePluginPortal() +} + +dependencies { + // Java convention dependencies + implementation("com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.6") + implementation("com.adarshr:gradle-test-logger-plugin:4.0.0") + + // Plugin convention dependencies + implementation("com.gradle.publish:plugin-publish-plugin:1.2.1") +} diff --git a/buildSrc/src/main/kotlin/smithy-gradle-plugin.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/smithy-gradle-plugin.java-conventions.gradle.kts new file mode 100644 index 0000000..19bc203 --- /dev/null +++ b/buildSrc/src/main/kotlin/smithy-gradle-plugin.java-conventions.gradle.kts @@ -0,0 +1,52 @@ + +plugins { + `java-library` + checkstyle +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:[1.0, 2.0[") + implementation("software.amazon.smithy:smithy-build:[1.0, 2.0[") + implementation("software.amazon.smithy:smithy-cli:[1.0, 2.0[") +} + +//// ==== Licensing ===== +// Reusable license copySpec +val licenseSpec = copySpec { + from("${project.rootDir}/LICENSE") + from("${project.rootDir}/NOTICE") +} + +// Configure all jars to include license info +tasks.withType() { + metaInf.with(licenseSpec) +} + + + +// Suppress warnings in javadocs +tasks.withType { + (options as StandardJavadocDocletOptions).addStringOption("Xdoclint:-html", "-quiet") +} + +/* + * CheckStyle + * ==================================================== + * + * Apply CheckStyle to source files but not tests. + */ +tasks["checkstyleTest"].enabled = false + +/* + * Repositories + * ==================================================== + */ +repositories { + mavenLocal() + mavenCentral() +} diff --git a/buildSrc/src/main/kotlin/smithy-gradle-plugin.plugin-conventions.gradle.kts b/buildSrc/src/main/kotlin/smithy-gradle-plugin.plugin-conventions.gradle.kts new file mode 100644 index 0000000..0259f42 --- /dev/null +++ b/buildSrc/src/main/kotlin/smithy-gradle-plugin.plugin-conventions.gradle.kts @@ -0,0 +1,131 @@ +import com.github.spotbugs.snom.Effort + +plugins { + id("smithy-gradle-plugin.java-conventions") + `java-gradle-plugin` + id("com.gradle.plugin-publish") + jacoco + id("com.adarshr.test-logger") + id("com.github.spotbugs") +} + +/* + * Common plugin settings + * ==================================================== + */ +gradlePlugin { + website.set("https://smithy.io") + vcsUrl.set("https://github.com/smithy-lang/smithy-gradle-plugin") +} + +/* + * Staging repository + * ==================================================== + * + * Configure publication to staging repo for jreleaser + */ +publishing { + repositories { + maven { + name = "stagingRepository" + url = uri("${rootProject.buildDir}/staging") + } + } +} + +/* + * Unit tests + * ==================================================== + */ +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.0") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.0") + testImplementation("org.hamcrest:hamcrest:2.1") + testImplementation(project(":integ-test-utils")) +} + +// Use Junit5's test runner. +tasks.withType { + useJUnitPlatform() +} + +testlogger { + showExceptions = true + showStackTraces = true + showFullStackTraces = false + showCauses = true + showSummary = true + showPassed = true + showSkipped = true + showFailed = true + showOnlySlow = false + showStandardStreams = true + showPassedStandardStreams = false + showSkippedStandardStreams = false + showFailedStandardStreams = true + logLevel = LogLevel.LIFECYCLE +} + +/* + * Configure integration tests + * ==================================================== + */ +sourceSets { + create("it") { + compileClasspath += sourceSets["main"].output + configurations["testRuntimeClasspath"] + runtimeClasspath += output + compileClasspath + sourceSets["test"].runtimeClasspath + } +} +// Disable spotbugs and checkstyle for integration tests +tasks["spotbugsIt"].enabled = false +tasks["checkstyleIt"].enabled = false + + +tasks.register("integTest") { + useJUnitPlatform() + testClassesDirs = sourceSets["it"].output.classesDirs + classpath = sourceSets["it"].runtimeClasspath + maxParallelForks = Runtime.getRuntime().availableProcessors() / 2 +} + +afterEvaluate { + tasks["integTest"].dependsOn("publishToMavenLocal") + + // Always run javadoc and integration tests after build. + tasks["assemble"].dependsOn("javadoc") + tasks["build"].finalizedBy(tasks["integTest"]) +} + +/* + * Code coverage + * ==================================================== + * + * Create code coverage reports after running tests. + */ +// Always run the jacoco test report after testing. +tasks["test"].finalizedBy(tasks["jacocoTestReport"]) +// Configure jacoco to generate an HTML report. +tasks.jacocoTestReport { + reports { + xml.required.set(false) + csv.required.set(false) + html.outputLocation.set(file("$buildDir/reports/jacoco")) + } +} + +/* + * Spotbugs + * ==================================================== + * + * Run spotbugs against source files and configure suppressions. + */ +// Configure the spotbugs extension. +spotbugs { + effort = Effort.MAX + excludeFilter = file("${project.rootDir}/config/spotbugs/filter.xml") +} + +// We don't need to lint tests. +tasks["spotbugsTest"].enabled = false + diff --git a/config/spotbugs/filter.xml b/config/spotbugs/filter.xml index 5c7da96..888e398 100644 --- a/config/spotbugs/filter.xml +++ b/config/spotbugs/filter.xml @@ -28,4 +28,9 @@ + + + + + diff --git a/integ-test-utils/build.gradle.kts b/integ-test-utils/build.gradle.kts index bb18e22..986ca57 100644 --- a/integ-test-utils/build.gradle.kts +++ b/integ-test-utils/build.gradle.kts @@ -1,5 +1,9 @@ description = "Integration test utilities used across multiple plugins." +plugins { + id("smithy-gradle-plugin.java-conventions") +} + dependencies { implementation(gradleTestKit()) implementation("org.junit.jupiter:junit-jupiter-api:5.4.0") diff --git a/integ-test-utils/src/main/java/software/amazon/smithy/gradle/Utils.java b/integ-test-utils/src/main/java/software/amazon/smithy/gradle/Utils.java index 9c1c0c1..bbedfc0 100644 --- a/integ-test-utils/src/main/java/software/amazon/smithy/gradle/Utils.java +++ b/integ-test-utils/src/main/java/software/amazon/smithy/gradle/Utils.java @@ -15,11 +15,6 @@ package software.amazon.smithy.gradle; -import org.gradle.testkit.runner.BuildResult; -import org.gradle.testkit.runner.BuildTask; -import org.gradle.testkit.runner.TaskOutcome; -import org.junit.jupiter.api.Assertions; - import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; @@ -36,6 +31,10 @@ import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.BuildTask; +import org.gradle.testkit.runner.TaskOutcome; +import org.junit.jupiter.api.Assertions; public final class Utils { private Utils() {} diff --git a/smithy-base/build.gradle.kts b/smithy-base/build.gradle.kts index 3435efc..09dd478 100644 --- a/smithy-base/build.gradle.kts +++ b/smithy-base/build.gradle.kts @@ -1,12 +1,14 @@ import org.apache.tools.ant.filters.ReplaceTokens - - description = "This plugin sets up the basic capabilities necessary for building Smithy models. " + "Applying this plugin will create the basic source sets and configurations needed for Smithy " + "projects. It will also create a smithy build task that will build and validate all the " + "Smithy models in the project." +plugins { + id("smithy-gradle-plugin.plugin-conventions") +} + gradlePlugin { plugins { create("smithy-base-plugin") { diff --git a/smithy-jar/build.gradle.kts b/smithy-jar/build.gradle.kts index 81787dc..37877ae 100644 --- a/smithy-jar/build.gradle.kts +++ b/smithy-jar/build.gradle.kts @@ -3,6 +3,10 @@ description = "Adds built Smithy files to an existing jar task such as that crea "and tags to the JAR's MANIFEST. The smithy-jar plugin applies the smithy-base " + "plugin when it is applied." +plugins { + id("smithy-gradle-plugin.plugin-conventions") +} + gradlePlugin { plugins { create("smithy-jar-plugin") {