From 03f9d78eb3a2a1196ca324498e577e0b1961b7b2 Mon Sep 17 00:00:00 2001 From: Alexander Likhachev Date: Tue, 13 Apr 2021 17:33:56 +0300 Subject: [PATCH] [Build] Add workaround to make local publishing serializable Also signing plugin now being applied only when signing is required. #KT-44611 In Progress --- .../plugins/KotlinBuildPublishingPlugin.kt | 36 +++++++++++-------- buildSrc/src/main/kotlin/tasks.kt | 36 +++++++++++++++++++ .../build.gradle.kts | 26 +++++++++++++- .../build.gradle | 28 +++++++++++++-- 4 files changed, 109 insertions(+), 17 deletions(-) diff --git a/buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt b/buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt index 022e49d7f12..946d56c8d8d 100644 --- a/buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt +++ b/buildSrc/src/main/kotlin/plugins/KotlinBuildPublishingPlugin.kt @@ -5,6 +5,7 @@ package plugins +import PublishToMavenLocalSerializable import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.attributes.Usage @@ -13,10 +14,10 @@ import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.plugins.MavenPublishPlugin +import org.gradle.api.publish.maven.tasks.PublishToMavenLocal import org.gradle.api.publish.maven.tasks.PublishToMavenRepository import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* -import org.gradle.plugins.signing.Sign import org.gradle.plugins.signing.SigningExtension import org.gradle.plugins.signing.SigningPlugin import java.util.* @@ -27,7 +28,6 @@ class KotlinBuildPublishingPlugin @Inject constructor( ) : Plugin { override fun apply(target: Project): Unit = with(target) { apply() - apply() val publishedRuntime = configurations.maybeCreate(RUNTIME_CONFIGURATION).apply { isCanBeConsumed = false @@ -132,32 +132,40 @@ fun Project.configureDefaultPublishing() { } } - configureSigning() + val signingRequired = project.providers.gradleProperty("signingRequired").forUseAtConfigurationTime().orNull?.toBoolean() + ?: project.providers.gradleProperty("isSonatypeRelease").forUseAtConfigurationTime().orNull?.toBoolean() ?: false + + if (signingRequired) { + apply() + configureSigning() + } tasks.register("install") { dependsOn(tasks.named("publishToMavenLocal")) } + // workaround for Gradle configuration cache + // TODO: remove it when https://github.com/gradle/gradle/pull/16945 merged into used in build Gradle version + tasks.withType(PublishToMavenLocal::class.java) { + val originalTask = this + val serializablePublishTask = + tasks.register(originalTask.name + "Serializable", PublishToMavenLocalSerializable::class.java) { + publication = originalTask.publication + } + originalTask.onlyIf { false } + originalTask.dependsOn(serializablePublishTask) + } + tasks.withType() .matching { it.name.endsWith("PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository") } .all { configureRepository() } } private fun Project.configureSigning() { - val signingRequired = provider { - project.findProperty("signingRequired")?.toString()?.toBoolean() - ?: project.property("isSonatypeRelease") as Boolean - } - configure { - setRequired(signingRequired) sign(extensions.getByType().publications) // all publications useGpgCmd() } - - tasks.withType().configureEach { - setOnlyIf { signingRequired.get() } - } } fun TaskProvider.configureRepository() = @@ -181,4 +189,4 @@ private fun PublishToMavenRepository.configureRepository() { } } } -} +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/tasks.kt b/buildSrc/src/main/kotlin/tasks.kt index 81b0997553d..36d4bbda491 100644 --- a/buildSrc/src/main/kotlin/tasks.kt +++ b/buildSrc/src/main/kotlin/tasks.kt @@ -7,13 +7,22 @@ // usages in build scripts are not tracked properly @file:Suppress("unused") +import org.gradle.api.InvalidUserDataException import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.file.FileSystemOperations import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter +import org.gradle.api.publish.internal.PublishOperation +import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal +import org.gradle.api.publish.maven.internal.publisher.MavenNormalizedPublication +import org.gradle.api.publish.maven.internal.publisher.MavenPublisher +import org.gradle.api.publish.maven.internal.publisher.ValidatingMavenPublisher +import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven +import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.testing.Test +import org.gradle.internal.serialization.Cached import org.gradle.kotlin.dsl.extra import org.gradle.kotlin.dsl.project import org.gradle.kotlin.dsl.support.serviceOf @@ -280,3 +289,30 @@ fun Task.useAndroidSdk() { fun Task.useAndroidJar() { TaskUtils.useAndroidJar(this) } + +// Workaround to make PublishToMavenLocal compatible with Gradle configuration cache +// TODO: remove it when https://github.com/gradle/gradle/pull/16945 merged into used in build Gradle version +abstract class PublishToMavenLocalSerializable : AbstractPublishToMaven() { + private val normalizedPublication = Cached.of { this.computeNormalizedPublication() } + + private fun computeNormalizedPublication(): MavenNormalizedPublication { + val publicationInternal: MavenPublicationInternal = publicationInternal + ?: throw InvalidUserDataException("The 'publication' property is required") + duplicatePublicationTracker.checkCanPublishToMavenLocal(publicationInternal) + return publicationInternal.asNormalisedPublication() + } + + @TaskAction + open fun publish() { + val normalizedPublication = normalizedPublication.get() + object : PublishOperation(normalizedPublication.name, "mavenLocal") { + override fun publish() { + val localPublisher = mavenPublishers.getLocalPublisher( + temporaryDirFactory + ) + val validatingPublisher: MavenPublisher = ValidatingMavenPublisher(localPublisher) + validatingPublisher.publish(normalizedPublication, null) + } + }.run() + } +} \ No newline at end of file diff --git a/libraries/examples/annotation-processor-example/build.gradle.kts b/libraries/examples/annotation-processor-example/build.gradle.kts index b9b1b951af3..1c046cd620b 100644 --- a/libraries/examples/annotation-processor-example/build.gradle.kts +++ b/libraries/examples/annotation-processor-example/build.gradle.kts @@ -4,7 +4,7 @@ description = "Simple Annotation Processor for testing kapt" plugins { kotlin("jvm") - maven // only used for installing to mavenLocal() + `maven-publish` // only used for installing to mavenLocal() id("jps-compatible") } @@ -18,4 +18,28 @@ dependencies { sourceSets { "test" {} +} + +publishing { + publications { + create("main") { + from(components["java"]) + } + } +} + +tasks.register("install") { + dependsOn(tasks.named("publishToMavenLocal")) +} + +// workaround for Gradle configuration cache +// TODO: remove it when https://github.com/gradle/gradle/pull/16945 merged into used in build Gradle version +tasks.withType(PublishToMavenLocal::class.java) { + val originalTask = this + val serializablePublishTask = + tasks.register(originalTask.name + "Serializable", PublishToMavenLocalSerializable::class.java) { + publication = originalTask.publication + } + originalTask.onlyIf { false } + originalTask.dependsOn(serializablePublishTask) } \ No newline at end of file diff --git a/libraries/examples/kotlin-gradle-subplugin-example/build.gradle b/libraries/examples/kotlin-gradle-subplugin-example/build.gradle index 6775b93549f..edccbb86802 100644 --- a/libraries/examples/kotlin-gradle-subplugin-example/build.gradle +++ b/libraries/examples/kotlin-gradle-subplugin-example/build.gradle @@ -1,5 +1,5 @@ apply plugin: 'kotlin' -apply plugin: 'maven' +apply plugin: 'maven-publish' apply plugin: 'jps-compatible' repositories { @@ -38,4 +38,28 @@ dependencies { // Relocate `com.intellij.*` and some other classes to match those in the `kotlin-compiler-embeddable` // (for example, the actual package at runtime is `org.jetbrains.kotlin.com.intellij.*`): ArtifactsKt.runtimeJar(project, EmbeddableKt.rewriteDefaultJarDepsToShadedCompiler(project, {}), {}) -// In a standalone build, you can setup the relocation with the Shadow plugin. \ No newline at end of file +// In a standalone build, you can setup the relocation with the Shadow plugin. + +publishing { + publications { + main(MavenPublication) { + artifact tasks.named("embeddable") + } + } +} + +tasks.register("install") { + dependsOn(tasks.named("publishToMavenLocal")) +} + +// workaround for Gradle configuration cache +// TODO: remove it when https://github.com/gradle/gradle/pull/16945 merged into used in build Gradle version +tasks.withType(PublishToMavenLocal) { + def originalTask = it + def serializablePublishTask = + tasks.register(originalTask.name + "Serializable", PublishToMavenLocalSerializable) { + publication = originalTask.publication + } + originalTask.onlyIf { false } + originalTask.dependsOn(serializablePublishTask) +}