Skip to content

Commit

Permalink
Add maven central publication (#1688)
Browse files Browse the repository at this point in the history
* Add OSSRH repositories

* Rewrite Gradle plugin publication

* Add publication version assertion

* Use Nexus publish plugin for publishing to Sonatype

* Remove explicit publishing from s3 tests

* Don't document Dokka for local publication

* Fix a bug with closing Sonatype repository

* Bump internal Dokka version

* Move publication version check to the validate task

* Fix Gradle plugin publication

* Bump Dokka and gradle plugin-publish versions

* Do not run Dokka for test tasks

* Do not fail all runs in a workflow

* Reduce JVM memory limit
  • Loading branch information
kamildoleglo committed Jun 23, 2021
1 parent 5227751 commit c2182b7
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 58 deletions.
1 change: 1 addition & 0 deletions .github/workflows/gradle-test.pr.yml
Expand Up @@ -19,6 +19,7 @@ jobs:
strategy:
matrix:
version: [ 11, 15, 16 ]
fail-fast: false
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
Expand Down
9 changes: 0 additions & 9 deletions .github/workflows/s3-snapshots.yml
Expand Up @@ -19,9 +19,6 @@ jobs:
with:
java-version: 12

- name: Publish dokka locally
run: ./gradlew clean publishToMavenLocal --stacktrace

- name: Document stdlib
run: ./gradlew :integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.StdlibGradleIntegrationTest --stacktrace
env:
Expand Down Expand Up @@ -52,9 +49,6 @@ jobs:
with:
java-version: 12

- name: Publish dokka locally
run: ./gradlew clean publishToMavenLocal --stacktrace

- name: Document serialization
run: ./gradlew :integration-tests:gradle:integrationTest --tests org.jetbrains.dokka.it.gradle.kotlin.SerializationGradleIntegrationTest --stacktrace
env:
Expand Down Expand Up @@ -85,9 +79,6 @@ jobs:
with:
java-version: 12

- name: Publish dokka locally
run: ./gradlew clean publishToMavenLocal --stacktrace

- name: Document biojava-core
run: ./gradlew :integration-tests:maven:integrationTest --tests org.jetbrains.dokka.it.maven.BiojavaIntegrationTest --stacktrace
env:
Expand Down
28 changes: 20 additions & 8 deletions build.gradle.kts
@@ -1,11 +1,11 @@
import org.jetbrains.ValidatePublications
import org.jetbrains.configureDokkaVersion
import org.jetbrains.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm") apply false
id("java")
id("org.jetbrains.dokka") version "1.4.10.2"
id("org.jetbrains.dokka") version "1.4.32"
id("io.github.gradle-nexus.publish-plugin")
}

