Skip to content

Commit

Permalink
Migrate build logic to conventions plugins (#2484)
Browse files Browse the repository at this point in the history
* Overhauls our builds to use convention plugins

---------

Co-authored-by: Hunter Mellema <hpm@amazon.com>
  • Loading branch information
haydenbaker and hpmellema authored Dec 10, 2024
1 parent b855e2b commit 1fdb522
Show file tree
Hide file tree
Showing 47 changed files with 959 additions and 947 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ jobs:
java-version: ${{ matrix.java }}
distribution: 'corretto'

- name: Clean, build and javadoc
- name: Clean, build, test, and javadoc
run: ./gradlew clean build javadoc -Plog-tests --stacktrace

- name: Allow long file names in git for windows
if: matrix.os == 'windows-latest'
run: git config --system core.longpaths true

- name: CLI integration tests
- name: Integration tests
if: matrix.java == 17
run: ./gradlew :smithy-cli:integ -Plog-tests --stacktrace
run: ./gradlew integ -Plog-tests --stacktrace

- uses: actions/upload-artifact@v4
if: failure()
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ target/
**/dependency-reduced-pom.xml

# Gradle
/.gradle
**/.gradle
build/
!smithy-build/src/main/java/software/amazon/smithy/build
!smithy-build/src/main/resources/software/amazon/smithy/build
Expand Down
294 changes: 36 additions & 258 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import org.jreleaser.gradle.plugin.JReleaserExtension
import org.jreleaser.model.Active

/*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
Expand All @@ -13,263 +16,35 @@
* permissions and limitations under the License.
*/

import com.github.spotbugs.snom.Effort
import org.jreleaser.model.Active
import org.gradle.api.tasks.testing.logging.TestExceptionFormat

plugins {
`java-library`
`maven-publish`
signing
checkstyle
jacoco
id("com.github.spotbugs") version "6.0.8"
id("io.codearte.nexus-staging") version "0.30.0"
id("me.champeau.jmh") version "0.7.2"
id("com.github.johnrengelman.shadow") version "7.1.2"
id("org.jreleaser") version "1.12.0" apply false
java
alias(libs.plugins.jreleaser) apply false
}

// Load the Smithy version from VERSION.
val libraryVersion = project.file("VERSION").readText().trim()

println("Smithy version: '$libraryVersion'")

allprojects {
group = "software.amazon.smithy"
version = libraryVersion
}

// 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 = rootProject.layout.buildDirectory.dir("staging")

subprojects {
apply(plugin = "java-library")

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.0")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.0")
testImplementation("org.hamcrest:hamcrest:2.1")
testCompileOnly("org.apiguardian:apiguardian-api:1.1.2")
}

// Reusable license copySpec for building JARs
val licenseSpec = copySpec {
from("${project.rootDir}/LICENSE")
from("${project.rootDir}/NOTICE")
}

// Set up tasks that build source and javadoc jars.
tasks.register<Jar>("sourcesJar") {
metaInf.with(licenseSpec)
from(sourceSets.main.get().allSource)
archiveClassifier.set("sources")
}

// Build a javadoc JAR too.
tasks.register<Jar>("javadocJar") {
metaInf.with(licenseSpec)
from(tasks.javadoc)
archiveClassifier.set("javadoc")
}

// Include an Automatic-Module-Name in all JARs.
afterEvaluate {
tasks.jar {
metaInf.with(licenseSpec)
inputs.property("moduleName", project.extra.get("moduleName"))
manifest {
attributes("Automatic-Module-Name" to project.extra.get("moduleName"))
}
}
}

// Always run javadoc after build.
tasks["build"].dependsOn(tasks["javadoc"])

// ==== Tests ====
// https://docs.gradle.org/current/samples/sample_java_multi_project_with_junit5_tests.html
tasks.test {
useJUnitPlatform()
}

// Log on passed, skipped, and failed test events if the `-Plog-tests` property is set.
// https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLoggingContainer.html
if (project.hasProperty("log-tests")) {
tasks.test {
testLogging {
events("passed", "skipped", "failed")
exceptionFormat = TestExceptionFormat.FULL
}
}
}

// ==== Maven ====
apply(plugin = "maven-publish")
apply(plugin = "signing")
apply(plugin = "com.github.johnrengelman.shadow")

// This is a little hacky, but currently needed to build a shadowed CLI JAR and smithy-syntax JAR with the same
// customizations as other JARs.
if (project.name != "smithy-cli" && project.name != "smithy-syntax") {
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
isEnabled = false
}
}

