Skip to content

Commit

Permalink
feat!: add support for selecting the Dokka type to be included in the…
Browse files Browse the repository at this point in the history
… publication (#567)

* feat!: remove class MavenRepositoryDescriptor

* feat: support selection of which dokkaTask should be used for generating javadoc artifacts to be published

* fix: factorize Dokka-related stuff management

* chore(test): test docStyle property

* feat(doc): explain property in README.md

* docs: improve description of docStyle in the readme
  • Loading branch information
gciatto authored and DanySK committed Apr 2, 2023
1 parent 4dcb292 commit 4382aae
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 62 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ publishOnCentral {
repoOwner.set("DanySK") // Used to populate the default value for projectUrl and scmConnection
projectUrl.set("https://github.com/${repoOwner}/${project.name}")
scmConnection.set("scm:git:https://github.com/${repoOwner}/${project.name}")
/*
* If the project is a Kotlin multiplatform project, Dokka can not generate the Javadocs correctly.
* In these cases, the plugin by default may fail.
* This option can be used to select a different documentation format for the Dokka engine,
* in case you want to publish on Central a jar with a reasonable (altough not Javadoc-compatible content)
* we recommend DocStyle.HTML.
*/
docStyle.set(org.danilopianini.gradle.mavencentral.DocStyle.JAVADOC) // alternatives are GFM, HTML, and JEKYLL

/*
* The plugin is pre-configured to fetch credentials for Maven Central from the context in the following order:
* 1. Environment variables MAVEN_CENTRAL_USERNAME and MAVEN_CENTRAL_PASSWORD
Expand Down Expand Up @@ -116,6 +125,7 @@ publishOnCentral {
nexusUrl = "https://some/valid/nexus/instance"
// nexusTimeOut and nexusConnectionTimeOut can be configured, too.
}

/*
* A simplified handler is available for publishing on the Snapshots repository of Maven Central
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fun Project.configureRepository(repoToConfigure: Repository) {
publishing.repositories { repository ->
repository.maven { mavenArtifactRepository ->
mavenArtifactRepository.name = repoToConfigure.name
mavenArtifactRepository.url = URI(repoToConfigure.url)
mavenArtifactRepository.url = repoToConfigure.url.map { URI(it) }.get()
mavenArtifactRepository.credentials { credentials ->
credentials.username = repoToConfigure.user.orNull
credentials.password = repoToConfigure.password.orNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.danilopianini.gradle.mavencentral

/**
* Admissible type of styles used by Dokka to generate documentation from KDoc.
*/
enum class DocStyle {
GFM, HTML, JAVADOC, JEKYLL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.danilopianini.gradle.mavencentral

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.provider.Property
import org.gradle.api.tasks.TaskCollection

/**
* Looks for the class `DokkaPlugin`, which will only be available if the plugin user is applying the Dokka plugin.
*/
internal val dokkaPluginClass: Result<Class<Plugin<*>>> = runCatching {
@Suppress("UNCHECKED_CAST")
Class.forName("org.jetbrains.dokka.gradle.DokkaPlugin") as Class<Plugin<*>>
}

/**
* Looks for the class `DokkaTask`, which will only be available if the plugin user is applying the Dokka plugin.
*/
internal val dokkaTaskClass: Result<Class<out Task>> = dokkaPluginClass.mapCatching {
@Suppress("UNCHECKED_CAST")
Class.forName("org.jetbrains.dokka.gradle.DokkaTask") as Class<out Task>
}

/**
* Selects the available Dokka tasks supporting the generation of [docStyle]-style documentation.
* There may be no such tasks, if the plugin user did not apply the Dokka plugin.
*/
internal fun Project.dokkaTasksFor(docStyle: Property<DocStyle>): TaskCollection<out Task> =
dokkaTaskClass
.map { dokkaTaskType ->
tasks.withType(dokkaTaskType).matching {
it.name.startsWith("dokka") && it.name.endsWith(docStyle.get().name, ignoreCase = true)
}
}
.getOrElse { tasks.matching { false } }

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,18 @@ class PublishOnCentral : Plugin<Project> {
}
project.tasks.withType(SourceJar::class.java).configureEach { it.sourceSet("main", true) }
}
val dokkaPluginClass = runCatching { Class.forName("org.jetbrains.dokka.gradle.DokkaPlugin") }
if (dokkaPluginClass.isSuccess) {
@Suppress("UNCHECKED_CAST")
project.plugins.withType(dokkaPluginClass.getOrThrow() as Class<Plugin<*>>).configureEach {
project.plugins.withType(dokkaPluginClass.getOrThrow()).configureEach {
project.tasks.withType(JavadocJar::class.java).configureEach { javadocJar ->
val dokkaJavadoc = checkNotNull(project.tasks.findByName("dokkaJavadoc")) {
"Dokka plugin applied but no dokkaJavadoc task existing!"
val dokkaTask = checkNotNull(project.dokkaTasksFor(extension.docStyle).firstOrNull()) {
"Dokka plugin applied but no task exists for style ${extension.docStyle.get()}!"
}
val outputDirectory = dokkaJavadoc.property("outputDirectory")
val outputDirectory = dokkaTask.property("outputDirectory")
?: throw IllegalStateException(
"dokkaJavadoc has no property 'outputDirectory' - " +
"maybe this version is incompatible with publish-on-central?"
)
javadocJar.dependsOn(dokkaJavadoc)
javadocJar.dependsOn(dokkaTask)
javadocJar.from(outputDirectory)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.danilopianini.gradle.mavencentral

import MavenRepositoryDescriptor
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.kotlin.dsl.property
Expand All @@ -24,7 +23,7 @@ open class PublishOnCentralExtension(val project: Project) {
*/
val mavenCentral: Repository = Repository(
Repository.mavenCentralName,
url = Repository.mavenCentralURL,
url = project.propertyWithDefaultProvider { Repository.mavenCentralURL },
user = project.propertyWithDefaultProvider {
System.getenv("MAVEN_CENTRAL_USERNAME")
?: project.properties["mavenCentralUsername"]?.toString()
Expand Down Expand Up @@ -87,24 +86,24 @@ open class PublishOnCentralExtension(val project: Project) {
repoOwner.map { "https://github.com/$it/${project.name}" }
)

/**
* The style of `javadoc` artifacts being published on Maven repositories.
*/
val docStyle: Property<DocStyle> = project.objects.property<DocStyle>().convention(
DocStyle.JAVADOC
)

/**
* Utility to configure a new Maven repository as target.
*/
@JvmOverloads fun repository(
url: String,
name: String = repositoryNameFromURL(url),
configurator: MavenRepositoryDescriptor.() -> Unit = { }
configurator: Repository.() -> Unit = { }
) {
val repoDescriptor = MavenRepositoryDescriptor(project, name).apply(configurator)
val repo = Repository(
repoDescriptor.name,
url,
repoDescriptor.user,
repoDescriptor.password,
repoDescriptor.nexusUrl,
repoDescriptor.nexusTimeOut,
repoDescriptor.nexusConnectionTimeout,
)
val repo = Repository.fromProject(project, name)
repo.url.set(url)
repo.apply(configurator)
project.afterEvaluate { it.configureRepository(repo) }
}

Expand All @@ -113,7 +112,7 @@ open class PublishOnCentralExtension(val project: Project) {
*/
@JvmOverloads fun mavenCentralSnapshotsRepository(
name: String = "MavenCentralSnapshots",
configurator: MavenRepositoryDescriptor.() -> Unit = { },
configurator: Repository.() -> Unit = { },
) = repository(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/", name = name) {
user.set(mavenCentral.user)
password.set(mavenCentral.password)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.danilopianini.gradle.mavencentral

import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.kotlin.dsl.property
import java.time.Duration

/**
Expand All @@ -12,8 +13,8 @@ import java.time.Duration
* Time outs can be set with [nexusTimeOut] and [nexusConnectTimeOut].
*/
data class Repository(
val name: String,
val url: String,
var name: String,
val url: Property<String>,
val user: Property<String>,
val password: Property<String>,
val nexusUrl: String? = null,
Expand Down Expand Up @@ -44,5 +45,16 @@ data class Repository(
* The Sonatype Nexus instance URL of Maven Central.
*/
const val mavenCentralNexusUrl = "https://s01.oss.sonatype.org/service/local/"

/**
* Creates a named [Repository] from a [project] and a [name].
*/
fun fromProject(project: Project, name: String): Repository =
Repository(
name = name,
url = project.objects.property(),
user = project.objects.property(),
password = project.objects.property()
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@file:Suppress("UnstableApiUsage")

import org.danilopianini.gradle.mavencentral.DocStyle
import org.danilopianini.gradle.mavencentral.JavadocJar
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
Expand Down Expand Up @@ -122,6 +123,7 @@ signing {
}

publishOnCentral {
docStyle.set(DocStyle.HTML)
projectLongName.set("Template for Kotlin Multiplatform Project")
projectDescription.set("A template repository for Kotlin Multiplatform projects")
repository("https://maven.pkg.github.com/danysk/${rootProject.name}".toLowerCase()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.danilopianini.gradle.mavencentral.DocStyle
plugins {
`java-library`
`java-gradle-plugin`
Expand All @@ -6,6 +7,7 @@ plugins {
group = "io.github.danysk"
version = "0.1.0"
publishOnCentral {
docStyle.set(DocStyle.JAVADOC)
repoOwner.set("test")
projectDescription.set("test")
repository("https://maven.pkg.github.com/OWNER/REPOSITORY") {
Expand Down

0 comments on commit 4382aae

Please sign in to comment.