Skip to content

Commit

Permalink
Build Config update & enable Configuration Cache (#4062)
Browse files Browse the repository at this point in the history
Minor build config updates, aiming to improve build configuration speed
and stability.

- Re-order repositories by stability, and add snapshotsOnly() filter to
Sonatype snapshots.
- Update Shadow plugin to 8.1.1 (better config cache support)
- remove deprecated `kotlin { targets {} }` config
- update gradle.properties
  - enable configuration cache - should work fine with KGP 1.9
  - re-enable KN compiler daemon - again, it should be more stable
- remove ignoreIncorrectDependencies (it doesn't seem to be triggered
any more - but if it was, it's an important warning so it shouldn't be
ignored)
  - sort & group properties
- remove `kotlin.code.style` - I don't think it does anything, and
besides, the project has an .editorconfig file
- remove nested `gradle.properties` files (it's not clear whether it
works, and the only option in the files was `org.gradle.parallel=false`
- which only makes sense as a project-wide setting)
- Introduce BuildService for limiting parallel publishing, because Maven
Central can't handle parallel uploads.
- Add a delay in `kotest-tests-spec-parallelism` test to try and make it
more stable.
- Comment out non-functional `buildConfigDocs` task.
- Update GitHub workflows to make the Gradle flags closer to what's in
the project's `gradle.properties`.
  • Loading branch information
aSemy committed Jun 6, 2024
1 parent 2cd159d commit 7b4fe30
Show file tree
Hide file tree
Showing 35 changed files with 239 additions and 251 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release_base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_multiplatform_plugin_gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:

env:
RELEASE_VERSION: ${{ github.event.inputs.version }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=false -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_tvos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_watchos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ jobs:
path: build-reports.zip

env:
GRADLE_OPTS: -Dorg.gradle.configureondemand=false -Dorg.gradle.parallel=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx12g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
1 change: 0 additions & 1 deletion buildSrc/src/main/kotlin/kotest-jvm-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ plugins {
}

kotlin {

jvm {
withJava()
}
Expand Down
140 changes: 38 additions & 102 deletions buildSrc/src/main/kotlin/kotest-publishing-conventions.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,92 +1,19 @@
import groovy.util.Node
import groovy.util.NodeList
import org.gradle.configurationcache.extensions.capitalized

/**
* Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
* metadata can still get the platform artifact and transitive dependencies from the POM
* (see details in https://youtrack.jetbrains.com/issue/KT-39184#focus=streamItem-27-4115233.0-0)
*/
fun Project.publishPlatformArtifactsInRootModule() {
val platformPublication: MavenPublication? =
extensions
.findByType(PublishingExtension::class.java)
?.publications
?.getByName<MavenPublication>("jvm")
if (platformPublication != null) {

lateinit var platformXml: XmlProvider
platformPublication.pom?.withXml { platformXml = this }

extensions
.findByType(PublishingExtension::class.java)
?.publications
?.getByName("kotlinMultiplatform")
?.let { it as MavenPublication }
?.run {

// replace pom
pom.withXml {
val xmlProvider = this
val root = xmlProvider.asNode()
// Remove the original content and add the content from the platform POM:
root.children().toList().forEach { root.remove(it as Node) }
platformXml.asNode().children().forEach { root.append(it as Node) }

// Adjust the self artifact ID, as it should match the root module's coordinates:
((root.get("artifactId") as NodeList).get(0) as Node).setValue(artifactId)

// Set packaging to POM to indicate that there's no artifact:
root.appendNode("packaging", "pom")

// Remove the original platform dependencies and add a single dependency on the platform
// module:
val dependencies = (root.get("dependencies") as NodeList).get(0) as Node
dependencies.children().toList().forEach { dependencies.remove(it as Node) }
val singleDependency = dependencies.appendNode("dependency")
singleDependency.appendNode("groupId", platformPublication.groupId)
singleDependency.appendNode("artifactId", platformPublication.artifactId)
singleDependency.appendNode("version", platformPublication.version)
singleDependency.appendNode("scope", "compile")
}
}

tasks
.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }
.configureEach {
dependsOn("generatePomFileFor${platformPublication.name.capitalized()}Publication")
}
}
}

plugins {
signing
`maven-publish`
}

val publications: PublicationContainer = (extensions.getByName("publishing") as PublishingExtension).publications

val javadoc = tasks.named("javadoc")

group = "io.kotest"
version = Ci.publishVersion

val javadocJar by tasks.creating(Jar::class) {
val javadocJar by tasks.registering(Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Assembles java doc to jar"
archiveClassifier.set("javadoc")
val javadoc = tasks.named("javadoc")
from(javadoc)
}


publishing {
publications.withType<MavenPublication>().forEach {
it.apply {
artifact(javadocJar)
}
}
}

val ossrhUsername: String by project
val ossrhPassword: String by project
val signingKey: String? by project
Expand All @@ -95,16 +22,13 @@ val signingPassword: String? by project
signing {
useGpgCmd()
if (signingKey != null && signingPassword != null) {
@Suppress("UnstableApiUsage")
useInMemoryPgpKeys(signingKey, signingPassword)
}
if (Ci.isRelease) {
sign(publications)
sign(publishing.publications)
}
}

publishPlatformArtifactsInRootModule()

publishing {
repositories {
maven {
Expand All @@ -119,37 +43,49 @@ publishing {
}
}

publications.withType<MavenPublication>().forEach {
it.apply {
//if (Ci.isRelease)
pom {
name.set("Kotest")
description.set("Kotlin Test Framework")
url.set("https://github.com/kotest/kotest")
publications.withType<MavenPublication>().configureEach {
artifact(javadocJar)

scm {
connection.set("scm:git:https://github.com/kotest/kotest/")
developerConnection.set("scm:git:https://github.com/sksamuel/")
url.set("https://github.com/kotest/kotest/")
}
pom {
name.set("Kotest")
description.set("Kotlin Test Framework")
url.set("https://github.com/kotest/kotest")

licenses {
license {
name.set("Apache-2.0")
url.set("https://opensource.org/licenses/Apache-2.0")
}
scm {
connection.set("scm:git:https://github.com/kotest/kotest/")
developerConnection.set("scm:git:https://github.com/sksamuel/")
url.set("https://github.com/kotest/kotest/")
}

licenses {
license {
name.set("Apache-2.0")
url.set("https://opensource.org/licenses/Apache-2.0")
}
}

developers {
developer {
id.set("sksamuel")
name.set("Stephen Samuel")
email.set("sam@sksamuel.com")
}
developers {
developer {
id.set("sksamuel")
name.set("Stephen Samuel")
email.set("sam@sksamuel.com")
}
}
}
}
}

publishPlatformArtifactsInRootModule(project)

//region Maven Central can't handle parallel uploads, so limit parallel uploads with a BuildService
abstract class MavenPublishLimiter : BuildService<BuildServiceParameters.None>

val mavenPublishLimiter =
gradle.sharedServices.registerIfAbsent("mavenPublishLimiter", MavenPublishLimiter::class) {
maxParallelUsages = 1
}

tasks.withType<PublishToMavenRepository>().configureEach {
usesService(mavenPublishLimiter)
}
//endregion
8 changes: 5 additions & 3 deletions buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ plugins {
}

repositories {
google()
mavenCentral()
mavenLocal()
maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
google()
maven("https://oss.sonatype.org/content/repositories/snapshots/") {
mavenContent { snapshotsOnly() }
}
gradlePluginPortal() // tvOS builds need to be able to fetch a kotlin gradle plugin
mavenLocal()
}

testlogger {
Expand Down
71 changes: 71 additions & 0 deletions buildSrc/src/main/kotlin/publishingUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import groovy.util.Node
import groovy.util.NodeList
import org.gradle.api.Project
import org.gradle.api.XmlProvider
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.configurationcache.extensions.capitalized
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.withType
import org.gradle.plugins.signing.SigningExtension

//region manually define accessors, because IntelliJ _still_ doesn't index them properly :(
internal val Project.signing get() = extensions.getByType<SigningExtension>()
internal fun Project.signing(configure: SigningExtension.() -> Unit = {}): Unit = signing.configure()
internal val Project.publishing get() = extensions.getByType<PublishingExtension>()
internal fun Project.publishing(configure: PublishingExtension.() -> Unit = {}): Unit = publishing.configure()
//endregion

/**
* Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
* metadata can still get the platform artifact and transitive dependencies from the POM
* (see details in https://youtrack.jetbrains.com/issue/KT-39184#focus=streamItem-27-4115233.0-0)
*/
internal fun publishPlatformArtifactsInRootModule(project: Project) {
val platformPublication: MavenPublication =
project.publishing.publications.named<MavenPublication>("jvm").get()
val kmpPublication: MavenPublication =
project.publishing.publications.named<MavenPublication>("kotlinMultiplatform").get()

lateinit var platformXml: XmlProvider
platformPublication.pom?.withXml { platformXml = this }

// replace pom
kmpPublication.pom.withXml {
val xmlProvider = this
val root = xmlProvider.asNode()
// Remove the original content and add the content from the platform POM:
root.children().toList().forEach { root.remove(it as Node) }
platformXml.asNode().children().forEach { root.append(it as Node) }

// Adjust the self artifact ID, as it should match the root module's coordinates:
((root.get("artifactId") as NodeList).get(0) as Node).setValue(kmpPublication.artifactId)

// Set packaging to POM to indicate that there's no artifact:
root.appendNode("packaging", "pom")

// Remove the original platform dependencies and add a single dependency on the platform
// module:
val dependencies = (root.get("dependencies") as NodeList).get(0) as Node
dependencies.children().toList().forEach { dependencies.remove(it as Node) }
val singleDependency = dependencies.appendNode("dependency")
singleDependency.appendNode("groupId", platformPublication.groupId)
singleDependency.appendNode("artifactId", platformPublication.artifactId)
singleDependency.appendNode("version", platformPublication.version)
singleDependency.appendNode("scope", "compile")
}

project.tasks
.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }
.configureEach {
dependsOn("generatePomFileFor${platformPublication.name.capitalized()}Publication")

// Disable Config Cache to prevent error:
// Task `:[...]:generatePomFileForKotlinMultiplatformPublication` of type `GenerateMavenPom`:
// cannot serialize object of type 'DefaultMavenPublication', a subtype of 'Publication',
// as these are not supported with the configuration cache.
notCompatibleWithConfigurationCache("publishPlatformArtifactsInRootModule")
}
}
24 changes: 8 additions & 16 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,22 @@ ossrhPassword=xx
gradle.publish.key=xx
gradle.publish.secret=xx

# See https://dev.to/jmfayard/configuring-gradle-with-gradle-properties-211k
org.gradle.parallel=false
kotlin.code.style=official

org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=756m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
systemProp.org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=756m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=true

org.gradle.caching=true
org.gradle.parallel=false
org.gradle.daemon=true
org.gradle.configuration-cache=true
org.gradle.configureondemand=false
#https://github.com/gradle/gradle/issues/11308
org.gradle.internal.publish.checksums.insecure=true
systemProp.org.gradle.internal.publish.checksums.insecure=true
kotlin.native.disableCompilerDaemon=true

kotlin.native.ignoreDisabledTargets=true
systemProp.kotlin.native.disableCompilerDaemon=true
org.gradle.configureondemand=false
kotlin.mpp.stability.nowarn=true
# https://youtrack.jetbrains.com/issue/KT-58063 (should be fixed in Kotlin 1.9)
org.gradle.configuration-cache=false

android.useAndroidX=true
android.enableJetifier=true
kotlin.native.ignoreIncorrectDependencies=true

kotlin.incremental=true
kotlin.incremental.js=true

org.gradle.caching=true
android.useAndroidX=true
android.enableJetifier=true
Loading

0 comments on commit 7b4fe30

Please sign in to comment.