diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..32bd05c089 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,42 @@ +# Inspired by https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/ +name: Publish + +on: + workflow_dispatch: + release: + types: [ released ] + +jobs: + publish: + name: Publish to Maven Central + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: develop + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: 11 + + # Builds the release artifacts of the library + - name: Release build + run: ./gradlew assembleRelease + + # Generates other artifacts (javadocJar is optional) + - name: Source jar and dokka + run: ./gradlew androidSourcesJar javadocJar + + # Runs upload, and then closes & releases the repository + - name: Publish to Maven Central + run: ./gradlew publishReleasePublicationToSonatypeRepository --max-workers 1 closeAndReleaseSonatypeStagingRepository + env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} + SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} + diff --git a/README.md b/README.md index 0dc05b954b..6a8195a0a3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ A [Test App](test-app) demonstrates how to integrate the Readium Kotlin toolkit ## Setting Up Readium -Readium modules are distributed through [JitPack](https://jitpack.io/#readium/kotlin-toolkit). Make sure that you have the `$readium_version` property set in your root `build.gradle`, then add the JitPack and JCenter repositories. +Readium modules are distributed with [Maven Central](https://search.maven.org/search?q=g:org.readium.kotlin-toolkit). Make sure that you have the `$readium_version` property set in your root `build.gradle`, then add the Maven Central and JCenter repositories. ```groovy buildscript { @@ -35,7 +35,7 @@ buildscript { allprojects { repositories { jcenter() - maven { url 'https://jitpack.io' } + mavenCentral() } } ``` @@ -44,11 +44,11 @@ Then, add the dependencies to the Readium modules you need in your app's `build. ```groovy dependencies { - implementation "com.github.readium.kotlin-toolkit:readium-shared:$readium_version" - implementation "com.github.readium.kotlin-toolkit:readium-streamer:$readium_version" - implementation "com.github.readium.kotlin-toolkit:readium-navigator:$readium_version" - implementation "com.github.readium.kotlin-toolkit:readium-opds:$readium_version" - implementation "com.github.readium.kotlin-toolkit:readium-lcp:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-shared:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-streamer:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-navigator:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-opds:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-lcp:$readium_version" } ``` diff --git a/build.gradle.kts b/build.gradle.kts index a0f3f2d580..f9774a5d8a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,25 +9,20 @@ import org.jetbrains.dokka.gradle.DokkaTaskPartial plugins { id("com.android.application") apply false id("com.android.library") apply false - id("org.jetbrains.kotlin.android") apply false + id("io.github.gradle-nexus.publish-plugin") apply true id("org.jetbrains.dokka") apply true + id("org.jetbrains.kotlin.android") apply false id("org.jlleitschuh.gradle.ktlint") apply true } -allprojects { - group = "com.github.readium.kotlin-toolkit" +apply(from = "$rootDir/scripts/publish-root.gradle") + +ext { + set("publish.groupId", "org.readium.kotlin-toolkit") + set("publish.version", "2.3.0") } subprojects { - tasks.register("javadocsJar") { - archiveClassifier.set("javadoc") - } - - tasks.register("sourcesJar") { - archiveClassifier.set("sources") - from("src/main/java", "src/main/resources") - } - apply(plugin = "org.jlleitschuh.gradle.ktlint") ktlint { diff --git a/docs/migration-guide.md b/docs/migration-guide.md index 6cc46e5e92..c8992f56be 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -2,6 +2,33 @@ All migration steps necessary in reading apps to upgrade to major versions of the Kotlin Readium toolkit will be documented in this file. +## Unreleased + +### Maven Central + +Readium is now distributed with [Maven Central](https://search.maven.org/search?q=g:org.readium.kotlin-toolkit). You must update your Gradle configuration. + +```diff +allprojects { + repositories { +- maven { url 'https://jitpack.io' } ++ mavenCentral() + } +} +``` + +The group ID of the Readium modules is now `org.readium.kotlin-toolkit`, for instance: + +```groovy +dependencies { + implementation "org.readium.kotlin-toolkit:readium-shared:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-streamer:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-navigator:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-opds:$readium_version" + implementation "org.readium.kotlin-toolkit:readium-lcp:$readium_version" +} +``` + ## 2.3.0 ### `Decoration.extras` diff --git a/readium/adapters/pdfium/build.gradle.kts b/readium/adapters/pdfium/build.gradle.kts index b405f1df97..8021c8dee7 100644 --- a/readium/adapters/pdfium/build.gradle.kts +++ b/readium/adapters/pdfium/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -42,20 +40,8 @@ android { namespace = "org.readium.adapters.pdfium" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pdfium" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:adapters:pdfium:readium-adapter-pdfium-document")) diff --git a/readium/adapters/pdfium/pdfium-document/build.gradle.kts b/readium/adapters/pdfium/pdfium-document/build.gradle.kts index 685d80fde5..6113dec3c1 100644 --- a/readium/adapters/pdfium/pdfium-document/build.gradle.kts +++ b/readium/adapters/pdfium/pdfium-document/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -45,20 +43,8 @@ android { namespace = "org.readium.adapters.pdfium.document" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pdfium-document" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium-document" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts b/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts index 5a3cb4c6a6..31ce3a0f4d 100644 --- a/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts +++ b/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts @@ -9,8 +9,6 @@ plugins { kotlin("android") kotlin("plugin.parcelize") kotlin("plugin.serialization") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -46,20 +44,8 @@ android { namespace = "org.readium.adapters.pdfium.navigator" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pdfium-navigator" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium-navigator" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/adapters/pspdfkit/build.gradle.kts b/readium/adapters/pspdfkit/build.gradle.kts index 698cb753d3..e09623883c 100644 --- a/readium/adapters/pspdfkit/build.gradle.kts +++ b/readium/adapters/pspdfkit/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -42,20 +40,8 @@ android { namespace = "org.readium.adapters.pspdfkit" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pspdfkit" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:adapters:pspdfkit:readium-adapter-pspdfkit-document")) diff --git a/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts b/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts index c068027672..a8ab144c29 100644 --- a/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts +++ b/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -45,20 +43,8 @@ android { namespace = "org.readium.adapters.pspdfkit.document" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pspdfkit-document" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit-document" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts b/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts index 249dd778e7..0b9a53a6e3 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts @@ -9,8 +9,6 @@ plugins { kotlin("android") kotlin("plugin.parcelize") kotlin("plugin.serialization") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -46,20 +44,8 @@ android { namespace = "org.readium.adapters.pspdfkit.navigator" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-adapter-pspdfkit-navigator" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit-navigator" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/lcp/build.gradle.kts b/readium/lcp/build.gradle.kts index b1e28dc28d..2d4fd94f66 100644 --- a/readium/lcp/build.gradle.kts +++ b/readium/lcp/build.gradle.kts @@ -9,8 +9,6 @@ plugins { kotlin("android") kotlin("plugin.parcelize") kotlin("kapt") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -42,20 +40,8 @@ android { namespace = "org.readium.r2.lcp" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-lcp" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-lcp" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { implementation(libs.kotlinx.coroutines.core) diff --git a/readium/navigator-media2/build.gradle.kts b/readium/navigator-media2/build.gradle.kts index ba61bbf29a..2512435bf7 100644 --- a/readium/navigator-media2/build.gradle.kts +++ b/readium/navigator-media2/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -45,21 +43,8 @@ android { namespace = "org.readium.navigator.media2" } -publishing { - publications { - create("release") { - - groupId = "com.github.readium" - artifactId = "readium-navigator-media2" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-navigator-media2" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/navigator/build.gradle.kts b/readium/navigator/build.gradle.kts index d21d98abfb..c4f7562363 100644 --- a/readium/navigator/build.gradle.kts +++ b/readium/navigator/build.gradle.kts @@ -9,8 +9,6 @@ plugins { kotlin("android") kotlin("plugin.parcelize") kotlin("plugin.serialization") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -50,20 +48,8 @@ android { namespace = "org.readium.r2.navigator" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-navigator" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-navigator" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/opds/build.gradle.kts b/readium/opds/build.gradle.kts index aec5f5ca9b..749f173f10 100644 --- a/readium/opds/build.gradle.kts +++ b/readium/opds/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -42,20 +40,8 @@ android { namespace = "org.readium.r2.opds" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-opds" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-opds" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/readium/shared/build.gradle.kts b/readium/shared/build.gradle.kts index c5807887cf..219216d124 100644 --- a/readium/shared/build.gradle.kts +++ b/readium/shared/build.gradle.kts @@ -9,8 +9,6 @@ plugins { kotlin("android") kotlin("plugin.parcelize") kotlin("plugin.serialization") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -43,20 +41,8 @@ android { namespace = "org.readium.r2.shared" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-shared" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-shared" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { implementation(libs.androidx.appcompat) diff --git a/readium/streamer/build.gradle.kts b/readium/streamer/build.gradle.kts index 25295b8806..0d30a46089 100644 --- a/readium/streamer/build.gradle.kts +++ b/readium/streamer/build.gradle.kts @@ -8,8 +8,6 @@ plugins { id("com.android.library") kotlin("android") kotlin("plugin.parcelize") - id("maven-publish") - id("org.jetbrains.dokka") } android { @@ -42,20 +40,8 @@ android { namespace = "org.readium.r2.streamer" } -publishing { - publications { - create("release") { - groupId = "com.github.readium" - artifactId = "readium-streamer" - artifact(tasks.findByName("sourcesJar")) - artifact(tasks.findByName("javadocsJar")) - - afterEvaluate { - from(components.getByName("release")) - } - } - } -} +rootProject.ext["publish.artifactId"] = "readium-streamer" +apply(from = "$rootDir/scripts/publish-module.gradle") dependencies { api(project(":readium:readium-shared")) diff --git a/scripts/publish-module.gradle b/scripts/publish-module.gradle new file mode 100644 index 0000000000..7c044790fc --- /dev/null +++ b/scripts/publish-module.gradle @@ -0,0 +1,99 @@ +/* + * Copyright 2022 Readium Foundation. All rights reserved. + * Use of this source code is governed by the BSD-style license + * available in the top-level LICENSE file of the project. + */ + +apply plugin: 'maven-publish' +apply plugin: 'signing' +apply plugin: 'org.jetbrains.dokka' + +task androidSourcesJar(type: Jar) { + archiveClassifier.set('sources') + if (project.plugins.findPlugin("com.android.library")) { + // // For Android libraries + from android.sourceSets.main.java.srcDirs + from android.sourceSets.main.kotlin.srcDirs + } else { + // For pure Kotlin libraries + from sourceSets.main.java.srcDirs + from sourceSets.main.kotlin.srcDirs + } +} + +task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { + archiveClassifier.set('javadoc') + from dokkaJavadoc.outputDirectory +} + +artifacts { + archives androidSourcesJar + archives javadocJar +} + +group = rootProject.ext["publish.groupId"] +version = rootProject.ext["publish.version"] + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + groupId rootProject.ext["publish.groupId"] + artifactId rootProject.ext["publish.artifactId"] + version rootProject.ext["publish.version"] + + if (project.plugins.findPlugin("com.android.library")) { + from components.release + } else { + from components.java + } + + artifact androidSourcesJar + artifact javadocJar + + pom { + name = rootProject.ext["publish.artifactId"] + description = 'A toolkit for ebooks, audiobooks and comics written in Kotlin' + url = 'https://github.com/readium/kotlin-toolkit' + licenses { + license { + name = 'BSD-3-Clause license' + url = 'https://github.com/readium/kotlin-toolkit/blob/main/LICENSE' + } + } + developers { + developer { + id = 'aferditamuriqi' + name = 'Aferdita Muriqi' + email = 'aferdita.muriqi@gmail.com' + } + developer { + id = 'mickael-menu' + name = 'Mickaƫl Menu' + email = 'mickael.menu@gmail.com' + } + developer { + id = 'qnga' + name = 'Quentin Gliosca' + email = 'quentin.gliosca@gmail.com' + } + } + scm { + connection = 'scm:git:github.com/readium/kotlin-toolkit.git' + developerConnection = 'scm:git:ssh://github.com/readium/kotlin-toolkit.git' + url = 'https://github.com/readium/kotlin-toolkit' + } + } + } + } + } +} + +signing { + useInMemoryPgpKeys( + rootProject.ext["signing.keyId"], + rootProject.ext["signing.key"], + rootProject.ext["signing.password"], + ) + sign publishing.publications +} diff --git a/scripts/publish-root.gradle b/scripts/publish-root.gradle new file mode 100644 index 0000000000..37b028bd15 --- /dev/null +++ b/scripts/publish-root.gradle @@ -0,0 +1,45 @@ +/* + * Copyright 2022 Readium Foundation. All rights reserved. + * Use of this source code is governed by the BSD-style license + * available in the top-level LICENSE file of the project. + */ + +// Inspired by https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/ + +// Create variables with empty default values +ext["ossrhUsername"] = '' +ext["ossrhPassword"] = '' +ext["sonatypeStagingProfileId"] = '' +ext["signing.keyId"] = '' +ext["signing.password"] = '' +ext["signing.key"] = '' + +File secretPropsFile = project.rootProject.file('local.properties') +if (secretPropsFile.exists()) { + // Read local.properties file first if it exists + Properties p = new Properties() + new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } + p.each { name, value -> ext[name] = value } +} else { + // Use system environment variables + ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') + ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') + ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') + ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') + ext["signing.password"] = System.getenv('SIGNING_PASSWORD') + ext["signing.key"] = System.getenv('SIGNING_KEY') +} + +// Set up Sonatype repository +nexusPublishing { + repositories { + sonatype { + stagingProfileId = sonatypeStagingProfileId + username = ossrhUsername + password = ossrhPassword + + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 6996958592..c1b9f5d53a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,8 +20,9 @@ pluginManagement { plugins { id("com.android.application") version ("7.3.1") id("com.android.library") version ("7.3.1") - id("org.jetbrains.kotlin.android") version ("1.7.20") + id("io.github.gradle-nexus.publish-plugin") version ("1.1.0") id("org.jetbrains.dokka") version ("1.7.20") + id("org.jetbrains.kotlin.android") version ("1.7.20") id("org.jetbrains.kotlin.plugin.serialization") version ("1.7.10") id("org.jlleitschuh.gradle.ktlint") version ("11.0.0") }