Skip to content

Commit

Permalink
replace dev.adamko.dev-publish with custom implementation that uses…
Browse files Browse the repository at this point in the history
… `maven.repo.local`
  • Loading branch information
adam-enko committed Feb 23, 2024
1 parent 67ba564 commit b29f542
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 49 deletions.
2 changes: 0 additions & 2 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,4 @@ dependencies {
// workaround for accessing version-catalog in convention plugins
// https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))

implementation(libs.gradlePlugin.devPublish)
}
124 changes: 124 additions & 0 deletions build-logic/src/main/kotlin/dokkabuild.dev-maven-publish.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import dokkabuild.internal.consumable
import dokkabuild.internal.declarable
import dokkabuild.internal.resolvable
import dokkabuild.DevMavenPublishExtension
import dokkabuild.DevMavenPublishExtension.Companion.DEV_MAVEN_PUBLISH_EXTENSION_NAME
import org.gradle.kotlin.dsl.support.uppercaseFirstChar

/**
* Utility for publishing a project to a local Maven directory for use in integration tests.
*
* Using a local directory is beneficial because Maven Local
* [has some flaws](https://docs.gradle.org/8.6/userguide/declaring_repositories.html#sec:case-for-maven-local),
* and we can more tightly control what artifacts are published and are persisted.
*
* It's possible to publish to a local directory using a regular [PublishToMavenRepository] task,
* but when the project has a SNAPSHOT version the output will be timestamped, so Gradle will
* _always_ publish a new artifact. This causes two issues:
*
* - The publication tasks, and any test tasks, will _always_ be out-of-date, even if no code changed.
* - The local directory will endlessly grow in size
* (which can be remedied by running `./gradlew clean`, but this is not ideal)
*
* To overcome this we manually set the system property `maven.repo.local` to a local directory.
* Gradle will respect this property, and publish artifacts to the local directory only when
* they have changed, improving performance.
*/
plugins {
base
}

/**
* Directory for the output of the current subproject's 'publishToMavenLocal'
*/
val currentProjectDevMavenRepo = gradle.rootProject.layout.buildDirectory.dir("dev-maven-repo")

val devMavenPublishAttribute = Attribute.of("dev-maven-publish", String::class.java)

dependencies {
attributesSchema {
attribute(devMavenPublishAttribute)
}
}

val publishToDevMavenRepo by tasks.registering {
description = "Publishes all Maven publications to the dev Maven repository."
group = PublishingPlugin.PUBLISH_TASK_GROUP
}


plugins.withType<MavenPublishPlugin>().all {
extensions
.getByType<PublishingExtension>()
.publications
.withType<MavenPublication>().all publication@{
val publicationName = this@publication.name
val installTaskName = "publish${publicationName.uppercaseFirstChar()}PublicationToDevMavenRepo"

// Register a new publication task for each publication.
val installTask = tasks.register<PublishToMavenLocal>(installTaskName) {
description = "Publishes Maven publication '$publicationName' to the test Maven repository."
group = PublishingPlugin.PUBLISH_TASK_GROUP
publication = this@publication

val destinationDir = currentProjectDevMavenRepo.get().asFile
inputs.property("currentProjectDevMavenRepoPath", destinationDir.invariantSeparatorsPath)

doFirst {
/**
* `maven.repo.local` will set the destination directory for this [PublishToMavenLocal] task.
*
* @see org.gradle.api.internal.artifacts.mvnsettings.DefaultLocalMavenRepositoryLocator.getLocalMavenRepository
*/
System.setProperty("maven.repo.local", destinationDir.absolutePath)
}
}

publishToDevMavenRepo.configure {
dependsOn(installTask)
}

tasks.check {
mustRunAfter(installTask)
}
}
}


val devPublication: Configuration by configurations.creating {
description = "Depend on project-local Dev Maven repositories"
declarable()
}

val devPublicationResolver: Configuration by configurations.creating {
description = "Resolve project-local Dev Maven repositories"
resolvable()
extendsFrom(devPublication)
attributes {
attribute(devMavenPublishAttribute, "devMavenRepo")
}
}

