Skip to content

Commit

Permalink
fix: fix bugged source jar management in kotlin-js projects (#619)
Browse files Browse the repository at this point in the history
* fix: sources jar management in kotlin-js projects

* style: stile improvements

* fix: ensure hacks are confined to Kotlin/JS projects

---------

Co-authored-by: Giovanni Ciatto <[email protected]>
  • Loading branch information
DanySK and gciatto authored Apr 23, 2023
1 parent e640fb0 commit db3278c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package org.danilopianini.gradle.mavencentral

import io.github.gradlenexus.publishplugin.internal.StagingRepository.State.CLOSED
import org.danilopianini.gradle.mavencentral.MavenPublicationExtensions.signingTasks
import org.gradle.api.Action
import org.gradle.api.DefaultTask
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.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
import org.gradle.api.publish.plugins.PublishingPlugin
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.property
Expand All @@ -23,13 +26,51 @@ import kotlin.reflect.KClass

internal object ProjectExtensions {

/**
* The id of the Kotlin/JS plugin.
*/
private const val KOTLIN_JS_PLUGIN = "org.jetbrains.kotlin.js"

/**
* The `jsSourcesJar` [Task] of a Kotlin/JS project.
*/
internal val Project.jsSourcesJar: Jar? get() = tasks.withType<Jar>().findByName("jsSourcesJar")

/**
* The `kotlinSourcesJar` [Task] of a Kotlin/JS or Kotlin/JVM project.
*/
private val Project.kotlinSourcesJar: Jar? get() = tasks.withType<Jar>().findByName("kotlinSourcesJar")

/**
* The list of default sources Jar [Task]s: it may include [kotlinSourcesJar] and [jsSourcesJar],
* if they are non-null.
*/
internal val Project.sourcesJarTasks: List<Jar> get() = listOfNotNull(jsSourcesJar, kotlinSourcesJar)

/**
* Executes an action on Kotlin/JS projects only.
*/
internal fun Project.ifKotlinJsProject(action: Action<Plugin<*>>) {
plugins.withId(KOTLIN_JS_PLUGIN, action)
}

/**
* Configures the provided task to include the `main` source set of a Kotlin/JS project.
* The configuration does nothing if the provided task not of type [SourceJar].
*/
fun Project.configureJavadocJarTaskForKtJs(sourcesJarTask: Task) {
plugins.withId("org.jetbrains.kotlin.js") { _ ->
ifKotlinJsProject { _ ->
configure<KotlinJsProjectExtension> {
js {
sourceSets.getByName("main") {
(sourcesJarTask as SourceJar).sourceSet(it.kotlin)
sourcesJarTask.sourceSet(it.resources)
(sourcesJarTask as? SourceJar)?.run {
sourceSet(it.kotlin)
sourceSet(it.resources)
} ?: logger.warn(
"source sets of task {} not configured because it is not of type {}",
sourcesJarTask.name,
SourceJar::class.java.name,
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import org.danilopianini.gradle.mavencentral.MavenPublicationExtensions.configur
import org.danilopianini.gradle.mavencentral.MavenPublicationExtensions.signingTasks
import org.danilopianini.gradle.mavencentral.ProjectExtensions.configureJavadocJarTaskForKtJs
import org.danilopianini.gradle.mavencentral.ProjectExtensions.configureRepository
import org.danilopianini.gradle.mavencentral.ProjectExtensions.ifKotlinJsProject
import org.danilopianini.gradle.mavencentral.ProjectExtensions.jsSourcesJar
import org.danilopianini.gradle.mavencentral.ProjectExtensions.registerTaskIfNeeded
import org.danilopianini.gradle.mavencentral.ProjectExtensions.sourcesJarTasks
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
Expand All @@ -29,6 +33,48 @@ class PublishOnCentral : Plugin<Project> {
private const val publicationName = "OSSRH"
}

private fun addSourcesArtifactIfNeeded(project: Project, publication: MavenPublication, sourcesJarTask: Task) {
if (sourcesJarTask is SourceJar) {
if (project.jsSourcesJar == null) {
publication.artifact(sourcesJarTask)
project.logger.info(
"add sources jar artifact to publication {} from task {}",
publication.name,
sourcesJarTask.name,
)
} else {
/*
* This is a hack for Kotlin/JS projects.
* These projects already contain tasks named "jsSourcesJar" and "kotlinSourcesJar", generating the
* same jar "<project.name>-js-<project.version>-sources.jar".
* In particular, task kotlinSourcesJar is automatically registered as an artifact to Maven publications
* when they are created. So, adding further sources-jar-generating tasks it troublesome in this
* situation. The following code simply removes the "-js" appendix from the jar file name,
* hence making the jar compliant with Maven Central.
*/
project.ifKotlinJsProject { _ ->
project.sourcesJarTasks.forEach {
it.archiveAppendix.set("")
// Better to tell the user the plugin is changing the behaviour of default tasks
project.logger.lifecycle(
"remove '-js' appendix from sources jar generated by task {}",
it.name,
)
}
}
}
}
}

private fun addJavadocArtifactIfNeeded(project: Project, publication: MavenPublication, javadocJarTask: Task) {
if (javadocJarTask is JavadocJar) {
publication.artifact(javadocJarTask)
project.logger.info(
"add javadoc jar artifact to publication ${publication.name} from task ${javadocJarTask.name}",
)
}
}

override fun apply(project: Project) {
project.plugins.apply(MavenPublishPlugin::class.java)
project.plugins.apply(SigningPlugin::class.java)
Expand All @@ -48,13 +94,8 @@ class PublishOnCentral : Plugin<Project> {
publications.create(name, MavenPublication::class.java) { publication ->
createdPublications += publication
publication.from(component)
// Add artifacts selectively, only if this plugin created the publication
if (sourcesJarTask is SourceJar) {
publication.artifact(sourcesJarTask)
}
if (javadocJarTask is JavadocJar) {
publication.artifact(javadocJarTask)
}
addSourcesArtifactIfNeeded(project, publication, sourcesJarTask)
addJavadocArtifactIfNeeded(project, publication, javadocJarTask)
publication.configurePomForMavenCentral(extension)
publication.pom.packaging = "jar"
project.configure<SigningExtension> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@file:Suppress("UnstableApiUsage")

import org.danilopianini.gradle.mavencentral.DocStyle
import org.gradle.kotlin.dsl.repositories

@Suppress("DSL_SCOPE_VIOLATION")
plugins {
Expand All @@ -11,6 +12,10 @@ plugins {
group = "org.danilopianini"
version = "1.0.0"

repositories {
mavenCentral()
}

kotlin {
js {
browser()
Expand Down
29 changes: 25 additions & 4 deletions src/test/resources/org/danilopianini/gradle/test/ktjs/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,36 @@ tests:
- '--stacktrace'
expectation:
success: *tasks1
file_exists:
file_exists: &exists
- name: /build/libs/ktjs-1.0.0-sources.jar
- description: "Task :jsSourcesJar should generate sources Jar with -js specifier for Kotlin Js projects"
- description: "Task :jsSourcesJar should generate sources Jar with for Kotlin Js projects"
configuration:
tasks: &tasks2
- 'jsSourcesJar'
options:
- '--stacktrace'
expectation:
success: *tasks2
file_exists:
- name: /build/libs/ktjs-js-1.0.0-sources.jar
file_exists: *exists
- description: "Task :kotlinSourcesJar should generate sources Jar with for Kotlin Js projects"
configuration:
tasks: &tasks3
- 'kotlinSourcesJar'
options:
- '--stacktrace'
expectation:
success: *tasks3
file_exists: *exists
- description: "Publishing should only use :jsSourcesJar to create sources Jars"
configuration:
tasks:
- 'publishToMavenLocal'
options:
- '--dry-run'
- '--stacktrace'
expectation:
output_contains:
- ":kotlinSourcesJar SKIPPED"
output_doesnt_contain:
- ":sourcesJar"
- ":jsSourcesJar"

0 comments on commit db3278c

Please sign in to comment.