Skip to content

Commit 3de98ff

Browse files
authored
Fixed HOCON publication (#2723)
Fixes #2717
1 parent 0013192 commit 3de98ff

File tree

5 files changed

+310
-23
lines changed

5 files changed

+310
-23
lines changed

build.gradle.kts

+14-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ plugins {
1111
id("org.jetbrains.kotlinx.binary-compatibility-validator")
1212
id("org.jetbrains.dokka")
1313
id("benchmark-conventions")
14+
id("publishing-check-conventions")
1415

1516
alias(libs.plugins.serialization) apply false
1617
}
@@ -111,23 +112,33 @@ subprojects {
111112
apply(plugin = "publishing-conventions")
112113
}
113114

115+
// == publishing setup ==
116+
117+
val mergeProject = project
118+
119+
subprojects {
120+
if (name in unpublishedProjects) return@subprojects
121+
apply(plugin = "publishing-conventions")
122+
mergeProject.dependencies.add(Publishing_check_conventions_gradle.TestPublishing.configurationName, this)
123+
}
124+
114125
// == animalsniffer setup ==
115126
subprojects {
116127
// Can't be applied to BOM
117-
if (excludedFromBomProjects.contains(project.name)) return@subprojects
128+
if (project.name in excludedFromBomProjects) return@subprojects
118129
apply(plugin = "animalsniffer-conventions")
119130
}
120131

121132
// == BOM setup ==
122133
subprojects {
123134
// Can't be applied to BOM
124-
if (excludedFromBomProjects.contains(project.name)) return@subprojects
135+
if (project.name in excludedFromBomProjects) return@subprojects
125136
apply(plugin = "bom-conventions")
126137
}
127138

128139
// == Kover setup ==
129140
subprojects {
130-
if (uncoveredProjects.contains(project.name)) return@subprojects
141+
if (project.name in uncoveredProjects) return@subprojects
131142
apply(plugin = "kover-conventions")
132143
}
133144

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
object TestPublishing {
2+
const val configurationName = "testRepository"
3+
}
4+
5+
val testRepositoryDependency = configurations.create(TestPublishing.configurationName) {
6+
isVisible = true
7+
isCanBeResolved = false
8+
isCanBeConsumed = false
9+
}
10+
11+
12+
val testRepositories = configurations.create("testRepositories") {
13+
isVisible = false
14+
isCanBeResolved = true
15+
// this config consumes modules from OTHER projects, and cannot be consumed by other projects
16+
isCanBeConsumed = false
17+
18+
attributes {
19+
attribute(Attribute.of("kotlinx.serialization.repository", String::class.java), "test")
20+
}
21+
extendsFrom(testRepositoryDependency)
22+
}
23+
24+
tasks.register<ArtifactsCheckTask>("checkArtifacts") {
25+
repositories.from(testRepositories)
26+
}
27+
28+
abstract class ArtifactsCheckTask: DefaultTask() {
29+
30+
@get:InputFiles
31+
@get:PathSensitive(PathSensitivity.RELATIVE)
32+
abstract val repositories: ConfigurableFileCollection
33+
34+
@TaskAction
35+
fun check() {
36+
val artifactsFile = project.rootDir.resolve("gradle/artifacts.txt")
37+
38+
val actualArtifacts = repositories.files.flatMap { file ->
39+
file.resolve("org/jetbrains/kotlinx").list()?.toSet() ?: emptySet()
40+
}.toSortedSet()
41+
42+
if (project.hasProperty("dumpArtifacts")) {
43+
artifactsFile.bufferedWriter().use { writer ->
44+
actualArtifacts.forEach { artifact -> writer.appendLine(artifact) }
45+
}
46+
return
47+
}
48+
49+
val expectedArtifacts = artifactsFile.readLines().toSet()
50+
51+
if (expectedArtifacts == actualArtifacts) {
52+
logger.lifecycle("All artifacts are published")
53+
} else {
54+
val missedArtifacts = expectedArtifacts - actualArtifacts
55+
val unknownArtifacts = actualArtifacts - expectedArtifacts
56+
val message = "The published artifacts differ from the expected ones." +
57+
(if (missedArtifacts.isNotEmpty()) missedArtifacts.joinToString(prefix = "\n\tMissing artifacts: ") else "") +
58+
(if (unknownArtifacts.isNotEmpty()) unknownArtifacts.joinToString(prefix = "\n\tUnknown artifacts: ") else "") +
59+
"\nTo save current list of artifacts as expecting, call 'checkArtifacts -PdumpArtifacts'"
60+
61+
logger.error(message)
62+
throw GradleException("The published artifacts differ from the expected ones")
63+
}
64+
}
65+
}

buildSrc/src/main/kotlin/publishing-conventions.gradle.kts

+53-20
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ afterEvaluate {
5151

5252
publishing {
5353
if (!isMultiplatform && !isBom) {
54-
publications.withType<MavenPublication>().all {
54+
publications.register<MavenPublication>("maven") {
5555
artifactId = project.name
5656
from(components["java"])
5757
artifact(mainSourcesJar)
5858
artifact(tasks.named("stubJavadoc"))
5959
}
6060
} else {
6161
// Rename artifacts for backward compatibility
62-
publications.withType(MavenPublication::class).all {
62+
publications.withType<MavenPublication>().configureEach {
6363
val type = name
6464
logger.info("Configuring $type")
6565
when (type) {
@@ -81,16 +81,49 @@ afterEvaluate {
8181
}
8282
}
8383

84-
publications.withType(MavenPublication::class).all {
85-
pom.configureMavenCentralMetadata(project)
86-
signPublicationIfKeyPresent(project, this)
84+
publications.withType<MavenPublication>().configureEach {
85+
pom.configureMavenCentralMetadata()
86+
signPublicationIfKeyPresent()
8787
}
8888
}
8989
}
9090

91+
val testRepositoryDir = project.layout.buildDirectory.dir("testRepository")
92+
9193
publishing {
9294
repositories {
93-
configureMavenPublication(this, project)
95+
addSonatypeRepository()
96+
97+
/**
98+
* Maven repository in build directory to check published artifacts.
99+
*/
100+
maven {
101+
setUrl(testRepositoryDir)
102+
name = "test"
103+
}
104+
}
105+
}
106+
107+
interface LocalArtifactAttr : Named {
108+
companion object {
109+
val ATTRIBUTE = Attribute.of(
110+
"kotlinx.kover.gradle-plugin",
111+
LocalArtifactAttr::class.java
112+
)
113+
}
114+
}
115+
116+
val testPublicationTask: TaskCollection<*> = tasks.named { name -> name == "publishAllPublicationsToTestRepository" }
117+
configurations.register("testPublication") {
118+
isVisible = false
119+
isCanBeResolved = false
120+
// this configuration produces modules that can be consumed by other projects
121+
isCanBeConsumed = true
122+
attributes {
123+
attribute(Attribute.of("kotlinx.serialization.repository", String::class.java), "test")
124+
}
125+
outgoing.artifact(testRepositoryDir) {
126+
builtBy(testPublicationTask)
94127
}
95128
}
96129

@@ -119,7 +152,7 @@ tasks.register("bintrayUpload") {
119152
dependsOn(tasks.publishToMavenLocal)
120153
}
121154

122-
fun MavenPom.configureMavenCentralMetadata(project: Project) {
155+
fun MavenPom.configureMavenCentralMetadata() {
123156
name = project.name
124157
description = "Kotlin multiplatform serialization runtime library"
125158
url = "https://github.com/Kotlin/kotlinx.serialization"
@@ -158,7 +191,7 @@ fun MavenPom.configureMavenCentralMetadata(project: Project) {
158191
*/
159192
public fun Project.reconfigureMultiplatformPublication(jvmPublication: MavenPublication) {
160193
val mavenPublications =
161-
extensions.getByType(PublishingExtension::class.java).publications.withType<MavenPublication>()
194+
extensions.getByType<PublishingExtension>().publications.withType<MavenPublication>()
162195
val kmpPublication = mavenPublications.getByName("kotlinMultiplatform")
163196

164197
var jvmPublicationXml: XmlProvider? = null
@@ -194,24 +227,24 @@ public fun Project.reconfigureMultiplatformPublication(jvmPublication: MavenPubl
194227
}
195228
}
196229

197-
fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication) {
198-
val keyId = project.getSensitiveProperty("libs.sign.key.id")
199-
val signingKey = project.getSensitiveProperty("libs.sign.key.private")
200-
val signingKeyPassphrase = project.getSensitiveProperty("libs.sign.passphrase")
230+
fun MavenPublication.signPublicationIfKeyPresent() {
231+
val keyId = getSensitiveProperty("libs.sign.key.id")
232+
val signingKey = getSensitiveProperty("libs.sign.key.private")
233+
val signingKeyPassphrase = getSensitiveProperty("libs.sign.passphrase")
201234
if (!signingKey.isNullOrBlank()) {
202-
project.extensions.configure<SigningExtension>("signing") {
235+
extensions.configure<SigningExtension>("signing") {
203236
useInMemoryPgpKeys(keyId, signingKey, signingKeyPassphrase)
204-
sign(publication)
237+
sign(this@signPublicationIfKeyPresent)
205238
}
206239
}
207240
}
208241

209-
fun configureMavenPublication(rh: RepositoryHandler, project: Project) {
210-
rh.maven {
242+
fun RepositoryHandler.addSonatypeRepository() {
243+
maven {
211244
url = mavenRepositoryUri()
212245
credentials {
213-
username = project.getSensitiveProperty("libs.sonatype.user")
214-
password = project.getSensitiveProperty("libs.sonatype.password")
246+
username = getSensitiveProperty("libs.sonatype.user")
247+
password = getSensitiveProperty("libs.sonatype.password")
215248
}
216249
}
217250
}
@@ -226,6 +259,6 @@ fun mavenRepositoryUri(): URI {
226259
}
227260
}
228261

229-
fun Project.getSensitiveProperty(name: String): String? {
230-
return project.findProperty(name) as? String ?: System.getenv(name)
262+
fun getSensitiveProperty(name: String): String? {
263+
return findProperty(name) as? String ?: System.getenv(name)
231264
}

0 commit comments

Comments
 (0)