publishing {
repositories {
// JReleaser's `publish` task publishes to all repositories, so only configure one.
maven {
name = "localStaging"
url = uri(stagingDirectory)
}
}

publications {
create<MavenPublication>("mavenJava") {
if (tasks.findByName("shadowJar")?.enabled == true) {
project.shadow.component(this)
} else {
from(components["java"])
}

// Ship the source and javadoc jars.
artifact(tasks["sourcesJar"])
artifact(tasks["javadocJar"])

// Include extra information in the POMs.
afterEvaluate {
pom {
name.set(project.ext["displayName"].toString())
description.set(project.description)
url.set("https://github.com/smithy-lang/smithy")
licenses {
license {
name.set("Apache License 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
distribution.set("repo")
}
}
developers {
developer {
id.set("smithy")
name.set("Smithy")
organization.set("Amazon Web Services")
organizationUrl.set("https://aws.amazon.com")
roles.add("developer")
}
}
scm {
url.set("https://github.com/smithy-lang/smithy.git")
}
}
}
}
}

// Don't sign the artifacts if we didn't get a key and password to use.
if (project.hasProperty("signingKey") && project.hasProperty("signingPassword")) {
signing {
useInMemoryPgpKeys(
project.property("signingKey").toString(),
project.property("signingPassword").toString()
)
sign(publishing.publications["mavenJava"])
}
}
}

tasks.register<Copy>("copyMavenMetadataForDevelopment") {
from("build/tmp/publishMavenJavaPublicationToMavenLocal") {
rename("module-maven-metadata.xml", "maven-metadata.xml")
}
val wdir = "${System.getProperty("user.home")}/.m2/repository/software/amazon/smithy/${project.name}"
into(wdir)
}

tasks.publishToMavenLocal {
finalizedBy("copyMavenMetadataForDevelopment")
}

// ==== CheckStyle ====
// https://docs.gradle.org/current/userguide/checkstyle_plugin.html
apply(plugin = "checkstyle")
tasks.named("checkstyleTest") {
enabled = false
}

// ==== Code coverage ====
// https://docs.gradle.org/current/userguide/jacoco_plugin.html
apply(plugin = "jacoco")

// report is always generated after tests run
tasks.test {
finalizedBy(tasks.jacocoTestReport)
}

// tests are required to run before generating the report
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(false)
csv.required.set(false)
html.outputLocation.set(file("$buildDir/reports/jacoco"))
}
}

// ==== Spotbugs ====
// https://plugins.gradle.org/plugin/com.github.spotbugs
apply(plugin = "com.github.spotbugs")
// We don't need to lint tests.
tasks.named("spotbugsTest") {
enabled = false
}
// Configure the bug filter for spotbugs.
spotbugs {
effort.set(Effort.MAX)
excludeFilter.set(file("${project.rootDir}/config/spotbugs/filter.xml"))
}
}

// The root project doesn't produce a JAR.
tasks.named("jar") {
enabled = false
}

// ==== Javadoc ====
// Consolidated Javadoc creation
afterEvaluate {
tasks.javadoc {
title = "Smithy API ${version}"
setDestinationDir(file("${project.buildDir}/docs/javadoc/latest"))
// Build a consolidated javadoc of all subprojects.
source(subprojects.map { project(it.path).sourceSets.main.get().allJava })
classpath = files(subprojects.map { project(it.path).sourceSets.main.get().compileClasspath })
}
}

// Disable HTML doclint to work around heading tag sequence validation
// inconsistencies between JDK15 and earlier Java versions.
allprojects {
tasks.withType<Javadoc> {
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:-html", "-quiet")
// Fixed in JDK 12: https://bugs.openjdk.java.net/browse/JDK-8215291
// --no-module-directories does not exist in JDK 8 and is removed in 13
if (JavaVersion.current().run { isJava9 || isJava10 || isJava11 }) {
addBooleanOption("-no-module-directories", true)
tasks {
javadoc {
title = "Smithy API ${version}"
setDestinationDir(layout.buildDirectory.dir("docs/javadoc/latest").get().asFile)
source(subprojects.map { project(it.path).sourceSets.main.get().allJava })
classpath = files(subprojects.map { project(it.path).sourceSets.main.get().compileClasspath })
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:-html", "-quiet")
// Fixed in JDK 12: https://bugs.openjdk.java.net/browse/JDK-8215291
// --no-module-directories does not exist in JDK 8 and is removed in 13
if (JavaVersion.current().run { isJava9 || isJava10 || isJava11 }) {
addBooleanOption("-no-module-directories", true)
}
}
}
}
Expand All @@ -280,29 +55,32 @@ allprojects {
if (project.hasProperty("release.main")) {
apply(plugin = "org.jreleaser")

extensions.configure<org.jreleaser.gradle.plugin.JReleaserExtension> {
dryrun.set(false)
// Workaround for https://github.com/jreleaser/jreleaser/issues/1492
tasks.register("clean")

configure<JReleaserExtension> {
dryrun = false

// Used for creating and pushing the version tag, but this configuration ensures that
// an actual GitHub release isn't created (since the CLI release does that)
release {
github {
skipRelease.set(true)
tagName.set("{{projectVersion}}")
skipRelease = true
tagName = "{{projectVersion}}"
}
}

// Used to announce a release to configured announcers.
// https://jreleaser.org/guide/latest/reference/announce/index.html
announce {
active.set(Active.NEVER)
active = Active.NEVER
}

// Signing configuration.
// https://jreleaser.org/guide/latest/reference/signing.html
signing {
active.set(Active.ALWAYS)
armored.set(true)
active = Active.ALWAYS
armored = true
}

// Configuration for deploying to Maven Central.
Expand All @@ -311,15 +89,15 @@ if (project.hasProperty("release.main")) {
maven {
nexus2 {
create("maven-central") {
active.set(Active.ALWAYS)
url.set("https://aws.oss.sonatype.org/service/local")
snapshotUrl.set("https://aws.oss.sonatype.org/content/repositories/snapshots")
closeRepository.set(true)
releaseRepository.set(true)
stagingRepository(stagingDirectory.get().toString())
active = Active.ALWAYS
url = "https://aws.oss.sonatype.org/service/local"
snapshotUrl = "https://aws.oss.sonatype.org/content/repositories/snapshots"
closeRepository = true
releaseRepository = true
stagingRepository(stagingDir().get().asFile.path)
}
}
}
}
}
}
}
18 changes: 18 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
plugins {
`kotlin-dsl`
}

repositories {
mavenCentral()
gradlePluginPortal()
}

dependencies {
// Plugins used by buildSrc scripts
implementation(libs.spotbugs)
implementation(libs.spotless)
implementation(libs.jmh)

// https://github.com/gradle/gradle/issues/15383
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}
Loading

0 comments on commit 1fdb522

Please sign in to comment.