val devPublicationConsumable: Configuration by configurations.creating {
description = "Provide project-local Dev Maven repositories dependencies"
consumable()
attributes {
attribute(devMavenPublishAttribute, "devMavenRepo")
}
outgoing {
artifact(currentProjectDevMavenRepo) {
builtBy(publishToDevMavenRepo)
}
}
}

val devMavenPublishExtension = extensions.create<DevMavenPublishExtension>(
DEV_MAVEN_PUBLISH_EXTENSION_NAME,
// fetch Dev Maven Repos from the dependencies
devPublicationResolver.incoming.artifacts.resolvedArtifacts.map { incoming ->
incoming.map { it.file }
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
id("dokkabuild.base")
`maven-publish`
signing
id("dev.adamko.dev-publish")
id("dokkabuild.dev-maven-publish")
}

publishing {
Expand Down
18 changes: 18 additions & 0 deletions build-logic/src/main/kotlin/dokkabuild/DevMavenPublishExtension.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package dokkabuild

import org.gradle.api.provider.Provider
import java.io.File

abstract class DevMavenPublishExtension(
/**
* Resolves Dev Maven repos from the current project's dependencies.
*/
val devMavenRepositories: Provider<List<File>>,
) {
companion object {
const val DEV_MAVEN_PUBLISH_EXTENSION_NAME = "devMavenPublish"
}
}
61 changes: 61 additions & 0 deletions build-logic/src/main/kotlin/dokkabuild/internal/gradleUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package dokkabuild.internal

import org.gradle.api.artifacts.Configuration

/**
* Mark this [Configuration] as one that will be consumed by other subprojects.
*
* ```
* isCanBeResolved = false
* isCanBeConsumed = true
* isCanBeDeclared = false
* ```
*/
fun Configuration.consumable(
visible: Boolean = false
) {
isVisible = visible
isCanBeResolved = false
isCanBeConsumed = true
isCanBeDeclared = false
}

/**
* Mark this [Configuration] as one that will consume artifacts from other subprojects (also known as 'resolving')
*
* ```
* isCanBeResolved = true
* isCanBeConsumed = false
* isCanBeDeclared = false
* ```
*/
fun Configuration.resolvable(
visible: Boolean = false
) {
isVisible = visible
isCanBeResolved = true
isCanBeConsumed = false
isCanBeDeclared = false
}

/**
* Mark this [Configuration] as one that will be used to declare dependencies.
*
* ```
* isCanBeResolved = false
* isCanBeConsumed = false
* isCanBeDeclared = true
* ```
*/
fun Configuration.declarable(
visible: Boolean = false
) {
isVisible = visible
isCanBeResolved = false
isCanBeConsumed = false
isCanBeDeclared = true
}
25 changes: 17 additions & 8 deletions dokka-integration-tests/gradle/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Disabled

plugins {
id("dokkabuild.kotlin-jvm")
id("dokkabuild.dev-maven-publish")
`jvm-test-suite`
`java-test-fixtures`
id("dev.adamko.dev-publish")
}

dependencies {
Expand Down Expand Up @@ -215,14 +215,23 @@ fun TestingExtension.registerTestProjectSuite(
templateSettingsGradleKts.asFile.invariantSeparatorsPath,
)

dependsOn(tasks.updateDevRepo)
inputs.dir(devPublish.devMavenRepo)
.withPropertyName("devPublish.devMavenRepo")
//region dev maven publish config

// Tell Gradle that the tests require 'publishToDevMavenRepo' tasks in the providing projects
dependsOn(configurations.devPublicationResolver)

val devMavenRepositories = devMavenPublish.devMavenRepositories
inputs.files(devMavenRepositories)
.withPropertyName("devMavenPublish.devMavenRepositories")
.withPathSensitivity(RELATIVE)
systemProperty(
"devMavenRepo",
devPublish.devMavenRepo.get().asFile.invariantSeparatorsPath
)

doFirst("workaround https://github.com/gradle/gradle/issues/12247") {
systemProperty(
"devMavenRepositories",
devMavenRepositories.get().joinToString(",") { it.invariantSeparatorsPath }
)
}
//endregion

if (jvm != null) {
javaLauncher = javaToolchains.launcherFor { languageVersion = jvm }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,36 +101,51 @@ abstract class AbstractGradleIntegrationTest : AbstractIntegrationTest() {
*/
val templateSettingsGradleKts: Path by systemProperty(Paths::get)

/** file-based Maven repositories that contains the Dokka dependencies */
private val devMavenRepo: Path by systemProperty(Paths::get)
/** file-based Maven repositories with Dokka dependencies */
private val devMavenRepositories: String by systemProperty { repos ->
val repoPaths = repos.split(",").map { Paths.get(it) }

val reposSpecs = repoPaths
.withIndex()
.joinToString(",\n") { (i, repoPath) ->
// Exclusive repository containing local Dokka artifacts.
// Must be compatible with both Groovy and Kotlin DSL.
/* language=kts */
"""
|maven {
| setUrl("${repoPath.invariantSeparatorsPathString}")
| name = "DokkaDevMavenRepo${i}"
|}
""".trimMargin()
}

/* language=kts */
"""
|exclusiveContent {
| forRepositories(
| $reposSpecs
| )
| filter {
| includeGroup("org.jetbrains.dokka")
| }
|}
|
""".trimMargin()
}

fun File.updateProjectLocalMavenDir() {

val dokkaDevMavenRepoMarker = "/* %{PROJECT_LOCAL_MAVEN_DIR}% */"

// Exclusive repository containing local Dokka artifacts.
// Must be compatible with both Groovy and Kotlin DSL.
val dokkaDevMavenRepoSpec = /* language=kts */ """
|exclusiveContent {
| forRepository{
| maven {
| setUrl("${devMavenRepo.invariantSeparatorsPathString}")
| name = "DokkaDevMavenRepo"
| }
| }
| filter {
| includeGroup("org.jetbrains.dokka")
| }
|}
|
""".trimMargin()

walk().filter { it.isFile }.forEach { file ->
val fileText = file.readText()

if (dokkaDevMavenRepoMarker in fileText) {
file.writeText(
fileText.replace(dokkaDevMavenRepoMarker, dokkaDevMavenRepoSpec)
fileText.replace(dokkaDevMavenRepoMarker, devMavenRepositories)
)
}
}
Expand Down
32 changes: 20 additions & 12 deletions dokka-integration-tests/maven/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import dokkabuild.tasks.GitCheckoutTask
import org.gradle.api.tasks.PathSensitivity.RELATIVE

plugins {
id("dokkabuild.test-integration")
id("dokkabuild.setup-maven-cli")
id("dev.adamko.dev-publish")
id("dokkabuild.dev-maven-publish")
}

dependencies {
Expand Down Expand Up @@ -46,12 +47,7 @@ val dokkaSubprojects = gradle.includedBuild("dokka")
val mavenPlugin = gradle.includedBuild("runner-maven-plugin")

tasks.integrationTest {
dependsOn(
tasks.updateDevRepo,
dokkaSubprojects.task(":publishToMavenLocal"),
mavenPlugin.task(":publishToMavenLocal"),
checkoutBioJava,
)
dependsOn(checkoutBioJava)

dependsOn(tasks.installMavenBinary)
val mvn = mavenCliSetup.mvn
Expand All @@ -60,11 +56,23 @@ tasks.integrationTest {
val dokkaVersion = provider { project.version.toString() }
inputs.property("dokkaVersion", dokkaVersion)

inputs.dir(devPublish.devMavenRepo).withPropertyName("devPublish.devMavenRepo")
systemProperty(
"devMavenRepo",
devPublish.devMavenRepo.get().asFile.invariantSeparatorsPath
)
//region dev maven publish config

// Tell Gradle that the tests require 'publishToDevMavenRepo' tasks in the providing projects
dependsOn(configurations.devPublicationResolver)

val devMavenRepositories = devMavenPublish.devMavenRepositories
inputs.files(devMavenRepositories)
.withPropertyName("devMavenPublish.devMavenRepositories")
.withPathSensitivity(RELATIVE)

doFirst {
systemProperty(
"devMavenRepositories",
devMavenRepositories.get().joinToString(",") { it.canonicalFile.invariantSeparatorsPath }
)
}
//endregion

doFirst("workaround for https://github.com/gradle/gradle/issues/24267") {
environment("DOKKA_VERSION", dokkaVersion.get())
Expand Down
Loading

0 comments on commit b29f542

Please sign in to comment.