val dokka_version: String by project
Expand Down Expand Up @@ -55,16 +55,13 @@ subprojects {
val dokkaOutputDir = "$buildDir/dokka"

dokkaHtml {
onlyIf { !isLocalPublication }
outputDirectory.set(file(dokkaOutputDir))
}

val deleteDokkaOutputDir by registering(Delete::class) {
delete(dokkaOutputDir)
}

register<Jar>("javadocJar") {
dependsOn(deleteDokkaOutputDir, dokkaHtml)
archiveClassifier.set("javadoc")
dependsOn(dokkaHtml)
from(dokkaOutputDir)
}
}
Expand All @@ -80,3 +77,18 @@ tasks.whenTaskAdded {

println("Publication version: $dokka_version")
tasks.register<ValidatePublications>("validatePublications")

nexusPublishing {
repositories {
sonatype {
username.set(System.getenv("SONATYPE_USER"))
password.set(System.getenv("SONATYPE_PASSWORD"))
}
}
}

tasks.maybeCreate("dokkaPublish").run {
if (publicationChannels.any { it.isMavenRepository }) {
finalizedBy(tasks.named("closeAndReleaseSonatypeStagingRepository"))
}
}
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Expand Up @@ -10,4 +10,5 @@ dependencies {
implementation("com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4")
implementation("com.github.jengelman.gradle.plugins:shadow:2.0.4")
implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.4.0")
implementation("io.github.gradle-nexus:publish-plugin:1.0.0")
}
28 changes: 24 additions & 4 deletions buildSrc/src/main/kotlin/org/jetbrains/DokkaPublicationChannel.kt
Expand Up @@ -4,18 +4,36 @@ package org.jetbrains

import org.gradle.api.Project

internal enum class DokkaPublicationChannel {
enum class DokkaPublicationChannel {
SpaceDokkaDev,
BintrayKotlinDev,
BintrayKotlinEap,
BintrayKotlinDokka;
BintrayKotlinDokka,
MavenCentral,
MavenCentralSnapshot;

val isSpaceRepository get() = this == SpaceDokkaDev

val isBintrayRepository
get() = when (this) {
SpaceDokkaDev -> false
BintrayKotlinDev, BintrayKotlinEap, BintrayKotlinDokka -> true
else -> false
}

val isMavenRepository
get() = when (this) {
MavenCentral, MavenCentralSnapshot -> true
else -> false
}

val acceptedDokkaVersionTypes: List<DokkaVersionType>
get() = when(this) {
MavenCentral -> listOf(DokkaVersionType.Release)
MavenCentralSnapshot -> listOf(DokkaVersionType.Snapshot)
SpaceDokkaDev -> listOf(DokkaVersionType.Release, DokkaVersionType.Dev, DokkaVersionType.MC, DokkaVersionType.Snapshot)
BintrayKotlinDev -> listOf(DokkaVersionType.Dev, DokkaVersionType.MC, DokkaVersionType.Snapshot)
BintrayKotlinEap -> listOf(DokkaVersionType.MC)
BintrayKotlinDokka -> listOf(DokkaVersionType.Release)
}

companion object {
Expand All @@ -24,12 +42,14 @@ internal enum class DokkaPublicationChannel {
"bintray-kotlin-dev" -> BintrayKotlinDev
"bintray-kotlin-eap" -> BintrayKotlinEap
"bintray-kotlin-dokka" -> BintrayKotlinDokka
"maven-central-release" -> MavenCentral
"maven-central-snapshot" -> MavenCentralSnapshot
else -> throw IllegalArgumentException("Unknown dokka_publication_channel=$value")
}
}
}

internal val Project.publicationChannels: Set<DokkaPublicationChannel>
val Project.publicationChannels: Set<DokkaPublicationChannel>
get() {
val publicationChannel = this.properties["dokka_publication_channel"]?.toString()
val publicationChannels = this.properties["dokka_publication_channels"]?.toString()
Expand Down
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/org/jetbrains/DokkaVersion.kt
Expand Up @@ -24,3 +24,6 @@ private fun dokkaVersionFromBase(baseVersion: String): String {

val Project.dokkaVersion: String
get() = configureDokkaVersion()

val Project.dokkaVersionType: DokkaVersionType?
get() = DokkaVersionType.values().find { it.suffix.matches(dokkaVersion.substringAfter("-", "")) }
5 changes: 5 additions & 0 deletions buildSrc/src/main/kotlin/org/jetbrains/DokkaVersionType.kt
@@ -0,0 +1,5 @@
package org.jetbrains

enum class DokkaVersionType(val suffix: Regex) {
Release("^$".toRegex()), Snapshot("SNAPSHOT".toRegex()), Dev("dev-\\d+".toRegex()), MC("mc-\\d+".toRegex())
}
16 changes: 15 additions & 1 deletion buildSrc/src/main/kotlin/org/jetbrains/ValidatePublications.kt
Expand Up @@ -19,7 +19,7 @@ open class ValidatePublications : DefaultTask() {
class UnpublishedProjectDependencyException(
project: Project, dependencyProject: Project
) : GradleException(
"Published project ${project.path} cannot depend on unpublished projed ${dependencyProject.path}"
"Published project ${project.path} cannot depend on unpublished project ${dependencyProject.path}"
)


Expand All @@ -36,6 +36,7 @@ open class ValidatePublications : DefaultTask() {
checkPublicationIsConfiguredForBintray(subProject, publication)
}
checkProjectDependenciesArePublished(subProject)
subProject.assertPublicationVersion()
}
}
}
Expand Down Expand Up @@ -72,6 +73,19 @@ open class ValidatePublications : DefaultTask() {
}
}

private fun Project.assertPublicationVersion() {
if (System.getenv("SKIP_VERSION_CHECK")?.contains("true", ignoreCase = true) == true)
return

if (!publicationChannels.all { publicationChannel ->
publicationChannel.acceptedDokkaVersionTypes.any { acceptedVersionType ->
acceptedVersionType == dokkaVersionType
}
}) {
throw AssertionError("Wrong version $dokkaVersion for configured publication channels $publicationChannels")
}
}

init {
group = "verification"
project.tasks.named("check") {
Expand Down
42 changes: 31 additions & 11 deletions buildSrc/src/main/kotlin/org/jetbrains/publication.kt
Expand Up @@ -4,13 +4,13 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowExtension
import com.jfrog.bintray.gradle.BintrayExtension
import kotlinx.validation.ApiValidationExtension
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
import org.gradle.kotlin.dsl.*
import org.gradle.plugins.signing.SigningExtension
import org.jetbrains.DokkaPublicationChannel.*
import io.github.gradlenexus.publishplugin.NexusPublishExtension
import java.net.URI

class DokkaPublicationBuilder {
Expand All @@ -26,24 +26,25 @@ class DokkaPublicationBuilder {
fun Project.registerDokkaArtifactPublication(publicationName: String, configure: DokkaPublicationBuilder.() -> Unit) {
configure<PublishingExtension> {
publications {
val publicationProvider = register<MavenPublication>(publicationName) {
register<MavenPublication>(publicationName) {
val builder = DokkaPublicationBuilder().apply(configure)
artifactId = builder.artifactId
when (builder.component) {
DokkaPublicationBuilder.Component.Java -> from(components["java"])
DokkaPublicationBuilder.Component.Shadow -> run {
artifact(tasks["sourcesJar"])
extensions.getByType(ShadowExtension::class.java).component(this)
artifact(tasks["sourcesJar"])
}
}
artifact(tasks["javadocJar"])
configurePom("Dokka ${project.name}")
}
signPublicationIfKeyPresent(publicationProvider)
}
}

configureBintrayPublicationIfNecessary(publicationName)
configureSpacePublicationIfNecessary(publicationName)
configureSonatypePublicationIfNecessary(publicationName)
createDokkaPublishTaskIfNecessary()
registerBinaryCompatibilityCheck(publicationName)
}
Expand Down Expand Up @@ -83,6 +84,11 @@ fun Project.createDokkaPublishTaskIfNecessary() {
if (publicationChannels.any { it.isSpaceRepository }) {
dependsOn(tasks.named("publish"))
}

if (publicationChannels.any { it.isMavenRepository }) {
dependsOn(tasks.named("publishToSonatype"))
}

if (publicationChannels.any { it.isBintrayRepository }) {
dependsOn(tasks.named("bintrayUpload"))
}
Expand Down Expand Up @@ -110,7 +116,7 @@ private fun Project.configureBintrayPublication(vararg publications: String) {
}

repo = when (bintrayPublicationChannels.single()) {
SpaceDokkaDev -> throw IllegalStateException("$SpaceDokkaDev is not a bintray repository")
SpaceDokkaDev, MavenCentral, MavenCentralSnapshot -> throw IllegalStateException("${bintrayPublicationChannels.single()} is not a bintray repository")
BintrayKotlinDev -> "kotlin-dev"
BintrayKotlinEap -> "kotlin-eap"
BintrayKotlinDokka -> "dokka"
Expand All @@ -129,8 +135,13 @@ private fun Project.configureBintrayPublication(vararg publications: String) {
}
}

fun Project.configureSonatypePublicationIfNecessary(vararg publications: String) {
if (publicationChannels.any { it.isMavenRepository }) {
signPublicationsIfKeyPresent(*publications)
}
}

private fun MavenPublication.configurePom(projectName: String) {
fun MavenPublication.configurePom(projectName: String) {
pom {
name.set(projectName)
description.set("Dokka is a documentation engine for Kotlin and Java, performing the same function as Javadoc for Java")
Expand Down Expand Up @@ -161,14 +172,23 @@ private fun MavenPublication.configurePom(projectName: String) {
}

@Suppress("UnstableApiUsage")
private fun Project.signPublicationIfKeyPresent(publicationProvider: Provider<MavenPublication>) {
val signingKey = System.getenv("SIGN_KEY")
val signingKeyPassphrase = System.getenv("SIGN_KEY_PASSPHRASE")
private fun Project.signPublicationsIfKeyPresent(vararg publications: String) {
val signingKeyId: String? = System.getenv("SIGN_KEY_ID")
val signingKey: String? = System.getenv("SIGN_KEY")
val signingKeyPassphrase: String? = System.getenv("SIGN_KEY_PASSPHRASE")

if (!signingKey.isNullOrBlank()) {
extensions.configure<SigningExtension>("signing") {
useInMemoryPgpKeys(signingKey, signingKeyPassphrase)
sign(publicationProvider.get())
if (signingKeyId?.isNotBlank() == true) {
useInMemoryPgpKeys(signingKeyId, signingKey, signingKeyPassphrase)
} else {
useInMemoryPgpKeys(signingKey, signingKeyPassphrase)
}
publications.forEach { publicationName ->
extensions.findByType(PublishingExtension::class)!!.publications.findByName(publicationName)?.let {
sign(it)
}
}
}
}
}
9 changes: 9 additions & 0 deletions buildSrc/src/main/kotlin/org/jetbrains/taskUtils.kt
@@ -1,5 +1,6 @@
package org.jetbrains

import org.gradle.api.Project
import org.gradle.api.Task

fun Task.dependsOnMavenLocalPublication() {
Expand All @@ -11,3 +12,11 @@ fun Task.dependsOnMavenLocalPublication() {
}
}
}

val Project.isLocalPublication: Boolean
get() = gradle.startParameter.taskNames.any {
it.endsWith("publishToMavenLocal", ignoreCase = true) ||
it.endsWith("integrationTest", ignoreCase = true) ||
it.endsWith("check", ignoreCase = true) ||
it.endsWith("test", ignoreCase = true)
}
6 changes: 3 additions & 3 deletions gradle.properties
@@ -1,6 +1,6 @@
# Project Settings
dokka_version_base=1.5.0
dokka_publication_channels=bintray-kotlin-dev&space-dokka-dev
dokka_publication_channels=maven-central-snapshot&space-dokka-dev
dokka_integration_test_parallelism=2
# Versions
kotlin_version=1.5.0
Expand All @@ -13,5 +13,5 @@ language_version=1.4
# Code style
kotlin.code.style=official
# Gradle settings
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=2g
org.gradle.parallel=true
4 changes: 4 additions & 0 deletions plugins/base/build.gradle.kts
Expand Up @@ -44,6 +44,10 @@ tasks {
dependsOn(copyFrontend)
}

sourcesJar {
dependsOn(processResources)
}

test {
maxHeapSize = "4G"
}
Expand Down

0 comments on commit c2182b7

Please sign in to comment.