diff --git a/.agents/documentation-guidelines.md b/.agents/documentation-guidelines.md
index 914dcc8..6c9c1ba 100644
--- a/.agents/documentation-guidelines.md
+++ b/.agents/documentation-guidelines.md
@@ -9,6 +9,6 @@
## Avoid widows, runts, orphans, or rivers
Agents should **AVOID** text flow patters illustrated
-on [this diagram](widow-runt-orphan-river.jpg).
+on [this diagram](widow-runt-orphan.jpg).
[todo-comments]: https://github.com/SpineEventEngine/documentation/wiki/TODO-comments
diff --git a/.agents/skills/writer/SKILL.md b/.agents/skills/writer/SKILL.md
new file mode 100644
index 0000000..5c72026
--- /dev/null
+++ b/.agents/skills/writer/SKILL.md
@@ -0,0 +1,51 @@
+---
+name: writer
+description: >
+ Write, edit, and restructure user-facing and developer-facing documentation.
+ Use when asked to create/update docs such as `README.md`, `docs/**`, and
+ other Markdown documentation;
+ when drafting tutorials, guides, troubleshooting pages, or migration notes; and
+ when improving inline API documentation (KDoc) and examples.
+---
+
+# Write documentation (repo-specific)
+
+## Decide the target and audience
+
+- Identify the target reader: end user, contributor, maintainer, or tooling/automation.
+- Identify the task type: new doc, update, restructure, or documentation audit.
+- Identify the acceptance criteria: “what is correct when the reader is done?”
+
+## Choose where the content should live
+
+- Prefer updating an existing doc over creating a new one.
+- Place content in the most discoverable location:
+ - `README.md`: project entry point and “what is this?”.
+ - `docs/`: longer-form docs (follow existing conventions in that tree).
+ - Source KDoc: API usage, examples, and semantics that belong with the code.
+
+## Follow local documentation conventions
+
+- Follow `.agents/documentation-guidelines.md` and `.agents/documentation-tasks.md`.
+- Use fenced code blocks for commands and examples; format file/dir names as code.
+- Avoid widows, runts, orphans, and rivers by reflowing paragraphs when needed.
+
+## Make docs actionable
+
+- Prefer steps the reader can execute (commands + expected outcome).
+- Prefer concrete examples over abstract descriptions.
+- Include prerequisites (versions, OS, environment) when they are easy to miss.
+- Use consistent terminology (match code identifiers and existing docs).
+
+## KDoc-specific guidance
+
+- For public/internal APIs, include at least one example snippet demonstrating common usage.
+- When converting from Javadoc/inline comments to KDoc:
+ - Remove HTML like `
` and preserve meaning.
+ - Prefer short paragraphs and blank lines over HTML formatting.
+
+## Validate changes
+
+- For code changes, follow `.agents/running-builds.md`.
+- For documentation-only changes in Kotlin/Java sources, prefer `./gradlew dokka`.
+
diff --git a/.agents/skills/writer/agents/openai.yaml b/.agents/skills/writer/agents/openai.yaml
new file mode 100644
index 0000000..44eaa4e
--- /dev/null
+++ b/.agents/skills/writer/agents/openai.yaml
@@ -0,0 +1,5 @@
+interface:
+ display_name: "Writer"
+ short_description: "Write and update user/developer docs"
+ default_prompt: "Write or revise documentation in this repository (for example: README.md, docs/**, CONTRIBUTING.md, and API documentation/KDoc). Follow local documentation guidelines in .agents/*.md, keep changes concise and actionable, and include concrete examples and commands where appropriate."
+
diff --git a/.agents/skills/writer/assets/templates/doc-page.md b/.agents/skills/writer/assets/templates/doc-page.md
new file mode 100644
index 0000000..f405b71
--- /dev/null
+++ b/.agents/skills/writer/assets/templates/doc-page.md
@@ -0,0 +1,23 @@
+# Title
+
+## Goal
+
+State what the reader will accomplish.
+
+## Prerequisites
+
+- List versions/tools the reader needs.
+
+## Steps
+
+1. Do the first thing.
+2. Do the next thing.
+
+## Verify
+
+Show how the reader can confirm success.
+
+## Troubleshooting
+
+- Common failure: likely cause → fix.
+
diff --git a/.agents/skills/writer/assets/templates/kdoc-example.md b/.agents/skills/writer/assets/templates/kdoc-example.md
new file mode 100644
index 0000000..fdbd9b6
--- /dev/null
+++ b/.agents/skills/writer/assets/templates/kdoc-example.md
@@ -0,0 +1,11 @@
+````kotlin
+/**
+ * Explain what this API does in one sentence.
+ *
+ * ## Example
+ * ```kotlin
+ * // Show the typical usage pattern.
+ * val result = doThing()
+ * ```
+ */
+````
diff --git a/.agents/skills/writer/assets/templates/kotlin-java-example.md b/.agents/skills/writer/assets/templates/kotlin-java-example.md
new file mode 100644
index 0000000..5517516
--- /dev/null
+++ b/.agents/skills/writer/assets/templates/kotlin-java-example.md
@@ -0,0 +1,13 @@
+{{< code-tabs langs="Kotlin, Java">}}
+
+{{< code-tab lang="Kotlin" >}}
+```kotlin
+```
+{{< /code-tab >}}
+
+{{< code-tab lang="Java" >}}
+```java
+```
+{{< /code-tab >}}
+
+{{< /code-tabs >}}
diff --git a/.agents/widow-runt-orphan.jpg b/.agents/widow-runt-orphan.jpg
new file mode 100644
index 0000000..284b02a
Binary files /dev/null and b/.agents/widow-runt-orphan.jpg differ
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 8b5b4d5..7de0c51 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -58,6 +58,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FORMAL_GIT_HUB_PAGES_AUTHOR: developers@spine.io
# https://docs.github.com/en/actions/reference/environment-variables
- REPO_SLUG: $GITHUB_REPOSITORY # e.g. SpineEventEngine/core-java
+ REPO_SLUG: ${{ github.repository }} # e.g. SpineEventEngine/core-jvm
GOOGLE_APPLICATION_CREDENTIALS: ./maven-publisher.json
NPM_TOKEN: ${{ secrets.NPM_SECRET }}
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 0bd1d9d..7be402d 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -255,6 +255,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 0dbadfe..f516735 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -3,11 +3,8 @@
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 31f80ae..5358548 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
@@ -41,4 +40,4 @@
-
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 9174287..36520ad 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -40,13 +40,25 @@ import io.spine.gradle.repo.standardToSpineSdk
import io.spine.gradle.report.license.LicenseReporter
import io.spine.gradle.report.pom.PomGenerator
+buildscript {
+ standardSpineSdkRepositories()
+ doForceVersions(configurations)
+ dependencies {
+ classpath(io.spine.dependency.local.ToolBase.protobufSetupPlugins)
+ }
+}
+
plugins {
id("module")
- `compile-protobuf`
+ id("com.google.protobuf")
id("module-testing")
`gradle-doctor`
`project-report`
+ `dokka-setup`
}
+apply(plugin = "io.spine.descriptor-set-file")
+apply(plugin = "io.spine.generated-sources")
+
apply()
apply(from = "$rootDir/version.gradle.kts")
@@ -95,14 +107,23 @@ dependencies {
}
spinePublishing {
+ // We have to have a prefix for this library because it is going to be exposed
+ // as API dependency from modules that are also, conventionally, called `testlib`.
+ // Since Gradle attempts to resolve a dependency using Maven coordinates at
+ // the build time, it will fail to resolve the `test-fixtures` capability if there are
+ // two artifacts with the "same" coordinates, that is, `io.spine.tools:testlib:$version`.
+ toolArtifactPrefix = "base-"
destinations = with(PublishingRepos) {
setOf(
cloudArtifactRegistry,
gitHub("testlib")
)
}
- dokkaJar {
- java = true
+}
+
+protobuf {
+ protoc {
+ artifact = Protobuf.compiler
}
}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 4048039..1a3fc8a 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -38,7 +38,7 @@ plugins {
`kotlin-dsl`
// https://github.com/jk1/Gradle-License-Report/releases
- id("com.github.jk1.dependency-license-report").version("2.7")
+ id("com.github.jk1.dependency-license-report").version("2.9")
}
repositories {
@@ -75,7 +75,7 @@ val grGitVersion = "4.1.1"
* This version may change from the [version of Kotlin][io.spine.dependency.lib.Kotlin.version]
* used by the project.
*/
-val kotlinEmbeddedVersion = "2.2.20"
+val kotlinEmbeddedVersion = "2.3.20"
/**
* The version of Guava used in `buildSrc`.
@@ -83,7 +83,7 @@ val kotlinEmbeddedVersion = "2.2.20"
* Always use the same version as the one specified in [io.spine.dependency.lib.Guava].
* Otherwise, when testing Gradle plugins, clashes may occur.
*/
-val guavaVersion = "33.4.8-jre"
+val guavaVersion = "33.5.0-jre"
/**
* The version of ErrorProne Gradle plugin.
@@ -103,7 +103,7 @@ val errorPronePluginVersion = "4.2.0"
* @see
* Protobuf Gradle Plugins Releases
*/
-val protobufPluginVersion = "0.9.5"
+val protobufPluginVersion = "0.9.6"
/**
* The version of Dokka Gradle Plugins.
@@ -113,7 +113,7 @@ val protobufPluginVersion = "0.9.5"
* @see
* Dokka Releases
*/
-val dokkaVersion = "2.0.0"
+val dokkaVersion = "2.1.0"
/**
* The version of Detekt Gradle Plugin.
@@ -127,11 +127,6 @@ val detektVersion = "1.23.8"
*/
val kotestJvmPluginVersion = "0.4.10"
-/**
- * @see [io.spine.dependency.test.Kotest.MultiplatformGradlePlugin]
- */
-val kotestMultiplatformPluginVersion = "5.9.1"
-
/**
* @see [io.spine.dependency.test.Kover]
*/
@@ -144,7 +139,21 @@ val koverVersion = "0.9.1"
*
* @see Shadow Plugin releases
*/
-val shadowVersion = "8.3.6"
+val shadowVersion = "9.2.2"
+
+/**
+ * The version of JUnit used to test the build scripts.
+ *
+ * @see [io.spine.dependency.test.JUnit]
+ */
+val junitVersion = "6.0.3"
+
+/**
+ * The version of Kotest used to test the build scripts.
+ *
+ * @see [io.spine.dependency.test.Kotest]
+ */
+val kotestVersion = "6.1.10"
configurations.all {
resolutionStrategy {
@@ -185,7 +194,6 @@ dependencies {
"com.gradleup.shadow:shadow-gradle-plugin:$shadowVersion",
"io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$detektVersion",
"io.kotest:kotest-gradle-plugin:$kotestJvmPluginVersion",
- "io.kotest:kotest-framework-multiplatform-plugin-gradle:$kotestMultiplatformPluginVersion",
// https://github.com/srikanth-lingala/zip4j
"net.lingala.zip4j:zip4j:2.10.0",
"net.ltgt.gradle:gradle-errorprone-plugin:$errorPronePluginVersion",
@@ -198,6 +206,15 @@ dependencies {
).forEach {
implementation(it)
}
+
+ testImplementation(platform("org.junit:junit-bom:$junitVersion"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+ testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+}
+
+tasks.test {
+ useJUnitPlatform()
}
dependOnBuildSrcJar()
diff --git a/buildSrc/src/main/kotlin/BuildExtensions.kt b/buildSrc/src/main/kotlin/BuildExtensions.kt
index e92238c..f7a11e3 100644
--- a/buildSrc/src/main/kotlin/BuildExtensions.kt
+++ b/buildSrc/src/main/kotlin/BuildExtensions.kt
@@ -156,15 +156,15 @@ val PluginDependenciesSpec.`gradle-doctor`: PluginDependencySpec
get() = id(GradleDoctor.pluginId).version(GradleDoctor.version)
val PluginDependenciesSpec.kotest: PluginDependencySpec
- get() = Kotest.MultiplatformGradlePlugin.let {
- return id(it.id).version(it.version)
+ get() = Kotest.let {
+ return id(it.gradlePluginId).version(it.version)
}
val PluginDependenciesSpec.kover: PluginDependencySpec
get() = id(Kover.id).version(Kover.version)
val PluginDependenciesSpec.ksp: PluginDependencySpec
- get() = id(Ksp.id).version(Ksp.version)
+ get() = id(Ksp.id).version(Ksp.dogfoodingVersion)
val PluginDependenciesSpec.`plugin-publish`: PluginDependencySpec
get() = id(PluginPublishPlugin.id).version(PluginPublishPlugin.version)
@@ -199,43 +199,36 @@ fun Project.configureTaskDependencies() {
}
afterEvaluate {
- val launchProtoData = "launchProtoData"
- val launchTestProtoData = "launchTestProtoData"
val generateProto = "generateProto"
val createVersionFile = "createVersionFile"
val compileKotlin = "compileKotlin"
compileKotlin.run {
dependOn(generateProto)
- dependOn(launchProtoData)
}
val compileTestKotlin = "compileTestKotlin"
- compileTestKotlin.dependOn(launchTestProtoData)
val sourcesJar = "sourcesJar"
val kspKotlin = "kspKotlin"
sourcesJar.run {
dependOn(generateProto)
- dependOn(launchProtoData)
dependOn(kspKotlin)
dependOn(createVersionFile)
dependOn("prepareProtocConfigVersions")
}
- val dokkaHtml = "dokkaHtml"
- dokkaHtml.run {
+ val dokkaGenerate = "dokkaGenerate"
+ dokkaGenerate.run {
dependOn(generateProto)
- dependOn(launchProtoData)
- dependOn(kspKotlin)
- }
- val dokkaJavadoc = "dokkaJavadoc"
- dokkaJavadoc.run {
- dependOn(launchProtoData)
dependOn(kspKotlin)
}
+ val dokkaGeneratePublicationJavadoc = "dokkaGeneratePublicationJavadoc"
+ dokkaGeneratePublicationJavadoc.dependOn(kspKotlin)
"publishPluginJar".dependOn(createVersionFile)
compileKotlin.dependOn(kspKotlin)
compileTestKotlin.dependOn("kspTestKotlin")
"compileTestFixturesKotlin".dependOn("kspTestFixturesKotlin")
- "javadocJar".dependOn(dokkaHtml)
- "dokkaKotlinJar".dependOn(dokkaJavadoc)
+ "javadocJar".dependOn(dokkaGeneratePublicationJavadoc)
+ "htmlDocsJar".dependOn(dokkaGenerate)
+
+ "kspTestKotlin".dependOn("launchTestSpineCompiler")
}
}
diff --git a/buildSrc/src/main/kotlin/DocumentationSettings.kt b/buildSrc/src/main/kotlin/DocumentationSettings.kt
index b538fae..49247e1 100644
--- a/buildSrc/src/main/kotlin/DocumentationSettings.kt
+++ b/buildSrc/src/main/kotlin/DocumentationSettings.kt
@@ -24,6 +24,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import org.gradle.api.Project
+
/**
* The documentation settings specific to this project.
*
@@ -33,6 +35,36 @@
@Suppress("ConstPropertyName")
object DocumentationSettings {
+ /**
+ * The organization infix for the Spine SDK.
+ */
+ private const val orgPath = "github.com/SpineEventEngine"
+
+ /**
+ * The organization URL of the Spine SDK.
+ */
+ private const val orgUrl = "https://$orgPath"
+
+ /**
+ * Obtains the repository URL for the given project.
+ */
+ fun repoUrl(project: Project) = "https://${repoPath(project)}"
+
+ /**
+ * Obtains the repository path for the given project.
+ */
+ private fun repoPath(project: Project) = "$orgPath/${project.rootProject.name}"
+
+ /**
+ * Obtains the connection URL for the given project.
+ */
+ fun connectionUrl(project: Project) = "scm:git:git://${repoPath(project)}.git"
+
+ /**
+ * Obtains the developer connection URL for the given project.
+ */
+ fun developerConnectionUrl(project: Project) = "scm:git:ssh://${repoPath(project)}.git"
+
/**
* Settings passed to Dokka for
* [sourceLink][[org.jetbrains.dokka.gradle.engine.parameters.DokkaSourceLinkSpec]
@@ -43,12 +75,16 @@ object DocumentationSettings {
* The URL of the remote source code
* [location][org.jetbrains.dokka.gradle.engine.parameters.DokkaSourceLinkSpec.remoteUrl].
*/
- const val url: String = "https://github.com/SpineEventEngine/base/tree/master/src"
+ fun url(project: Project): String {
+ val root = project.rootProject.name
+ val module = project.name
+ return "$orgUrl/$root/tree/master/$module/src/main/kotlin"
+ }
/**
* The suffix used to append the source code line number to the URL.
*
- * The suffix depends on the online code repository.
+ * The value depends on the online code repository and is set for GitHub (`#L`).
*
* @see
* remoteLineSuffix
diff --git a/buildSrc/src/main/kotlin/DokkaExts.kt b/buildSrc/src/main/kotlin/DokkaExts.kt
index e505a6d..3c72e3b 100644
--- a/buildSrc/src/main/kotlin/DokkaExts.kt
+++ b/buildSrc/src/main/kotlin/DokkaExts.kt
@@ -29,32 +29,18 @@ import io.spine.gradle.publish.getOrCreate
import java.io.File
import java.time.LocalDate
import org.gradle.api.Project
+import org.gradle.api.Task
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.dsl.DependencyHandler
-import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.DependencyHandlerScope
-import org.jetbrains.dokka.gradle.AbstractDokkaTask
import org.jetbrains.dokka.gradle.DokkaExtension
-import org.jetbrains.dokka.gradle.DokkaTask
-import org.jetbrains.dokka.gradle.GradleDokkaSourceSetBuilder
import org.jetbrains.dokka.gradle.engine.parameters.DokkaSourceSetSpec
import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier
import org.jetbrains.dokka.gradle.engine.plugins.DokkaHtmlPluginParameters
-/**
- * To generate the documentation as seen from Java perspective, the `kotlin-as-java`
- * plugin was added to the Dokka classpath.
- *
- * @see
- * Dokka output formats
- */
-fun DependencyHandlerScope.useDokkaForKotlinAsJava() {
- dokkaPlugin(Dokka.KotlinAsJavaPlugin.lib)
-}
-
/**
* To exclude pieces of code annotated with `@Internal` from the documentation
* a custom plugin is added to the Dokka classpath.
@@ -72,9 +58,8 @@ private fun DependencyHandler.dokkaPlugin(dependencyNotation: Any): Dependency?
/**
* Resolves the directory where Dokka outputs HTML documentation for the given language.
*/
-internal fun Project.dokkaOutput(language: String): File {
- val lng = language.titleCaseFirstChar()
- return layout.buildDirectory.dir("docs/dokka$lng").get().asFile
+internal fun Project.dokkaHtmlOutput(): File {
+ return layout.buildDirectory.dir("dokka/html").get().asFile
}
/**
@@ -187,14 +172,14 @@ private fun DokkaSourceSetSpec.configureSourceSet(config: SourceSetConfig) {
}
/**
- * Configures this [DokkaTask] to accept only Kotlin files.
+ * Configures this [DokkaExtension] to accept only Kotlin files.
*/
fun DokkaExtension.configureForKotlin(project: Project, sourceLinkRemoteUrl: String) {
configureFor(project, "kotlin", sourceLinkRemoteUrl)
}
/**
- * Configures this [DokkaTask] to accept only Java files.
+ * Configures this [DokkaExtension] to accept only Java files.
*/
@Suppress("unused")
fun DokkaExtension.configureForJava(project: Project, sourceLinkRemoteUrl: String) {
@@ -202,39 +187,27 @@ fun DokkaExtension.configureForJava(project: Project, sourceLinkRemoteUrl: Strin
}
/**
- * Finds the `dokkaHtml` Gradle task.
+ * Finds the `dokkaGenerateHtml` Gradle task.
*/
-fun TaskContainer.dokkaHtmlTask(): DokkaTask? = this.findByName("dokkaHtml") as DokkaTask?
+fun TaskContainer.dokkaHtmlTask(): Task? = this.findByName("dokkaGeneratePublicationHtml")
/**
- * Returns only Java source roots out of all present in the source set.
- *
- * It is a helper method for generating documentation by Dokka only for Java code.
- * It is helpful when both Java and Kotlin source files are present in a source set.
- * Dokka can properly generate documentation for either Kotlin or Java depending on
- * the configuration, but not both.
+ * Finds the `dokkaGeneratePublicationJavadoc` Gradle task.
*/
-@Suppress("unused")
-internal fun GradleDokkaSourceSetBuilder.onlyJavaSources(): FileCollection {
- return sourceRoots.filter(File::isJavaSourceDirectory)
-}
-
-private fun File.isJavaSourceDirectory(): Boolean {
- return isDirectory && name == "java"
-}
+fun TaskContainer.dokkaJavadocTask(): Task? = this.findByName("dokkaGeneratePublicationJavadoc")
/**
- * Locates or creates `dokkaKotlinJar` task in this [Project].
+ * Locates or creates `htmlDocsJar` task in this [Project].
*
* The output of this task is a `jar` archive. The archive contains the Dokka output, generated upon
* Kotlin sources from `main` source set. Requires Dokka to be configured in the target project by
- * applying `dokka-for-kotlin` plugin.
+ * applying `dokka-setup` plugin.
*/
-fun Project.dokkaKotlinJar(): TaskProvider = tasks.getOrCreate("dokkaKotlinJar") {
- archiveClassifier.set("dokka")
- from(files(dokkaOutput("kotlin")))
+fun Project.htmlDocsJar(): TaskProvider = tasks.getOrCreate("htmlDocsJar") {
+ archiveClassifier.set("html-docs")
+ from(files(dokkaHtmlOutput()))
- tasks.dokkaHtmlTask()?.let{ dokkaTask ->
+ tasks.dokkaHtmlTask()?.let { dokkaTask ->
this@getOrCreate.dependsOn(dokkaTask)
}
}
@@ -246,29 +219,13 @@ fun Project.dokkaKotlinJar(): TaskProvider = tasks.getOrCreate("dokkaKotlin
* This predicate could be useful for disabling publishing tasks
* when doing, e.g., `publishToMavenLocal` for the purpose of the
* integration tests that (of course) do not test the documentation
- * generation proces and its resuults.
+ * generation process and its results.
*/
-fun AbstractDokkaTask.isInPublishingGraph(): Boolean =
+fun Task.isInPublishingGraph(): Boolean =
project.gradle.taskGraph.allTasks.any {
it.name == "publish" || it.name.contains("dokkaGenerate")
}
-/**
- * Locates or creates `dokkaJavaJar` task in this [Project].
- *
- * The output of this task is a `jar` archive. The archive contains the Dokka output, generated upon
- * Kotlin sources from `main` source set. Requires Dokka to be configured in the target project by
- * applying `dokka-for-java` and/or `dokka-for-kotlin` script plugin.
- */
-fun Project.dokkaJavaJar(): TaskProvider = tasks.getOrCreate("dokkaJavaJar") {
- archiveClassifier.set("dokka-java")
- from(files(dokkaOutput("java")))
-
- tasks.dokkaHtmlTask()?.let{ dokkaTask ->
- this@getOrCreate.dependsOn(dokkaTask)
- }
-}
-
/**
* Disables Dokka and Javadoc tasks in this `Project`.
*
diff --git a/buildSrc/src/main/kotlin/compile-protobuf.gradle.kts b/buildSrc/src/main/kotlin/compile-protobuf.gradle.kts
deleted file mode 100644
index 4acbb86..0000000
--- a/buildSrc/src/main/kotlin/compile-protobuf.gradle.kts
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import io.spine.dependency.lib.Protobuf
-import io.spine.gradle.protobuf.setup
-
-plugins {
- id("java-library")
- id("com.google.protobuf")
-}
-
-// For generating test fixtures. See `src/test/proto`.
-protobuf {
- configurations.excludeProtobufLite()
- protoc {
- artifact = Protobuf.compiler
- }
-
- afterEvaluate {
- // Walk the collection of tasks to force the execution
- // of the `configureEach` operations earlier.
- // This hack allows to avoid `ConcurrentModificationException` on
- // creating `kspKotlin` task.
- generateProtoTasks.all().size
- }
-
- generateProtoTasks.all().configureEach {
- setup()
- }
-}
diff --git a/buildSrc/src/main/kotlin/dokka-for-kotlin.gradle.kts b/buildSrc/src/main/kotlin/dokka-for-kotlin.gradle.kts
deleted file mode 100644
index c24135e..0000000
--- a/buildSrc/src/main/kotlin/dokka-for-kotlin.gradle.kts
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import org.jetbrains.dokka.gradle.DokkaTaskPartial
-
-plugins {
- id("org.jetbrains.dokka") // Cannot use `Dokka` dependency object here yet.
-}
-
-dependencies {
- useDokkaWithSpineExtensions()
-}
-
-afterEvaluate {
- dokka {
- configureForKotlin(
- project,
- DocumentationSettings.SourceLink.url
- )
- }
-}
-
-tasks.withType().configureEach {
- onlyIf {
- isInPublishingGraph()
- }
-}
diff --git a/buildSrc/src/main/kotlin/dokka-for-java.gradle.kts b/buildSrc/src/main/kotlin/dokka-setup.gradle.kts
similarity index 80%
rename from buildSrc/src/main/kotlin/dokka-for-java.gradle.kts
rename to buildSrc/src/main/kotlin/dokka-setup.gradle.kts
index 6bab079..d34615c 100644
--- a/buildSrc/src/main/kotlin/dokka-for-java.gradle.kts
+++ b/buildSrc/src/main/kotlin/dokka-setup.gradle.kts
@@ -24,28 +24,34 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import org.jetbrains.dokka.gradle.DokkaTaskPartial
+import org.jetbrains.dokka.gradle.tasks.DokkaBaseTask
plugins {
id("org.jetbrains.dokka") // Cannot use `Dokka` dependency object here yet.
+ id("org.jetbrains.dokka-javadoc")
}
dependencies {
- useDokkaForKotlinAsJava()
useDokkaWithSpineExtensions()
}
+tasks.withType().configureEach {
+ onlyIf {
+ isInPublishingGraph()
+ }
+}
+
afterEvaluate {
dokka {
configureForKotlin(
project,
- DocumentationSettings.SourceLink.url
+ DocumentationSettings.SourceLink.url(project)
)
}
-}
-
-tasks.withType().configureEach {
- onlyIf {
- isInPublishingGraph()
+ val kspKotlin = tasks.findByName("kspKotlin")
+ kspKotlin?.let {
+ tasks.withType().configureEach {
+ dependsOn(kspKotlin)
+ }
}
}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/Dependency.kt b/buildSrc/src/main/kotlin/io/spine/dependency/Dependency.kt
index 80c79f4..999538f 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/Dependency.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/Dependency.kt
@@ -58,16 +58,22 @@ abstract class Dependency {
/**
* The [modules] given with the [version].
*/
- final val artifacts: Map by lazy {
+ val artifacts: Map by lazy {
modules.associateWith { "$it:$version" }
}
/**
- * Obtains full Maven coordinates for the requested [module].
+ * Obtains full Maven coordinates for the requested [module] and [version].
*/
- fun artifact(module: String): String = artifacts[module] ?: error(
- "The dependency `${this::class.simpleName}` does not declare a module `$module`."
- )
+ fun artifact(module: String, version: String = ""): String {
+ return if (version.isEmpty()) {
+ artifacts[module] ?: error(
+ "The dependency `${this::class.simpleName}` does not declare a module `$module`."
+ )
+ } else {
+ "$module:$version"
+ }
+ }
/**
* Forces all artifacts of this dependency using the given resolution strategy.
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/build/Dokka.kt b/buildSrc/src/main/kotlin/io/spine/dependency/build/Dokka.kt
index 003bf58..ba0433a 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/build/Dokka.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/build/Dokka.kt
@@ -35,7 +35,7 @@ object Dokka {
* When changing the version, also change the version used in the
* `buildSrc/build.gradle.kts`.
*/
- const val version = "2.0.0"
+ const val version = "2.1.0"
object GradlePlugin {
const val id = "org.jetbrains.dokka"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt b/buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt
index f96ce56..b81c2b2 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt
@@ -35,7 +35,8 @@ import io.spine.dependency.Dependency
*/
@Suppress("unused")
object Ksp : Dependency() {
- override val version = "2.2.20-2.0.4"
+ override val version = "2.3.6"
+ val dogfoodingVersion = version
override val group = "com.google.devtools.ksp"
const val id = "com.google.devtools.ksp"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/build/LicenseReport.kt b/buildSrc/src/main/kotlin/io/spine/dependency/build/LicenseReport.kt
index a4eb754..826f868 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/build/LicenseReport.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/build/LicenseReport.kt
@@ -29,7 +29,7 @@ package io.spine.dependency.build
// https://github.com/jk1/Gradle-License-Report
@Suppress("unused")
object LicenseReport {
- private const val version = "1.16"
+ private const val version = "3.0.1"
const val lib = "com.github.jk1:gradle-license-report:$version"
object GradlePlugin {
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Grpc.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Grpc.kt
index 48e70f4..9d48602 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Grpc.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Grpc.kt
@@ -32,7 +32,7 @@ import io.spine.dependency.DependencyWithBom
@Suppress("unused")
object Grpc : DependencyWithBom() {
- override val version = "1.72.0"
+ override val version = "1.76.0"
override val group = "io.grpc"
override val bom = "$group:grpc-bom:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Guava.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Guava.kt
index 9115701..a61639d 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Guava.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Guava.kt
@@ -37,7 +37,7 @@ package io.spine.dependency.lib
*/
@Suppress("unused", "ConstPropertyName")
object Guava {
- private const val version = "33.4.8-jre"
+ private const val version = "33.5.0-jre"
const val group = "com.google.guava"
const val lib = "$group:guava:$version"
const val testLib = "$group:guava-testlib:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt
index 0029ab1..ff4202f 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt
@@ -39,7 +39,7 @@ object Kotlin : DependencyWithBom() {
* depend on Gradle and the version of embedded Kotlin.
*/
@Suppress("MemberVisibilityCanBePrivate") // used directly from the outside.
- const val runtimeVersion = "2.2.20"
+ const val runtimeVersion = "2.3.20"
override val version = runtimeVersion
override val group = "org.jetbrains.kotlin"
@@ -49,7 +49,7 @@ object Kotlin : DependencyWithBom() {
* This is the version of
* [Kotlin embedded into Gradle](https://docs.gradle.org/current/userguide/compatibility.html#kotlin).
*/
- const val embeddedVersion = "2.2.20"
+ const val embeddedVersion = "2.3.20"
/**
* The version of the JetBrains annotations library, which is a transitive
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Protobuf.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Protobuf.kt
index 8eaf49a..b7277f5 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Protobuf.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Protobuf.kt
@@ -33,7 +33,7 @@ package io.spine.dependency.lib
)
object Protobuf {
const val group = "com.google.protobuf"
- const val version = "4.31.1"
+ const val version = "4.34.1"
/**
* The Java library with Protobuf data types.
@@ -64,7 +64,7 @@ object Protobuf {
*
* When changing the version, also change the version used in the `build.gradle.kts`.
*/
- const val version = "0.9.5"
+ const val version = "0.9.6"
const val id = "com.google.protobuf"
const val lib = "$group:protobuf-gradle-plugin:$version"
}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/ArtifactVersion.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/ArtifactVersion.kt
deleted file mode 100644
index 77497b2..0000000
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/ArtifactVersion.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.dependency.local
-
-/**
- * Versions for published Spine SDK artifacts.
- */
-@Suppress("ConstPropertyName")
-object ArtifactVersion {
-
- /**
- * The version of [Spine.base].
- *
- * @see spine-base
- */
- @Deprecated(message = "Please use `Base.version`.", ReplaceWith("Base.version"))
- const val base = Base.version
-
- @Suppress("unused")
- @Deprecated(
- message = "Please use `Base.versionForBuildScript`.",
- ReplaceWith("Base.versionForBuildScript")
- )
- const val baseForBuildScript = Base.versionForBuildScript
-
- /**
- * The version of [Spine.reflect].
- *
- * @see spine-reflect
- */
- @Deprecated(message = "Please use `Reflect.version`.", ReplaceWith("Reflect.version"))
- const val reflect = Reflect.version
-
- /**
- * The version of [Logging].
- */
- @Deprecated(message = "Please use `Logging.version`.", ReplaceWith("Logging.version"))
- const val logging = Logging.version
-
- /**
- * The version of [Spine.testlib].
- *
- * @see spine-testlib
- */
- @Deprecated(message = "Please use `TestLib.version`.", ReplaceWith("TestLib.version"))
- const val testlib = TestLib.version
-
- /**
- * The version of `core-java`.
- */
- @Deprecated(message = "Please use `CoreJava.version`.", ReplaceWith("CoreJava.version"))
- const val core = CoreJava.version
-
- /**
- * The version of [Spine.modelCompiler].
- *
- * @see spine-model-compiler
- */
- @Suppress("unused")
- @Deprecated(
- message = "Please use `ModelCompiler.version` instead.",
- ReplaceWith("ModelCompiler.version")
- )
- const val mc = ModelCompiler.version
-
- /**
- * The version of [Spine.baseTypes].
- *
- * @see spine-base-types
- */
- @Deprecated(message = "Please use `BaseTypes.version`.", ReplaceWith("BaseTypes.version"))
- const val baseTypes = BaseTypes.version
-
- /**
- * The version of [Spine.time].
- *
- * @see spine-time
- */
- @Deprecated(message = "Please use `Time.version`.", ReplaceWith("Time.version"))
- const val time = Time.version
-
- /**
- * The version of [Spine.change].
- *
- * @see spine-change
- */
- @Deprecated(message = "Please use `Change.version`.", ReplaceWith("Change.version"))
- const val change = Change.version
-
- /**
- * The version of [Spine.text].
- *
- * @see spine-text
- */
- @Deprecated(message = "Please use `Text.version`.", ReplaceWith("Text.version"))
- const val text = Text.version
-
- /**
- * The version of [Spine.toolBase].
- *
- * @see spine-tool-base
- */
- @Suppress("unused")
- @Deprecated(message = "Please use `ToolBase.version`.", ReplaceWith("ToolBase.version"))
- const val toolBase = ToolBase.version
-
- /**
- * The version of [Spine.javadocFilter].
- *
- * @see spine-javadoc-tools
- */
- const val javadocTools = "2.0.0-SNAPSHOT.75"
-}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt
index b8351d9..463cbf2 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt
@@ -29,16 +29,18 @@ package io.spine.dependency.local
/**
* Spine Base module.
*
- * @see spine-base
+ * @see spine-base-libraries
*/
@Suppress("ConstPropertyName", "unused")
object Base {
- const val version = "2.0.0-SNAPSHOT.361"
- const val versionForBuildScript = "2.0.0-SNAPSHOT.361"
+ const val version = "2.0.0-SNAPSHOT.387"
+ const val versionForBuildScript = "2.0.0-SNAPSHOT.387"
const val group = Spine.group
- const val artifact = "spine-base"
- const val lib = "$group:$artifact:$version"
- const val format = "$group:spine-format:$version"
- const val libForBuildScript = "$group:$artifact:$versionForBuildScript"
- const val annotations = "$group:spine-annotations:$version"
+ private const val prefix = "spine"
+ const val libModule = "$prefix-base"
+ const val lib = "$group:$libModule:$version"
+ const val libForBuildScript = "$group:$libModule:$versionForBuildScript"
+ const val annotations = "$group:$prefix-annotations:$version"
+ const val environment = "$group:$prefix-environment:$version"
+ const val format = "$group:$prefix-format:$version"
}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/BaseTypes.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/BaseTypes.kt
index b0b534d..2714738 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/BaseTypes.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/BaseTypes.kt
@@ -33,7 +33,7 @@ package io.spine.dependency.local
*/
@Suppress("ConstPropertyName")
object BaseTypes {
- const val version = "2.0.0-SNAPSHOT.210"
+ const val version = "2.0.0-SNAPSHOT.223"
const val group = Spine.group
const val artifact = "spine-base-types"
const val lib = "$group:$artifact:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Change.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Change.kt
index 2436580..7809c9c 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Change.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Change.kt
@@ -33,7 +33,7 @@ package io.spine.dependency.local
*/
@Suppress("ConstPropertyName")
object Change {
- const val version = "2.0.0-SNAPSHOT.200"
+ const val version = "2.0.0-SNAPSHOT.206"
const val group = Spine.group
const val artifact = "spine-change"
const val lib = "$group:$artifact:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt
index 708dd6b..31cbfb3 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt
@@ -26,10 +26,12 @@
package io.spine.dependency.local
+import io.spine.dependency.Dependency
+
/**
* Dependencies on the Spine Compiler modules.
*
- * To use a locally published ProtoData version instead of the version from a public plugin
+ * To use a locally published Compiler version instead of the version from a public plugin
* registry, set the `COMPILER_VERSION` and/or the `COMPILER_DF_VERSION` environment variables
* and stop the Gradle daemons so that Gradle observes the env change:
* ```
@@ -56,9 +58,9 @@ package io.spine.dependency.local
"ConstPropertyName" /* We use custom convention for artifact properties. */,
"MemberVisibilityCanBePrivate" /* The properties are used directly by other subprojects. */,
)
-object Compiler {
+object Compiler : Dependency() {
const val pluginGroup = Spine.group
- const val group = "io.spine.tools"
+ override val group = "io.spine.tools"
const val pluginId = "io.spine.compiler"
/**
@@ -67,22 +69,22 @@ object Compiler {
const val module = "io.spine.tools:compiler"
/**
- * The version of ProtoData dependencies.
+ * The version of the Compiler dependencies.
*/
- val version: String
- private const val fallbackVersion = "2.0.0-SNAPSHOT.024"
+ override val version: String
+ private const val fallbackVersion = "2.0.0-SNAPSHOT.041"
/**
- * The distinct version of ProtoData used by other build tools.
+ * The distinct version of the Compiler used by other build tools.
*
- * When ProtoData is used both for building the project and as a part of the Project's
- * transitional dependencies, this is the version used to build the project itself.
+ * When the Compiler is used both for building the project and as a part of the Project's
+ * transitive dependencies, this is the version used to build the project itself.
*/
val dogfoodingVersion: String
- private const val fallbackDfVersion = "2.0.0-SNAPSHOT.024"
+ private const val fallbackDfVersion = "2.0.0-SNAPSHOT.041"
/**
- * The artifact for the ProtoData Gradle plugin.
+ * The artifact for the Compiler Gradle plugin.
*/
val pluginLib: String
@@ -129,6 +131,21 @@ object Compiler {
val testlib
get() = "$group:compiler-testlib:$version"
+ override val modules: List
+ get() = listOf(
+ api,
+ backend,
+ params,
+ protocPlugin,
+ gradleApi,
+ cliApi,
+ jvm,
+ fatCli,
+ testlib
+ ).map {
+ it.split(":").let { (group, artifact) -> "$group:$artifact" }
+ }
+
/**
* An env variable storing a custom [version].
*/
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt
index d9f5ba3..2e0b697 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt
@@ -27,17 +27,19 @@
package io.spine.dependency.local
// For backward compatibility.
+@Suppress("unused")
+@Deprecated("Use `CoreJvm` instead.", ReplaceWith("CoreJvm"))
typealias CoreJava = CoreJvm
/**
- * Dependencies on `core-java` modules.
+ * Dependencies on `core-jvm` modules.
*
- * See [`SpineEventEngine/core-java`](https://github.com/SpineEventEngine/core-java/).
+ * See [`SpineEventEngine/core-jvm`](https://github.com/SpineEventEngine/core-jvm/).
*/
@Suppress("ConstPropertyName", "unused")
object CoreJvm {
const val group = Spine.group
- const val version = "2.0.0-SNAPSHOT.332"
+ const val version = "2.0.0-SNAPSHOT.372"
const val coreArtifact = "spine-core"
const val clientArtifact = "spine-client"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt
index 5762d48..344e8a1 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt
@@ -29,7 +29,7 @@ package io.spine.dependency.local
/**
* Dependencies on the CoreJvm Compiler artifacts.
*
- * See [mc-java](https://github.com/SpineEventEngine/core-jvm-compiler).
+ * See [CoreJvm Compiler](https://github.com/SpineEventEngine/core-jvm-compiler).
*/
@Suppress(
"MemberVisibilityCanBePrivate" /* `pluginLib()` is used by subprojects. */,
@@ -46,12 +46,12 @@ object CoreJvmCompiler {
/**
* The version used to in the build classpath.
*/
- const val dogfoodingVersion = "2.0.0-SNAPSHOT.015"
+ const val dogfoodingVersion = "2.0.0-SNAPSHOT.058"
/**
* The version to be used for integration tests.
*/
- const val version = "2.0.0-SNAPSHOT.015"
+ const val version = "2.0.0-SNAPSHOT.058"
/**
* The ID of the Gradle plugin.
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/ModelCompiler.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/ModelCompiler.kt
index 5f9e541..fb4359d 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/ModelCompiler.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/ModelCompiler.kt
@@ -33,7 +33,7 @@ package io.spine.dependency.local
*/
@Suppress("ConstPropertyName")
object ModelCompiler {
- const val version = "2.0.0-SNAPSHOT.133"
+ const val version = "2.0.0-SNAPSHOT.200"
const val group = Spine.toolsGroup
const val artifact = "spine-model-compiler"
const val lib = "$group:$artifact:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/ProtoTap.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/ProtoTap.kt
index 813b4cc..3b4df10 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/ProtoTap.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/ProtoTap.kt
@@ -38,7 +38,7 @@ package io.spine.dependency.local
)
object ProtoTap {
const val group = "io.spine.tools"
- const val version = "0.13.0"
+ const val version = "0.14.0"
const val gradlePluginId = "io.spine.prototap"
const val api = "$group:prototap-api:$version"
const val gradlePlugin = "$group:prototap-gradle-plugin:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt
index a5cce49..51cdee7 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt
@@ -27,7 +27,7 @@
package io.spine.dependency.local
/**
- * Dependencies on smaller Spine modules.
+ * Defines Maven groups for the Spine SDK artifacts.
*/
@Suppress("unused", "ConstPropertyName")
object Spine {
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/TestLib.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/TestLib.kt
index f9754bb..d3fe7c6 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/TestLib.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/TestLib.kt
@@ -33,7 +33,7 @@ package io.spine.dependency.local
*/
@Suppress("ConstPropertyName")
object TestLib {
- const val version = "2.0.0-SNAPSHOT.210"
+ const val version = "2.0.0-SNAPSHOT.211"
const val group = Spine.toolsGroup
const val artifact = "spine-testlib"
const val lib = "$group:$artifact:$version"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Text.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Text.kt
deleted file mode 100644
index 216ec13..0000000
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Text.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.dependency.local
-
-/**
- * Spine Reflect library.
- *
- * @see spine-text
- */
-@Suppress("ConstPropertyName")
-object Text {
- const val version = "2.0.0-SNAPSHOT.6"
- const val group = Spine.group
- const val artifact = "spine-text"
- const val lib = "$group:$artifact:$version"
-}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt
index 289adee..e78af42 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,17 +26,43 @@
package io.spine.dependency.local
+import io.spine.dependency.Dependency
+
/**
* Spine Time library.
*
* @see spine-time
*/
-@Suppress("ConstPropertyName")
-object Time {
- const val version = "2.0.0-SNAPSHOT.203"
- const val group = Spine.group
- const val artifact = "spine-time"
- const val lib = "$group:$artifact:$version"
-
- const val testLib = "${Spine.toolsGroup}:spine-time-testlib:$version"
+@Suppress(
+ "unused" /* Some subprojects do not use all Time artifacts. */,
+ "ConstPropertyName" /* We use custom convention for artifact properties. */,
+ "MemberVisibilityCanBePrivate" /* The properties are used directly by other subprojects. */,
+)
+object Time : Dependency() {
+ override val group = Spine.group
+ override val version = "2.0.0-SNAPSHOT.235"
+ private const val infix = "spine-time"
+
+ fun lib(version: String): String = "$group:$infix:$version"
+ val lib get() = lib(version)
+ const val libArtifact: String = infix
+
+ fun javaExtensions(version: String): String = "$group:$infix-java:$version"
+ val javaExtensions get() = javaExtensions(version)
+
+ fun kotlinExtensions(version: String): String = "$group:$infix-kotlin:$version"
+ val kotlinExtensions get() = kotlinExtensions(version)
+
+ fun testLib(version: String): String = "${Spine.toolsGroup}:time-testlib:$version"
+ val testLib get() = testLib(version)
+
+ override val modules: List
+ get() = listOf(
+ lib,
+ javaExtensions,
+ kotlinExtensions,
+ testLib
+ ).map {
+ it.split(":").let { (g, artifact) -> "$g:$artifact" }
+ }
}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt
index 69e7bea..c4b9b6d 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt
@@ -34,7 +34,8 @@ package io.spine.dependency.local
@Suppress("ConstPropertyName", "unused")
object ToolBase {
const val group = Spine.toolsGroup
- const val version = "2.0.0-SNAPSHOT.361"
+ const val version = "2.0.0-SNAPSHOT.376"
+ const val dogfoodingVersion = "2.0.0-SNAPSHOT.376"
const val lib = "$group:tool-base:$version"
const val classicCodegen = "$group:classic-codegen:$version"
@@ -45,14 +46,18 @@ object ToolBase {
const val intellijPlatformJava = "$group:intellij-platform-java:$version"
const val psi = "$group:psi:$version"
- const val psiJava = "$group:psi-java:$version"
+ const val psiJavaArtifactName = "psi-java"
+ const val psiJava = "$group:$psiJavaArtifactName:$version"
- const val gradleRootPlugin = "$group:gradle-root-plugin:$version"
+ const val rootGradlePlugins = "$group:root-gradle-plugins:$version"
const val gradlePluginApi = "$group:gradle-plugin-api:$version"
const val gradlePluginApiTestFixtures = "$group:gradle-plugin-api-test-fixtures:$version"
const val jvmTools = "$group:jvm-tools:$version"
- const val jvmToolPlugins = "$group:jvm-tool-all-plugins:$version"
+ const val jvmToolPluginDogfooding = "$group:jvm-tool-plugins-all:$dogfoodingVersion"
+ const val jvmToolPlugins = "$group:jvm-tool-plugins-all:$version"
+
+ const val protobufSetupPlugins = "$group:protobuf-setup-plugins:$version"
object JavadocFilter {
const val group = ToolBase.group
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
index e842283..549ed2c 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
@@ -36,21 +36,28 @@ object Validation {
/**
* The version of the Validation library artifacts.
*/
- const val version = "2.0.0-SNAPSHOT.351"
+ const val version = "2.0.0-SNAPSHOT.411"
/**
* The last version of Validation compatible with ProtoData.
*/
const val pdCompatibleVersion = "2.0.0-SNAPSHOT.342"
- const val group = "io.spine.validation"
- private const val prefix = "spine-validation"
+ const val group = Spine.toolsGroup
+ private const val prefix = "validation"
+
+ const val gradlePluginLib = "$group:$prefix-gradle-plugin:$version"
+
+ const val runtimeModule = "${Spine.group}:spine-$prefix-jvm-runtime"
+
+ fun runtime(version: String) = "$runtimeModule:$version"
+ val runtime = runtime(version)
+
+ @Deprecated("Use `runtime` instead.", ReplaceWith("runtime"))
+ const val oldRuntime = "io.spine.validation:spine-validation-java-runtime:2.0.0-SNAPSHOT.354"
- const val runtimeModule = "$group:$prefix-java-runtime"
- const val runtime = "$runtimeModule:$version"
const val javaModule = "$group:$prefix-java"
const val java = "$javaModule:$version"
-
const val javaBundleModule = "$group:$prefix-java-bundle"
/** Obtains the artifact for the `java-bundle` artifact of the given version. */
@@ -61,5 +68,5 @@ object Validation {
const val model = "$group:$prefix-model:$version"
const val configModule = "$group:$prefix-configuration"
- const val configuration = "$configModule:$version"
+ const val context = "$group:$prefix-context:$version"
}
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/test/JUnit.kt b/buildSrc/src/main/kotlin/io/spine/dependency/test/JUnit.kt
index b07849f..a496217 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/test/JUnit.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/test/JUnit.kt
@@ -29,11 +29,11 @@ package io.spine.dependency.test
import io.spine.dependency.Dependency
import io.spine.dependency.DependencyWithBom
-// https://junit.org/junit5/
+// https://junit.org/
@Suppress("unused", "ConstPropertyName")
object JUnit : DependencyWithBom() {
- override val version = "5.13.2"
+ override val version = "6.0.3"
override val group: String = "org.junit"
/**
@@ -63,19 +63,6 @@ object JUnit : DependencyWithBom() {
const val legacy = "junit:junit:$legacyVersion"
- @Deprecated("Use JUnit.Jupiter.api instead", ReplaceWith("JUnit.Jupiter.api"))
- val api = listOf(
- "org.apiguardian:apiguardian-api:$apiGuardianVersion",
- "org.junit.jupiter:junit-jupiter-api:$version",
- "org.junit.jupiter:junit-jupiter-params:$version"
- )
-
- @Deprecated("Use JUnit.Jupiter.engine instead", ReplaceWith("JUnit.Jupiter.engine"))
- val runner = "org.junit.jupiter:junit-jupiter-engine:$version"
-
- @Deprecated("Use JUnit.Jupiter.params instead", ReplaceWith("JUnit.Jupiter.params"))
- val params = "org.junit.jupiter:junit-jupiter-params:$version"
-
object Jupiter : Dependency() {
override val version = JUnit.version
override val group = "org.junit.jupiter"
@@ -86,9 +73,6 @@ object JUnit : DependencyWithBom() {
val params = "$group:$infix-params"
val engine = "$group:$infix-engine"
- @Deprecated("Please use `[Jupiter.run { artifacts[api] }` instead.")
- val apiArtifact = "$api:$version"
-
override val modules = listOf(api, params, engine)
}
@@ -105,7 +89,7 @@ object JUnit : DependencyWithBom() {
* So when we use JUnit as a platform, this property should be picked up
* for the dependencies automatically.
*/
- override val version: String = "1.13.2"
+ override val version: String = "6.0.0"
override val group = "org.junit.platform"
private const val infix = "junit-platform"
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/test/Kotest.kt b/buildSrc/src/main/kotlin/io/spine/dependency/test/Kotest.kt
index 0d71ab2..1c55190 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/test/Kotest.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/test/Kotest.kt
@@ -35,8 +35,9 @@ package io.spine.dependency.test
*/
@Suppress("unused", "ConstPropertyName")
object Kotest {
- const val version = "6.0.3"
+ const val version = "6.1.11"
const val group = "io.kotest"
+ const val gradlePluginId = "io.kotest"
const val assertions = "$group:kotest-assertions-core:$version"
const val runnerJUnit5 = "$group:kotest-runner-junit5:$version"
const val runnerJUnit5Jvm = "$group:kotest-runner-junit5-jvm:$version"
@@ -45,6 +46,7 @@ object Kotest {
const val frameworkEngine = "$group:kotest-framework-engine:$version"
// https://plugins.gradle.org/plugin/io.kotest.multiplatform
+ @Deprecated("The plugin is deprecated. Use `io.kotest` plugin instead.")
object MultiplatformGradlePlugin {
const val version = "6.0.0.M4"
const val id = "io.kotest.multiplatform"
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/Runtime.kt b/buildSrc/src/main/kotlin/io/spine/gradle/Cli.kt
similarity index 94%
rename from buildSrc/src/main/kotlin/io/spine/gradle/Runtime.kt
rename to buildSrc/src/main/kotlin/io/spine/gradle/Cli.kt
index 0a32c33..7e0c227 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/Runtime.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/Cli.kt
@@ -35,13 +35,7 @@ import java.lang.ProcessBuilder.Redirect.PIPE
import java.util.*
/**
- * Utilities for working with processes from Gradle code.
- */
-@Suppress("unused")
-private const val ABOUT = ""
-
-/**
- * Executor of CLI commands.
+ * Executes a process from Gradle code.
*
* Uses the passed [workingFolder] as the directory in which the commands are executed.
*/
@@ -92,7 +86,7 @@ class Cli(private val workingFolder: File) {
* Asynchronously reads all lines from this [InputStream] and appends them
* to the passed [StringWriter].
*/
-fun InputStream.pourTo(dest: StringWriter) {
+private fun InputStream.pourTo(dest: StringWriter) {
Thread {
val sc = Scanner(this)
while (sc.hasNextLine()) {
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/ProjectExtensions.kt b/buildSrc/src/main/kotlin/io/spine/gradle/ProjectExtensions.kt
index deda203..afccc24 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/ProjectExtensions.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/ProjectExtensions.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,10 +36,6 @@ import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.getByType
-/**
- * This file contains extension methods and properties for the Gradle `Project`.
- */
-
/**
* Logs the result of the function using the project logger at `INFO` level.
*/
@@ -86,8 +82,9 @@ fun Project.getTask(name: String): T {
/**
* Obtains Maven artifact ID of this [Project].
*
- * The method checks if [SpinePublishing] extension is configured upon this project. If yes,
- * returns [SpinePublishing.artifactId] for the project. Otherwise, a project's name is returned.
+ * The property getter checks if [SpinePublishing] extension is configured upon this project.
+ * If yes, it returns [SpinePublishing.artifactId] for the project.
+ * Otherwise, a project's name is returned.
*/
val Project.artifactId: String
get() {
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/VersionWriter.kt b/buildSrc/src/main/kotlin/io/spine/gradle/VersionWriter.kt
deleted file mode 100644
index d3d4323..0000000
--- a/buildSrc/src/main/kotlin/io/spine/gradle/VersionWriter.kt
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.gradle
-
-import java.util.*
-import org.gradle.api.DefaultTask
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.file.DirectoryProperty
-import org.gradle.api.provider.MapProperty
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.TaskAction
-
-/**
- * A task that generates a dependency versions `.properties` file.
- */
-abstract class WriteVersions : DefaultTask() {
-
- /**
- * Versions to add to the file.
- *
- * The map key is a string in the format of `_`, and the value
- * is the version corresponding to those group ID and artifact name.
- *
- * @see WriteVersions.version
- */
- @get:Input
- abstract val versions: MapProperty
-
- /**
- * The directory that hosts the generated file.
- */
- @get:OutputDirectory
- abstract val versionsFileLocation: DirectoryProperty
-
- /**
- * Adds a dependency version to write into the file.
- *
- * The given dependency notation is a Gradle artifact string of format:
- * `"::"`.
- *
- * @see WriteVersions.versions
- * @see WriteVersions.includeOwnVersion
- */
- fun version(dependencyNotation: String) {
- val parts = dependencyNotation.split(":")
- check(parts.size == 3) { "Invalid dependency notation: `$dependencyNotation`." }
- versions.put("${parts[0]}_${parts[1]}", parts[2])
- }
-
- /**
- * Enables the versions file to include the version of the project that owns this task.
- *
- * @see WriteVersions.version
- * @see WriteVersions.versions
- */
- fun includeOwnVersion() {
- val groupId = project.group.toString()
- val artifactId = project.artifactId
- val version = project.version.toString()
- versions.put("${groupId}_${artifactId}", version)
- }
-
- /**
- * Creates a `.properties` file with versions, named after the value
- * of [Project.artifactId] property.
- *
- * The name of the file would be: `versions-.properties`.
- *
- * By default, value of [Project.artifactId] property is a project's name with "spine-" prefix.
- * For example, if a project's name is "tools", then the name of the file would be:
- * `versions-spine-tools.properties`.
- */
- @TaskAction
- fun writeFile() {
- versions.finalizeValue()
- versionsFileLocation.finalizeValue()
-
- val values = versions.get()
- val properties = Properties()
- properties.putAll(values)
- val outputDir = versionsFileLocation.get().asFile
- outputDir.mkdirs()
- val fileName = resourceFileName()
- val file = outputDir.resolve(fileName)
- file.createNewFile()
- file.writer().use {
- properties.store(it, "Dependency versions supplied by the `$path` task.")
- }
- }
-
- private fun resourceFileName(): String {
- val artifactId = project.artifactId
- return "versions-${artifactId}.properties"
- }
-}
-
-/**
- * A plugin that enables storing dependency versions into a resource file.
- *
- * Dependency version may be used by Gradle plugins at runtime.
- *
- * The plugin adds one task — `writeVersions`, which generates a `.properties` file with some
- * dependency versions.
- *
- * The generated file will be available in classpath of the target project under the name:
- * `versions-.properties`, where `` is the name of the target
- * Gradle project.
- */
-@Suppress("unused")
-class VersionWriter : Plugin {
-
- override fun apply(target: Project): Unit = with (target.tasks) {
- val task = register("writeVersions", WriteVersions::class.java) {
- versionsFileLocation.convention(project.layout.buildDirectory.dir(name))
- includeOwnVersion()
- project.sourceSets
- .getByName("main")
- .resources
- .srcDir(versionsFileLocation)
- }
- getByName("processResources").dependsOn(task)
- }
-}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/docs/UpdatePluginVersion.kt b/buildSrc/src/main/kotlin/io/spine/gradle/docs/UpdatePluginVersion.kt
new file mode 100644
index 0000000..0277bcd
--- /dev/null
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/docs/UpdatePluginVersion.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2026, TeamDev. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and/or binary forms, with or without
+ * modification, must retain the above copyright notice and the following
+ * disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.spine.gradle.docs
+
+import java.io.File
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * Updates the version of a Gradle plugin in `build.gradle.kts` files.
+ *
+ * The task searches for plugin declarations in the format
+ * `id("plugin-id") version "version-number"` and replaces
+ * the version number with the one found in the version script file.
+ *
+ * @property directory
+ * The directory to scan recursively for `build.gradle.kts` files.
+ * @property version
+ * The version number to set for the plugin.
+ * @property pluginId
+ * The ID of the plugin whose version should be updated.
+ * @property kotlinVersion
+ * Optional. If set, updates the version of the Kotlin plugin declared with
+ * `kotlin("…") version "…"` syntax in the `plugins` block.
+ * This option works in combination with the [version] and [pluginId] properties.
+ */
+abstract class UpdatePluginVersion : DefaultTask() {
+
+ @get:InputDirectory
+ abstract val directory: DirectoryProperty
+
+ @get:Input
+ abstract val version: Property
+
+ @get:Input
+ abstract val pluginId: Property
+
+ @get:Input
+ @get:Optional
+ abstract val kotlinVersion: Property
+
+ /**
+ * Updates plugin versions in build files within the path in the [directory].
+ */
+ @TaskAction
+ fun update() {
+ val rootDir = directory.get().asFile
+
+ val kotlinVersionSet = kotlinVersion.isPresent
+ val kotlinVer = kotlinVersion.orNull
+ val id = pluginId.get()
+ val ver = version.get()
+
+ rootDir.walkTopDown()
+ .filter { it.name == "build.gradle.kts" }
+ .forEach { file ->
+ if (kotlinVersionSet && kotlinVer != null) {
+ updateKotlinPluginVersion(file, kotlinVer)
+ }
+ updatePluginVersion(file, id, ver)
+ }
+ }
+
+ @Suppress("MemberNameEqualsClassName")
+ private fun updatePluginVersion(file: File, id: String, version: String) {
+ val content = file.readText()
+ val pluginId = Regex.escape(id)
+ // Regex to match: id("pluginId") version "version-number"
+ val regex = """id\("$pluginId"\)\s+version\s+"([^"]+)"""".toRegex()
+
+ if (regex.containsMatchIn(content)) {
+ val updatedContent = regex.replace(content) {
+ "id(\"$id\") version \"$version\""
+ }
+ if (content != updatedContent) {
+ file.writeText(updatedContent)
+ logger.info("Updated version of '$id' in `${file.absolutePath}`.")
+ }
+ }
+ }
+
+ private fun updateKotlinPluginVersion(file: File, kotlinVersion: String) {
+ val content = file.readText()
+ // Regex to match Kotlin plugin declarations like: kotlin("jvm") version "1.9.0"
+ val regex = """kotlin\("([^"]+)"\)\s+version\s+"([^"]+)"""".toRegex()
+ if (regex.containsMatchIn(content)) {
+ val updatedContent = regex.replace(content) { matchResult ->
+ val plugin = matchResult.groupValues[1]
+ "kotlin(\"$plugin\") version \"$kotlinVersion\""
+ }
+ if (content != updatedContent) {
+ file.writeText(updatedContent)
+ logger.info("Updated Kotlin plugin version in `${file.absolutePath}`.")
+ }
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/dokka/DokkaExtensions.kt b/buildSrc/src/main/kotlin/io/spine/gradle/dokka/DokkaExtensions.kt
deleted file mode 100644
index 727a079..0000000
--- a/buildSrc/src/main/kotlin/io/spine/gradle/dokka/DokkaExtensions.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.gradle.dokka
-
-import java.io.File
-import org.gradle.api.file.FileCollection
-import org.jetbrains.dokka.gradle.GradleDokkaSourceSetBuilder
-
-/**
- * Returns only Java source roots out of all present in the source set.
- *
- * It is a helper method for generating documentation by Dokka only for Java code.
- * It is helpful when both Java and Kotlin source files are present in a source set.
- * Dokka can properly generate documentation for either Kotlin or Java depending on
- * the configuration, but not both.
- */
-@Suppress("unused")
-internal fun GradleDokkaSourceSetBuilder.onlyJavaSources(): FileCollection {
- return sourceRoots.filter(File::isJavaSourceDirectory)
-}
-
-private fun File.isJavaSourceDirectory(): Boolean {
- return isDirectory && name == "java"
-}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/dokka/TaskContainerExtensions.kt b/buildSrc/src/main/kotlin/io/spine/gradle/dokka/TaskContainerExtensions.kt
deleted file mode 100644
index 02deead..0000000
--- a/buildSrc/src/main/kotlin/io/spine/gradle/dokka/TaskContainerExtensions.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.spine.gradle.dokka
-
-import org.gradle.api.tasks.TaskContainer
-import org.jetbrains.dokka.gradle.DokkaTask
-
-/**
- * Finds the `dokkaHtml` Gradle task.
- */
-@Suppress("unused")
-fun TaskContainer.dokkaHtmlTask() = this.getByName("dokkaHtml") as DokkaTask
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/fs/LazyTempPath.kt b/buildSrc/src/main/kotlin/io/spine/gradle/fs/LazyTempPath.kt
index f6e1777..0344819 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/fs/LazyTempPath.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/fs/LazyTempPath.kt
@@ -57,7 +57,7 @@ class LazyTempPath(private val prefix: String) : Path {
vararg modifiers: WatchEvent.Modifier?
): WatchKey = delegate.register(watcher, events, *modifiers)
- override fun register(watcher: WatchService, vararg events: WatchEvent.Kind<*>?): WatchKey =
+ override fun register(watcher: WatchService, vararg events: WatchEvent.Kind<*>): WatchKey =
delegate.register(watcher, *events)
override fun getFileSystem(): FileSystem = delegate.fileSystem
@@ -101,7 +101,7 @@ class LazyTempPath(private val prefix: String) : Path {
override fun toAbsolutePath(): Path = delegate.toAbsolutePath()
- override fun toRealPath(vararg options: LinkOption?): Path = delegate.toRealPath(*options)
+ override fun toRealPath(vararg options: LinkOption): Path = delegate.toRealPath(*options)
override fun toFile(): File = delegate.toFile()
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/git/Repository.kt b/buildSrc/src/main/kotlin/io/spine/gradle/git/Repository.kt
index 55ce67f..e0ce827 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/git/Repository.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/git/Repository.kt
@@ -26,8 +26,11 @@
package io.spine.gradle.git
+import com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly
import io.spine.gradle.Cli
import io.spine.gradle.fs.LazyTempPath
+import java.util.concurrent.TimeUnit.MILLISECONDS
+import org.gradle.api.Project
/**
* Interacts with a real Git repository.
@@ -43,26 +46,18 @@ import io.spine.gradle.fs.LazyTempPath
* NOTE: This class creates a temporal folder, so it holds resources. For the proper
* release of resources please use the provided functionality inside a `use` block or
* call the `close` method manually.
+ *
+ * @property project The Gradle project in which context the repo operations are held.
+ * @property sshUrl The GitHub SSH URL to the underlying repository.
+ * @property user Current user configuration.
+ * This configuration determines what ends up in the `author` and `committer` fields of a commit.
+ * @property currentBranch The currently checked-out branch.
*/
class Repository private constructor(
-
- /**
- * The GitHub SSH URL to the underlying repository.
- */
+ private val project: Project,
private val sshUrl: String,
-
- /**
- * Current user configuration.
- *
- * This configuration determines what ends up in author and committer fields of a commit.
- */
private var user: UserInfo,
-
- /**
- * Currently checked out branch.
- */
- private var currentBranch: String
-
+ private var currentBranch: String,
) : AutoCloseable {
/**
@@ -80,14 +75,21 @@ class Repository private constructor(
/**
* Executes a command in the [location].
*/
- private fun repoExecute(vararg command: String): String =
- Cli(location.toFile()).execute(*command)
+ private fun repoExecute(vararg command: String): String {
+ val cmd = command.toList().joinToString(" ")
+ val msg = "[Repo (${project.path})] Executing command: `$cmd`."
+ System.err.println(msg)
+ return Cli(location.toFile()).execute(*command)
+ }
/**
* Checks out the branch by its name.
+ *
+ * IMPORTANT. The branch must exist in the upstream repository.
*/
fun checkout(branch: String) {
repoExecute("git", "checkout", branch)
+ repoExecute("git", "pull")
currentBranch = branch
}
@@ -128,10 +130,15 @@ class Repository private constructor(
}
/**
- * Pushes local repository to the remote.
+ * Pushes the current branch of the repository to the remote.
+ *
+ * Performs a pull with rebase before pushing to ensure the local branch is up-to-date.
*/
fun push() {
- repoExecute("git", "push")
+ withRetries(description = "Pushing to $sshUrl, branch = '$currentBranch'") {
+ repoExecute("git", "pull", "--rebase")
+ repoExecute("git", "push")
+ }
}
override fun close() {
@@ -139,18 +146,27 @@ class Repository private constructor(
}
companion object Factory {
+
/**
* Clones the repository with the provided SSH URL in a temporal folder.
- * Configures the username and the email of the Git user. See [configureUser]
- * documentation for more information. Performs checkout of the branch in
- * case it was passed. By default, [master][Branch.master] is checked out.
+ *
+ * Configures the username and the email of the Git user.
+ * See [configureUser] documentation for more information.
+ *
+ * Performs checkout of the branch in case it was passed.
+ * By default, [master][Branch.master] is checked out.
*
* @throws IllegalArgumentException if SSH URL is an empty string.
*/
- fun of(sshUrl: String, user: UserInfo, branch: String = Branch.master): Repository {
+ fun clone(
+ project: Project,
+ sshUrl: String,
+ user: UserInfo,
+ branch: String = Branch.master,
+ ): Repository {
require(sshUrl.isNotBlank()) { "SSH URL cannot be an empty string." }
- val repo = Repository(sshUrl, user, branch)
+ val repo = Repository(project, sshUrl, user, branch)
repo.clone()
repo.configureUser(user)
@@ -162,3 +178,44 @@ class Repository private constructor(
}
}
}
+
+/**
+ * Executes a given operation with retries using exponential backoff strategy.
+ *
+ * If the operation fails, it will be retried up to the specified number of times
+ * with increasing delays between attempts.
+ * The delay increases exponentially but is capped at the specified maximum value.
+ *
+ * If all retries fail, the exception from the final attempt will be thrown to the caller.
+ *
+ * @param T the type of value returned by the operation
+ * @param times the maximum number of attempts to execute the operation (default: 3)
+ * @param initialDelay the delay before the first retry in milliseconds (default: 100ms)
+ * @param maxDelay the maximum delay between retries in milliseconds (default: 2000ms)
+ * @param factor the multiplier used to increase delay after each failure (default: 2.0)
+ * @param description a description of the operation for error reporting (default: empty string)
+ * @param block the operation to execute
+ * @return the result of the successful operation execution
+ */
+@Suppress("TooGenericExceptionCaught", "LongParameterList")
+private fun withRetries(
+ times: Int = 5,
+ initialDelay: Long = 2000, // ms
+ maxDelay: Long = 20000, // ms
+ factor: Double = 2.0,
+ description: String = "",
+ block: () -> T
+): T {
+ var currentDelay = initialDelay
+ repeat(times - 1) {
+ try {
+ return block()
+ } catch (e: Exception) {
+ System.err.println("'$description' failed. " +
+ "Message: '${e.message}'. Retrying in $currentDelay ms.")
+ }
+ sleepUninterruptibly(currentDelay, MILLISECONDS)
+ currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
+ }
+ return block()
+}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/RepositoryExtensions.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/RepositoryExtensions.kt
index ef67c71..de75295 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/RepositoryExtensions.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/RepositoryExtensions.kt
@@ -30,6 +30,7 @@ import io.spine.gradle.git.Branch
import io.spine.gradle.git.Repository
import io.spine.gradle.git.UserInfo
import io.spine.gradle.repo.RepoSlug
+import org.gradle.api.Project
/**
* Clones the current project repository with the branch dedicated to publishing
@@ -38,14 +39,15 @@ import io.spine.gradle.repo.RepoSlug
* The repository's GitHub SSH URL is derived from the `REPO_SLUG` environment
* variable. The [branch][Branch.documentation] dedicated to publishing documentation
* is automatically checked out in this repository. Also, the username and the email
- * of the git user are automatically configured. The username is set
- * to "UpdateGitHubPages Plugin", and the email is derived from
+ * of the git user are automatically configured.
+ *
+ * The username is set to `"UpdateGitHubPages Plugin"`, and the email is derived from
* the `FORMAL_GIT_HUB_PAGES_AUTHOR` environment variable.
*
* @throws org.gradle.api.GradleException if any of the environment variables described above
* is not set.
*/
-internal fun Repository.Factory.forPublishingDocumentation(): Repository {
+internal fun Repository.Factory.forPublishingDocumentation(project: Project): Repository {
val host = RepoSlug.fromVar().gitHost()
val username = "UpdateGitHubPages Plugin"
@@ -54,5 +56,5 @@ internal fun Repository.Factory.forPublishingDocumentation(): Repository {
val branch = Branch.documentation
- return of(host, user, branch)
+ return clone(project, host, user, branch)
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/SshKey.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/SshKey.kt
index 186c474..68be42a 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/SshKey.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/SshKey.kt
@@ -29,24 +29,43 @@ package io.spine.gradle.github.pages
import io.spine.gradle.Cli
import java.io.File
import org.gradle.api.GradleException
+import org.gradle.api.logging.Logger
/**
- * Registers SSH key for further operations with GitHub Pages.
+ * Registers the SSH key for further operations with GitHub Pages.
+ *
+ * @property rootProjectFolder The folder of the project for which we build the documentation.
+ * @property logger The logger for placing diagnostic messages of this class.
*/
-internal class SshKey(private val rootProjectFolder: File) {
+internal class SshKey(
+ private val rootProjectFolder: File,
+ private val logger: Logger
+) {
+
+ private fun log(message: () -> String) {
+ if (logger.isInfoEnabled) {
+ logger.info("[SshKey] " + message())
+ }
+ }
+
/**
* Creates an SSH key with the credentials and registers it by invoking the
* `register-ssh-key.sh` script.
*/
fun register() {
+ log { "Registering using ${rootProjectFolder.absolutePath}." }
val gitHubAccessKey = gitHubKey()
+ log { "Obtained the key file at ${gitHubAccessKey.absolutePath}." }
val sshConfigFile = sshConfigFile()
+ log { "Located the SSH key file at ${sshConfigFile.absolutePath}." }
sshConfigFile.appendPublisher(gitHubAccessKey)
+ log { "SSH config file appended." }
execute(
"${rootProjectFolder.absolutePath}/config/scripts/register-ssh-key.sh",
gitHubAccessKey.absolutePath
)
+ log { "The SSH key registered." }
}
/**
@@ -59,7 +78,7 @@ internal class SshKey(private val rootProjectFolder: File) {
* publishing.
*
* Thus, we configure the SSH agent to use the `deploy_rsa_key` only for specific
- * references, namely in `github.com-publish`.
+ * references, namely in `github-publish`.
*
* @throws GradleException if `deploy_key_rsa` is not found.
*/
@@ -91,9 +110,10 @@ internal class SshKey(private val rootProjectFolder: File) {
val nl = System.lineSeparator()
this.appendText(
nl +
- "Host github.com-publish" + nl +
- "User git" + nl +
- "IdentityFile ${privateKey.absolutePath}" + nl
+ "Host github-publish" + nl +
+ " HostName github.com" + nl +
+ " User git" + nl +
+ " IdentityFile ${privateKey.absolutePath}" + nl
)
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/TaskName.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/TaskName.kt
index f5e3bfc..72b8fd3 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/TaskName.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/TaskName.kt
@@ -34,14 +34,14 @@ object TaskName {
const val updateGitHubPages = "updateGitHubPages"
/**
- * The name of the helper task to gather the generated Javadoc before updating
- * GitHub Pages.
+ * The name of the helper task to gather the generated Javadoc format
+ * documentation generated by Dokka before updating GitHub Pages.
*/
- const val copyJavadoc = "copyJavadoc"
+ const val copyJavadocDocs = "copyJavadocDocs"
/**
- * The name of the helper task to gather Dokka-generated documentation before
- * updating GitHub Pages.
+ * The name of the helper task to gather HTML documentation
+ * generated by Dokka before updating GitHub Pages.
*/
- const val copyDokka = "copyDokka"
+ const val copyHtmlDocs = "copyHtmlDocs"
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/Update.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/Update.kt
index 0f9a0f5..785162e 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/Update.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/Update.kt
@@ -41,23 +41,19 @@ import org.gradle.api.logging.Logger
fun Task.updateGhPages(project: Project) {
val plugin = project.plugins.getPlugin(UpdateGitHubPages::class.java)
- with(plugin) {
- SshKey(rootFolder).register()
- }
+ SshKey(plugin.rootFolder, logger).register()
- val repository = Repository.forPublishingDocumentation()
+ val repository = Repository.forPublishingDocumentation(project)
- val updateJavadoc = with(plugin) {
- UpdateJavadoc(project, javadocOutputFolder, repository, logger)
- }
+ val updateJavadocFormat =
+ UpdateJavadocFormat(project, plugin.javadocOutputFolder, repository, logger)
- val updateDokka = with(plugin) {
- UpdateDokka(project, dokkaOutputFolder, repository, logger)
- }
+ val updateHtmlFormat =
+ UpdateHtmlFormat(project, plugin.htmlOutputFolder, repository, logger)
repository.use {
- updateJavadoc.run()
- updateDokka.run()
+ updateJavadocFormat.run()
+ updateHtmlFormat.run()
repository.push()
}
}
@@ -80,17 +76,17 @@ private abstract class UpdateDocumentation(
protected abstract val docsDestinationFolder: String
/**
- * The name of the tool used to generate the documentation to update.
+ * The name of the format of the documentation to update.
*
* This name will appear in logs as part of a message.
*/
- protected abstract val toolName: String
+ protected abstract val formatName: String
private val mostRecentFolder by lazy {
File("${repository.location}/${docsDestinationFolder}/${project.name}")
}
- private fun logDebug(message: () -> String) {
+ private fun log(message: () -> String) {
if (logger.isDebugEnabled) {
logger.debug(message())
}
@@ -98,25 +94,24 @@ private abstract class UpdateDocumentation(
fun run() {
val module = project.name
- logDebug {"Update of the $toolName documentation for module `$module` started." }
+ log { "Update of the `$formatName` documentation for the module `$module` started." }
val documentation = replaceMostRecentDocs()
copyIntoVersionDir(documentation)
val version = project.version
val updateMessage =
- "Update `$toolName` documentation for module `$module` as for version $version"
+ "Update `$formatName` documentation for the module" +
+ " `$module` with the version `$version`."
repository.commitAllChanges(updateMessage)
- logDebug { "Update of the `$toolName` documentation for `$module` successfully finished." }
+ log { "Update of the `$formatName` documentation for `$module` successfully finished." }
}
private fun replaceMostRecentDocs(): ConfigurableFileCollection {
val generatedDocs = project.files(docsSourceFolder)
- logDebug {
- "Replacing the most recent `$toolName` documentation in `${mostRecentFolder}`."
- }
+ log { "Replacing the most recent `$formatName` documentation in `$mostRecentFolder`." }
copyDocs(generatedDocs, mostRecentFolder)
return generatedDocs
@@ -133,14 +128,12 @@ private abstract class UpdateDocumentation(
private fun copyIntoVersionDir(generatedDocs: ConfigurableFileCollection) {
val versionedDocDir = File("$mostRecentFolder/v/${project.version}")
- logDebug {
- "Storing the new version of `$toolName` documentation in `${versionedDocDir}`."
- }
+ log { "Storing the new version of `$formatName` documentation in `${versionedDocDir}`." }
copyDocs(generatedDocs, versionedDocDir)
}
}
-private class UpdateJavadoc(
+private class UpdateJavadocFormat(
project: Project,
docsSourceFolder: Path,
repository: Repository,
@@ -148,12 +141,12 @@ private class UpdateJavadoc(
) : UpdateDocumentation(project, docsSourceFolder, repository, logger) {
override val docsDestinationFolder: String
- get() = "reference"
- override val toolName: String
- get() = "Javadoc"
+ get() = "javadoc"
+ override val formatName: String
+ get() = "javadoc"
}
-private class UpdateDokka(
+private class UpdateHtmlFormat(
project: Project,
docsSourceFolder: Path,
repository: Repository,
@@ -161,7 +154,7 @@ private class UpdateDokka(
) : UpdateDocumentation(project, docsSourceFolder, repository, logger) {
override val docsDestinationFolder: String
- get() = "dokka-reference"
- override val toolName: String
- get() = "Dokka"
+ get() = "reference"
+ override val formatName: String
+ get() = "html"
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPages.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPages.kt
index e339dd4..860dfbe 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPages.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPages.kt
@@ -27,13 +27,11 @@
package io.spine.gradle.github.pages
import dokkaHtmlTask
+import dokkaJavadocTask
import io.spine.gradle.fs.LazyTempPath
-import io.spine.gradle.github.pages.TaskName.copyDokka
-import io.spine.gradle.github.pages.TaskName.copyJavadoc
+import io.spine.gradle.github.pages.TaskName.copyHtmlDocs
+import io.spine.gradle.github.pages.TaskName.copyJavadocDocs
import io.spine.gradle.github.pages.TaskName.updateGitHubPages
-import io.spine.gradle.isSnapshot
-import io.spine.gradle.javadoc.ExcludeInternalDoclet
-import io.spine.gradle.javadoc.javadocTask
import java.io.File
import org.gradle.api.Plugin
import org.gradle.api.Project
@@ -43,30 +41,12 @@ import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
/**
- * Registers the `updateGitHubPages` task which performs the update of the GitHub
- * Pages with the documentation generated by Javadoc and Dokka for a particular
- * Gradle project. The generated documentation is appended to the `spine.io` site
- * via GitHub pages by pushing commits to the `gh-pages` branch.
- *
- * Please note that the update is only performed for the projects which are
- * NOT snapshots.
+ * Registers the `updateGitHubPages` task which performs the update of
+ * the GitHub Pages with the documentation generated in Javadoc and HTML format
+ * for a particular Gradle project.
*
- * Users may supply [allowInternalJavadoc][UpdateGitHubPagesExtension.allowInternalJavadoc]
- * to configure documentation generated by Javadoc. The documentation for the code
- * marked `@Internal` is included when the option is set to `true`. By default, this
- * option is `false`.
- *
- * Usage:
- * ```
- * updateGitHubPages {
- *
- * // Include `@Internal`-annotated code.
- * allowInternalJavadoc.set(true)
- *
- * // Propagate the full path to the local folder of the repository root.
- * rootFolder.set(rootDir.absolutePath)
- * }
- * ```
+ * The generated documentation is appended to the `spine.io` site
+ * via GitHub pages by pushing commits to the `gh-pages` branch.
*
* In order to work, the script needs a `deploy_key_rsa` private RSA key file in the
* repository root. It is recommended to encrypt it in the repository and then decrypt
@@ -104,16 +84,16 @@ class UpdateGitHubPages : Plugin {
private lateinit var includedInputs: Set
/**
- * Path to the temp folder used to gather the Javadoc output before submitting it
- * to the GitHub Pages update.
+ * Path to the temp folder used to gather the Javadoc format output (generated by Dokka)
+ * before submitting it to the GitHub Pages update.
*/
internal val javadocOutputFolder = LazyTempPath("javadoc")
/**
- * Path to the temp folder used to gather the documentation generated by Dokka
- * before submitting it to the GitHub Pages update.
+ * Path to the temp folder used to gather the HTML documentation
+ * generated by Dokka before submitting it to the GitHub Pages update.
*/
- internal val dokkaOutputFolder = LazyTempPath("dokka")
+ internal val htmlOutputFolder = LazyTempPath("html")
/**
* Applies the plugin to the specified [project].
@@ -127,12 +107,7 @@ class UpdateGitHubPages : Plugin {
override fun apply(project: Project) {
val extension = UpdateGitHubPagesExtension.createIn(project)
project.afterEvaluate {
- val projectVersion = project.version.toString()
- if (projectVersion.isSnapshot()) {
- registerNoOpTask()
- } else {
- registerTasks(extension)
- }
+ registerTasks(extension)
}
}
@@ -141,6 +116,7 @@ class UpdateGitHubPages : Plugin {
* the message telling the update is skipped, since the project is in
* its `SNAPSHOT` version.
*/
+ @Suppress("unused")
private fun Project.registerNoOpTask() {
tasks.register(updateGitHubPages) {
doLast {
@@ -154,41 +130,31 @@ class UpdateGitHubPages : Plugin {
}
private fun Project.registerTasks(extension: UpdateGitHubPagesExtension) {
- val allowInternalJavadoc = extension.allowInternalJavadoc()
rootFolder = extension.rootFolder()
includedInputs = extension.includedInputs()
- if (!allowInternalJavadoc) {
- val doclet = ExcludeInternalDoclet()
- doclet.registerTaskIn(this)
- }
-
- tasks.registerCopyJavadoc(allowInternalJavadoc)
+ tasks.registerCopyJavadoc()
tasks.registerCopyDokka()
val updatePagesTask = tasks.registerUpdateTask()
updatePagesTask.configure {
- dependsOn(copyJavadoc)
- dependsOn(copyDokka)
+ dependsOn(copyJavadocDocs)
+ dependsOn(copyHtmlDocs)
}
}
- private fun TaskContainer.registerCopyJavadoc(allowInternalJavadoc: Boolean) {
- val inputs = composeJavadocInputs(allowInternalJavadoc)
+ private fun TaskContainer.registerCopyJavadoc() {
+ val inputs = composeJavadocInputs()
- register(copyJavadoc, Copy::class.java) {
+ register(copyJavadocDocs, Copy::class.java) {
inputs.forEach { from(it) }
into(javadocOutputFolder)
}
}
- private fun TaskContainer.composeJavadocInputs(allowInternalJavadoc: Boolean): List {
+ private fun TaskContainer.composeJavadocInputs(): List {
val inputs = mutableListOf()
- if (allowInternalJavadoc) {
- inputs.add(javadocTask())
- } else {
- inputs.add(javadocTask(ExcludeInternalDoclet.taskName))
- }
+ inputs.add(dokkaJavadocTask()!!)
inputs.addAll(includedInputs)
return inputs
}
@@ -196,9 +162,9 @@ class UpdateGitHubPages : Plugin {
private fun TaskContainer.registerCopyDokka() {
val inputs = composeDokkaInputs()
- register(copyDokka, Copy::class.java) {
+ register(copyHtmlDocs, Copy::class.java) {
inputs.forEach { from(it) }
- into(dokkaOutputFolder)
+ into(htmlOutputFolder)
}
}
@@ -226,7 +192,7 @@ class UpdateGitHubPages : Plugin {
}
private fun cleanup() {
- val folders = listOf(dokkaOutputFolder, javadocOutputFolder)
+ val folders = listOf(htmlOutputFolder, javadocOutputFolder)
folders.forEach {
it.toFile().deleteRecursively()
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPagesExtension.kt b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPagesExtension.kt
index 90eebc2..a849a83 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPagesExtension.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPagesExtension.kt
@@ -38,65 +38,41 @@ import org.gradle.kotlin.dsl.property
* Configures the `updateGitHubPages` extension.
*/
@Suppress("unused")
-fun Project.updateGitHubPages(excludeInternalDocletVersion: String,
- action: UpdateGitHubPagesExtension.() -> Unit) {
+fun Project.updateGitHubPages(
+ action: UpdateGitHubPagesExtension.() -> Unit
+) {
apply()
val extension = extensions.getByType(UpdateGitHubPagesExtension::class)
- extension.excludeInternalDocletVersion = excludeInternalDocletVersion
extension.action()
}
/**
* The extension for configuring the [UpdateGitHubPages] plugin.
+ *
+ * @property rootFolder The root folder of the repository to which the updated `Project` belongs.
+ * @property includeInputs The external inputs, which output should be included
+ * into the GitHub Pages update. The values are interpreted according to
+ * [Copy.from][org.gradle.api.tasks.Copy.from] specification.
+ * This property is optional.
*/
-class UpdateGitHubPagesExtension
-private constructor(
-
- /**
- * Tells whether the types marked `@Internal` should be included into
- * the doc generation.
- */
- val allowInternalJavadoc: Property,
-
- /**
- * The root folder of the repository to which the updated `Project` belongs.
- */
+class UpdateGitHubPagesExtension private constructor(
var rootFolder: Property,
-
- /**
- * The external inputs, which output should be included into
- * the GitHub Pages update.
- *
- * The values are interpreted according to
- * [org.gradle.api.tasks.Copy.from] specification.
- *
- * This property is optional.
- */
var includeInputs: SetProperty
) {
-
- /**
- * The version of the
- * [ExcludeInternalDoclet][io.spine.gradle.javadoc.ExcludeInternalDoclet]
- * used when updating documentation at GitHub Pages.
- *
- * This value is used when adding dependency on the doclet when the plugin tasks
- * are registered. Since the doclet dependency is required, its value passed as
- * a parameter for the extension, rather than a property.
- */
- internal lateinit var excludeInternalDocletVersion: String
-
internal companion object {
- /** The name of the extension. */
+ /**
+ * The name of the extension.
+ */
const val name = "updateGitHubPages"
- /** Creates a new extension and adds it to the passed project. */
+ /**
+ * Creates a new extension and adds it to the passed project.
+ */
fun createIn(project: Project): UpdateGitHubPagesExtension {
val factory = project.objects
val result = UpdateGitHubPagesExtension(
- allowInternalJavadoc = factory.property(Boolean::class),
rootFolder = factory.property(File::class),
includeInputs = factory.setProperty(Any::class.java)
)
@@ -105,27 +81,15 @@ private constructor(
}
}
- /**
- * Returns `true` if the `@Internal`-annotated code should be included into the
- * generated documentation, `false` otherwise.
- */
- fun allowInternalJavadoc(): Boolean {
- return allowInternalJavadoc.get()
- }
-
/**
* Returns the local root folder of the repository, to which the handled Gradle
* Project belongs.
*/
- fun rootFolder(): File {
- return rootFolder.get()
- }
+ fun rootFolder(): File = rootFolder.get()
/**
* Returns the external inputs, which results should be included into the
* GitHub Pages update.
*/
- fun includedInputs(): Set {
- return includeInputs.get()
- }
+ fun includedInputs(): Set = includeInputs.get()
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt b/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
index 4539aa9..92b7a38 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
@@ -27,7 +27,9 @@
package io.spine.gradle.kotlin
import org.gradle.jvm.toolchain.JavaLanguageVersion
+import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
/**
@@ -53,11 +55,12 @@ fun KotlinJvmProjectExtension.applyJvmToolchain(version: String) =
*/
@Suppress("unused")
fun KotlinCommonCompilerOptions.setFreeCompilerArgs() {
+ if (this is KotlinJvmCompilerOptions) {
+ jvmDefault.set(JvmDefaultMode.NO_COMPATIBILITY)
+ }
freeCompilerArgs.addAll(
listOf(
"-Xskip-prerelease-check",
- "-Xjvm-default=all",
- "-Xinline-classes",
"-Xexpect-actual-classes",
"-Xcontext-parameters",
"-opt-in=" +
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/protobuf/ProtoTaskExtensions.kt b/buildSrc/src/main/kotlin/io/spine/gradle/protobuf/ProtoTaskExtensions.kt
deleted file mode 100644
index b8439a0..0000000
--- a/buildSrc/src/main/kotlin/io/spine/gradle/protobuf/ProtoTaskExtensions.kt
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright 2025, TeamDev. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Redistribution and use in source and/or binary forms, with or without
- * modification, must retain the above copyright notice and the following
- * disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-@file:Suppress("unused", "UnusedReceiverParameter") /* Extensions declared in this file
- are used in the modules that build proto files without using the Spine Compiler. */
-
-package io.spine.gradle.protobuf
-
-import com.google.protobuf.gradle.GenerateProtoTask
-import com.google.protobuf.gradle.ProtobufExtension
-import io.spine.gradle.sourceSets
-import java.io.File
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.Paths
-import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
-import kotlin.io.path.Path
-import org.gradle.api.Project
-import org.gradle.api.file.SourceDirectorySet
-import org.gradle.api.tasks.SourceSet
-import org.gradle.kotlin.dsl.get
-import org.gradle.kotlin.dsl.getByType
-import org.gradle.plugins.ide.idea.GenerateIdeaModule
-import org.gradle.plugins.ide.idea.model.IdeaModel
-import org.gradle.plugins.ide.idea.model.IdeaModule
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
-import titleCaseFirstChar
-
-/**
- * Obtains the path of the `generated` directory under the project root directory.
- */
-private val Project.generatedDir: Path
- get() = projectDir.resolve("generated").toPath()
-
-/**
- * Obtains the `generated` directory for the source set of the task.
- *
- * If [language] is specified returns the subdirectory for this language.
- */
-private fun GenerateProtoTask.generatedDir(language: String = ""): File {
- val path = "${project.generatedDir}/${sourceSet.name}/$language"
- return File(path)
-}
-
-/**
- * Configures a [GenerateProtoTask] for the code which cannot use Spine Model Compiler
- * (e.g., Spine Base or Spine Validation modules).
- *
- * The task configuration consists of the following steps:
- *
- * 1. Adding `"kotlin"` to the list of involved `protoc` builtins.
- *
- * 2. Turning on the generation of a descriptor set file for each source set.
- * These files are placed under the `build/descriptors` directory.
- *
- * 3. Removing source code generated for `com.google` package for both Java and Kotlin.
- * This is done at the final steps of the code generation.
- *
- * 4. Making `processResource` tasks depend on corresponding `generateProto` tasks.
- * If the source set of the configured task isn't `main`, appropriate infix for
- * the task names is used.
- *
- * The usage of this extension in a module build file would be:
- * ```
- * protobuf {
- * generateProtoTasks.all().configureEach {
- * setup()
- * }
- * }
- * ```
- * Using the same code under `subprojects` in a root build file does not seem to work because
- * test descriptor set files are not copied to resources. Performing this configuration from
- * a module build script solves the issue.
- *
- * IMPORTANT: In addition to calling `setup`, a submodule must contain a descriptor set reference
- * file (`desc.ref`) files placed under `resources`. The descriptor reference file must contain
- * a reference to the descriptor set file generated by the corresponding `GenerateProtoTask`.
- *
- * For example, for the `test` source set, the reference would be `known_types_test.desc`, and
- * for the `main` source set, the reference would be `known_types_main.desc`.
- *
- * See `io.spine.code.proto.DescriptorReference` and `io.spine.code.proto.FileDescriptors` classes
- * under the `base` project for more details.
- */
-@Suppress("unused")
-fun GenerateProtoTask.setup() {
- builtins.maybeCreate("kotlin")
- setupDescriptorSetFileCreation()
- excludeProtocOutput()
- doLast {
- copyGeneratedFiles()
- }
- setupKotlinCompile()
- dependOnProcessResourcesTask()
- makeDirsForIdeaModule()
-}
-
-/**
- * Tell `protoc` to generate descriptor set files under the project build dir.
- *
- * The name of the descriptor set file to be generated
- * is made to be unique via the project's Maven coordinates.
- *
- * As the last step of this task, writes a `desc.ref` file
- * for the contextual source set, pointing to the generated descriptor set file.
- * This is needed to allow other Spine libraries to locate and load the generated
- * descriptor set files properly.
- *
- * Such a job is usually performed by Spine McJava plugin;
- * however, it is not possible to use this plugin (or its code)
- * in this repository due to cyclic dependencies.
- */
-@Suppress(
- "TooGenericExceptionCaught" /* Handling all file-writing failures in the same way.*/
-)
-fun GenerateProtoTask.setupDescriptorSetFileCreation() {
- // Tell `protoc` generate a descriptor set file.
- // The name of the generated file reflects the Maven coordinates of the project.
- val ssn = sourceSet.name
- generateDescriptorSet = true
- val buildDir = project.layout.buildDirectory.asFile.get().path
- val descriptorsDir = "$buildDir/descriptors/${ssn}"
- val descriptorName = project.descriptorSetName(sourceSet)
- with(descriptorSetOptions) {
- path = "$descriptorsDir/$descriptorName"
- includeImports = true
- includeSourceInfo = true
- }
-
- // Add the descriptor set file into the resources.
- project.sourceSets.named(ssn) {
- resources.srcDirs(descriptorsDir)
- }
-
- // Create a `desc.ref` in the same resource folder,
- // with the name of the descriptor set file created above.
- this.doLast {
- val descRefFile = File(descriptorsDir, "desc.ref")
- descRefFile.createNewFile()
- try {
- Files.write(descRefFile.toPath(), setOf(descriptorName), TRUNCATE_EXISTING)
- } catch (e: Exception) {
- project.logger.error("Error writing `${descRefFile.absolutePath}`.", e)
- throw e
- }
- }
-}
-
-/**
- * Returns a name of the descriptor file for the given [sourceSet],
- * reflecting the Maven coordinates of Gradle artifact, and the source set
- * for which the descriptor set name is to be generated.
- *
- * The returned value is just a file name and does not contain a file path.
- */
-private fun Project.descriptorSetName(sourceSet: SourceSet) =
- arrayOf(
- group.toString(),
- name,
- sourceSet.name,
- version.toString()
- ).joinToString(separator = "_", postfix = ".desc")
-
-/**
- * Copies files from the [outputBaseDir][GenerateProtoTask.outputBaseDir] into
- * a subdirectory of [generatedDir][Project.generatedDir] for
- * the current [sourceSet][GenerateProtoTask.sourceSet].
- *
- * Also removes sources belonging to the `com.google` package in the target directory.
- */
-private fun GenerateProtoTask.copyGeneratedFiles() {
- project.copy {
- from(outputBaseDir)
- into(generatedDir())
- }
- deleteComGoogle("java")
- deleteComGoogle("kotlin")
-}
-
-/**
- * Remove the code generated for Google Protobuf library types.
- *
- * Java code for the `com.google` package was generated because we wanted
- * to have descriptors for all the types, including those from Google Protobuf library.
- * We want all the descriptors so that they are included into the resources used by
- * the `io.spine.type.KnownTypes` class.
- *
- * Now, as we have the descriptors _and_ excessive Java or Kotlin code, we delete it to avoid
- * classes that duplicate those coming from Protobuf library JARs.
- */
-private fun GenerateProtoTask.deleteComGoogle(language: String) {
- val comDirectory = generatedDir(language).resolve("com")
- val googlePackage = comDirectory.resolve("google")
-
- project.delete(googlePackage)
-
- // If the `com` directory becomes empty, delete it too.
- if (comDirectory.exists() && comDirectory.isDirectory && comDirectory.list()!!.isEmpty()) {
- project.delete(comDirectory)
- }
-}
-
-/**
- * Exclude [GenerateProtoTask.outputBaseDir] from Java source set directories to avoid
- * duplicated source code files.
- */
-fun GenerateProtoTask.excludeProtocOutput() {
- val protocOutputDir = File(outputBaseDir).parentFile
-
- /**
- * Filter out directories belonging to `build/generated/source/proto`.
- */
- fun filterFor(directorySet: SourceDirectorySet) {
- val newSourceDirectories = directorySet.sourceDirectories
- .filter { !it.residesIn(protocOutputDir) }
- .toSet()
- // Make sure we start from scratch.
- // Not doing this failed the following, real, assignment sometimes.
- directorySet.setSrcDirs(listOf())
- directorySet.srcDirs(newSourceDirectories)
- }
-
- val java: SourceDirectorySet = sourceSet.java
- filterFor(java)
- // Add copied files to the Java source set.
- java.srcDir(generatedDir("java"))
-
- val kotlin = sourceSet.kotlin
- filterFor(kotlin)
- // Add copied files to the Kotlin source set.
- kotlin.srcDir(generatedDir("kotlin"))
-}
-
-private val SourceSet.kotlin: SourceDirectorySet get() =
- (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("kotlin")
- as SourceDirectorySet
-
-/**
- * Make sure Kotlin compilation explicitly depends on this `GenerateProtoTask` to avoid racing.
- */
-fun GenerateProtoTask.setupKotlinCompile() {
- val kotlinCompile = project.kotlinCompilationTaskFor(sourceSet)
- kotlinCompile?.dependsOn(this)
-}
-
-/**
- * Make the tasks `processResources` depend on `generateProto` tasks explicitly so that:
- * 1) Descriptor set files get into resources, avoiding the racing conditions
- * during the build.
- *
- * 2) We don't have the warning "Execution optimizations have been disabled..." issued
- * by Gradle during the build because Protobuf Gradle Plugin does not set
- * dependencies between `generateProto` and `processResources` tasks.
- */
-fun GenerateProtoTask.dependOnProcessResourcesTask() {
- val processResources = processResourceTaskName(sourceSet.name)
- project.tasks[processResources].dependsOn(this)
-}
-
-/**
- * Obtains the name of the `processResource` task for the given source set name.
- */
-private fun processResourceTaskName(sourceSetName: String): String {
- val infix =
- if (sourceSetName == "main") ""
- else sourceSetName.titleCaseFirstChar()
- return "process${infix}Resources"
-}
-
-private fun Project.kotlinCompilationTaskFor(sourceSet: SourceSet): KotlinCompilationTask<*>? {
- val taskName = sourceSet.getCompileTaskName("Kotlin")
- return tasks.named(taskName, KotlinCompilationTask::class.java).orNull
-}
-
-private fun File.residesIn(directory: File): Boolean =
- canonicalFile.startsWith(directory.absolutePath)
-
-/**
- * Ensures that generated directories for Java and Kotlin are created before [GenerateIdeaModule].
- *
- * This works as advised by `Utils.groovy` from Protobuf Gradle plugin:
- * ```
- * This is required because the IntelliJ IDEA plugin does not allow adding source directories
- * that do not exist. The IntelliJ IDEA config files should be valid from the start even if
- * a user runs './gradlew idea' before running './gradlew generateProto'.
- * ```
- */
-fun GenerateProtoTask.makeDirsForIdeaModule() {
- project.plugins.withId("idea") {
- val javaDir = generatedDir("java")
- val kotlinDir = generatedDir("kotlin")
- project.tasks.withType(GenerateIdeaModule::class.java).forEach {
- it.doFirst {
- javaDir.mkdirs()
- kotlinDir.mkdirs()
- }
- }
- }
-}
-
-/**
- * Prints diagnostic output of `sourceDirs` and `generatedSourceDirs` of an [IdeaModule].
- *
- * To get a handle on [IdeaModule] please use the following code:
- *
- * ```kotlin
- * val module = project.extensions.findByType(IdeaModel::class.java)!!.module
- * ```
- */
-@Suppress("unused") // To be used when debugging build scripts.
-fun IdeaModule.printSourceDirectories() {
- println("**** [IDEA] Source directories:")
- sourceDirs.forEach { println(it) }
- println()
- println("**** [IDEA] Generated source directories:")
- generatedSourceDirs.forEach { println(it) }
- println()
- println("**** [IDEA] Excluded directories:")
- excludeDirs.forEach { println(it) }
-}
-
-/**
- * Obtains the extension of Protobuf Gradle Plugin in the given project.
- */
-val Project.protobufExtension: ProtobufExtension?
- get() = extensions.findByType(ProtobufExtension::class.java)
-
-/**
- * Obtains the directory where the Protobuf Gradle Plugin should place the generated code.
- *
- * The directory is fixed to be `$buildDir/generated/source/proto` in versions pre v0.9.5
- * and cannot be changed by the settings of the plugin.
- * In the v0.9.5 the path was changed to
- * [`$buildDir/generated/sources/proto`](https://github.com/google/protobuf-gradle-plugin/releases/tag/v0.9.5).
- *
- * Even though [ProtobufExtension] has a property
- * [generatedFilesBaseDir][ProtobufExtension.getGeneratedFilesBaseDir], which is supposed
- * to be used for this purpose, it is declared with `@PackageScope` (again in earlier versions)
- * and thus cannot be accessed from outside the plugin.
- * The Protobuf Gradle Plugin (at v0.9.2) does not modify the value of the property either.
- * Therefore, we try getting the path using the newer version API and resort to the "legacy"
- * convention if the call fails.
- */
-val Project.generatedSourceProtoDir: Path
- get() {
- val legacyPath = layout.buildDirectory.dir("generated/source/proto").get().asFile.toPath()
- protobufExtension?.let {
- return try {
- it.generatedFilesBaseDir.let { Path(it) }
- } catch (_: Throwable) {
- // Probably we're running on an older version of the Protobuf Gradle Plugin
- // which has `package-access` for the `getGeneratedFilesDir()` method.
- legacyPath
- }
- }
- return legacyPath
- }
-
-/**
- * Ensures that the sources generated by Protobuf Gradle Plugin
- * are not included in the IDEA project.
- *
- * IDEA should only see the sources generated by ProtoData as
- * we define in [GenerateProtoTask.excludeProtocOutput].
- */
-@Suppress("unused")
-fun Project.configureIdea() {
-
- fun filterSources(sources: Set, excludeDir: File): Set =
- sources.filter { !it.residesIn(excludeDir) }.toSet()
-
- pluginManager.withPlugin("idea") {
- val idea = extensions.getByType()
- with(idea.module) {
- val protocOutput = file(generatedSourceProtoDir)
- val protocTargets = protocTargets()
- excludeWithNested(protocOutput.toPath(), protocTargets)
- sourceDirs = filterSources(sourceDirs, protocOutput)
- testSources.filter { !it.residesIn(protocOutput) }
- generatedSourceDirs = generatedDir.resolve(protocTargets)
- .map { it.toFile() }
- .toSet()
- }
- }
-}
-
-/**
- * Lists target directories for Protobuf code generation.
- *
- * The directory names are in the following format:
- *
- * `/`
- */
-private fun Project.protocTargets(): List {
- val protobufTasks = tasks.withType(GenerateProtoTask::class.java)
- val codegenTargets = sequence {
- protobufTasks.forEach { task ->
- val sourceSet = task.sourceSet.name
- val builtins = task.builtins.map { builtin -> builtin.name }
- val plugins = task.plugins.map { plugin -> plugin.name }
- val combined = builtins + plugins
- combined.forEach { subdir ->
- yield(Paths.get(sourceSet, subdir))
- }
- }
- }
- return codegenTargets.toList()
-}
-
-private fun Path.resolve(subdirs: Iterable): List =
- subdirs.map {
- resolve(it)
- }
-
-/**
- * Excludes the given directory and its subdirectories from
- * being seen as ones with the source code.
- *
- * The primary use of this extension is to exclude `build/generated/source/proto` and its
- * subdirectories to avoid duplication of types in the generated code with those in
- * produced by ProtoData under the `$projectDir/generated/` directory.
- */
-private fun IdeaModule.excludeWithNested(directory: Path, subdirs: Iterable) {
- excludeDirs.add(directory.toFile())
- directory.resolve(subdirs).forEach {
- excludeDirs.add(it.toFile())
- }
-}
-
-@Suppress("unused") // To be used when debugging build scripts.
-private fun printExcluded(dir: Any) {
- println(" [IDEA] Excluding directory: $dir")
-}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/JarDsl.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/JarDsl.kt
index 1371184..1bf0c0b 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/JarDsl.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/JarDsl.kt
@@ -26,37 +26,6 @@
package io.spine.gradle.publish
-/**
- * A DSL element of [SpinePublishing] extension which configures publishing of
- * [dokkaKotlinJar] artifact.
- *
- * This artifact contains Dokka-generated documentation. By default, it is not published.
- *
- * Take a look at the [SpinePublishing.dokkaJar] for a usage example.
- *
- * @see [artifacts]
- */
-class DokkaJar {
- /**
- * Enables publishing `JAR`s with Dokka-generated documentation for all published modules.
- */
- @Suppress("unused")
- @Deprecated("Please use `kotlin` and `java` flags instead.")
- var enabled = false
-
- /**
- * Controls whether [dokkaKotlinJar] artifact should be published.
- * The default value is `true`.
- */
- var kotlin = true
-
- /**
- * Controls whether [dokkaJavaJar] artifact should be published.
- * The default value is `false`.
- */
- var java = false
-}
-
/**
* A DSL element of [SpinePublishing] extension which allows enabling publishing
* of [testJar] artifact.
@@ -80,88 +49,25 @@ class TestJar {
var enabled = false
}
-/**
- * A DSL element of [SpinePublishing] extension which allows disabling publishing
- * of [protoJar] artifact.
- *
- * This artifact contains all the `.proto` definitions from `sourceSets.main.proto`. By default,
- * it is published.
- *
- * Take a look on [SpinePublishing.protoJar] for a usage example.
- *
- * @see [artifacts]
- */
-class ProtoJar {
-
- /**
- * Set of modules, for which a proto JAR will not be published.
- */
- var exclusions: Set = emptySet()
-
- /**
- * Disables proto JAR publishing for all published modules.
- */
- var disabled = false
-}
-
/**
* Flags for turning optional JAR artifacts in a project.
+ *
+ * @property sourcesJar Tells whether [sourcesJar] artifact should be published.
+ * Default value is `true`.
+ * @property publishTestJar Tells whether [testJar] artifact should be published.
*/
internal data class JarFlags(
-
- /**
- * Tells whether [sourcesJar] artifact should be published.
- *
- * Default value is `true`.
- */
val sourcesJar: Boolean = true,
-
- /**
- * Tells whether [javadocJar] artifact should be published.
- *
- * Default value is `true`.
- */
- val javadocJar: Boolean = true,
-
- /**
- * Tells whether [protoJar] artifact should be published.
- */
- val publishProtoJar: Boolean,
-
- /**
- * Tells whether [testJar] artifact should be published.
- */
val publishTestJar: Boolean,
-
- /**
- * Tells whether [dokkaKotlinJar] artifact should be published.
- */
- val publishDokkaKotlinJar: Boolean,
-
- /**
- * Tells whether [dokkaJavaJar] artifact should be published.
- */
- val publishDokkaJavaJar: Boolean
) {
internal companion object {
/**
* Creates an instance of [JarFlags] for the project with the given name,
* taking the setup parameters from JAR DSL elements.
*/
- fun create(
- projectName: String,
- protoJar: ProtoJar,
- testJar: TestJar,
- dokkaJar: DokkaJar
- ): JarFlags {
- val addProtoJar = (protoJar.exclusions.contains(projectName) || protoJar.disabled).not()
+ fun create(projectName: String, testJar: TestJar): JarFlags {
val addTestJar = testJar.inclusions.contains(projectName) || testJar.enabled
- return JarFlags(
- sourcesJar = true,
- javadocJar = true,
- addProtoJar, addTestJar,
- dokkaJar.kotlin, dokkaJar.java
- )
+ return JarFlags(sourcesJar = true, addTestJar)
}
}
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/ProtoExts.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/ProtoExts.kt
index 874b7f9..a32e969 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/ProtoExts.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/ProtoExts.kt
@@ -35,11 +35,15 @@ import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.tasks.bundling.Jar
/**
- * Tells whether there are any Proto sources in "main" source set.
+ * Tells whether there are any Proto sources in the "main" source set.
*/
-internal fun Project.hasProto(): Boolean {
+fun Project.hasProto(): Boolean {
val protoSources = protoSources()
- val result = protoSources.any { it.exists() }
+ val result = protoSources.any {
+ it.exists()
+ && it.isDirectory
+ && it.listFiles()?.isNotEmpty() ?: false
+ }
return result
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt
index 75c5413..8a212b7 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt
@@ -27,8 +27,10 @@
package io.spine.gradle.publish
import LicenseSettings
+import io.spine.gradle.artifactId
import io.spine.gradle.isSnapshot
import io.spine.gradle.repo.Repository
+import io.spine.gradle.report.pom.InceptionYear
import org.gradle.api.Project
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.invocation.BuildInvocationDetails
@@ -52,7 +54,7 @@ private const val MAVEN_PUBLISH = "maven-publish"
* the [`spinePublishing`][io.spine.gradle.publish.SpinePublishing.destinations]
* extension applied to the subproject.
*/
-internal sealed class PublicationHandler(
+sealed class PublicationHandler(
protected val project: Project,
protected var destinations: Set
) {
@@ -124,33 +126,42 @@ internal sealed class PublicationHandler(
}
/**
- * Copies the attributes of Gradle [Project] to this [MavenPublication].
+ * Copies the attributes of the [project] to this [MavenPublication].
*
* The following project attributes are copied:
* * [group][Project.getGroup];
* * [version][Project.getVersion];
* * [description][Project.getDescription].
*
- * Also, this function adds the [artifactPrefix][SpinePublishing.artifactPrefix] to
- * the [artifactId][MavenPublication.setArtifactId] of this publication,
- * if the prefix is not added yet.
+ * The [artifactId] of the publication is copied from the project
+ * [extension property][io.spine.gradle.artifactId] of the same name.
*
- * Finally, the Apache Software License 2.0 is set as the only license
- * under which the published artifact is distributed.
+ * The Apache Software License 2.0 is set as the only license
+ * under which the published artifact is distributed via [LicenseSettings]
+ *
+ * The source control management attributes are obtained from [DocumentationSettings].
+ *
+ * @see LicenseSettings
+ * @see DocumentationSettings
*/
protected fun MavenPublication.copyProjectAttributes() {
groupId = project.group.toString()
- val prefix = project.spinePublishing.artifactPrefix
- if (!artifactId.startsWith(prefix)) {
- artifactId = prefix + artifactId
- }
+ artifactId = project.artifactId
version = project.version.toString()
pom.description.set(project.description)
-
+ pom.inceptionYear.set(InceptionYear.value)
pom.licenses {
license {
name.set(LicenseSettings.name)
url.set(LicenseSettings.url)
+ distribution.set(LicenseSettings.url)
+ }
+ }
+ pom.scm {
+ DocumentationSettings.run {
+ url.set(repoUrl(project))
+ connection.set(connectionUrl(project))
+ developerConnection.set(developerConnectionUrl(project))
}
}
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt
index 0a24b56..efe51d6 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt
@@ -26,7 +26,7 @@
package io.spine.gradle.publish
-import dokkaKotlinJar
+import htmlDocsJar
import io.spine.gradle.isSnapshot
import io.spine.gradle.repo.Repository
import io.spine.gradle.sourceSets
@@ -36,6 +36,7 @@ import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.publish.PublicationContainer
import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar
@@ -231,7 +232,7 @@ fun TaskContainer.excludeGoogleProtoFromArtifacts() {
* Java and Kotlin sources are default to `main` source set since it is created by `java` plugin.
* For Proto sources to be included – [special treatment][protoSources] is needed.
*/
-internal fun Project.sourcesJar(): TaskProvider = tasks.getOrCreate("sourcesJar") {
+fun Project.sourcesJar(): TaskProvider = tasks.getOrCreate("sourcesJar") {
dependOnGenerateProto()
archiveClassifier.set("sources")
from(sourceSets["main"].allSource) // Puts Java and Kotlin sources.
@@ -245,7 +246,7 @@ internal fun Project.sourcesJar(): TaskProvider = tasks.getOrCreate("source
* The output of this task is a `jar` archive. The archive contains only
* [Proto sources][protoSources] from `main` source set.
*/
-internal fun Project.protoJar(): TaskProvider = tasks.getOrCreate("protoJar") {
+fun Project.protoJar(): TaskProvider = tasks.getOrCreate("protoJar") {
dependOnGenerateProto()
archiveClassifier.set("proto")
from(protoSources())
@@ -271,9 +272,9 @@ internal fun Project.testJar(): TaskProvider = tasks.getOrCreate("testJar")
*/
fun Project.javadocJar(): TaskProvider = tasks.getOrCreate("javadocJar") {
archiveClassifier.set("javadoc")
- val javadocFiles = layout.buildDirectory.files("/docs/javadoc")
+ val javadocFiles = layout.buildDirectory.dir("dokka/javadoc")
from(javadocFiles)
- dependsOn("javadoc")
+ dependsOn("dokkaGeneratePublicationJavadoc")
}
internal fun TaskContainer.getOrCreate(name: String, init: Jar.() -> Unit): TaskProvider =
@@ -300,12 +301,12 @@ internal fun Project.artifacts(jarFlags: JarFlags): Set> {
tasks.add(sourcesJar())
}
- if (jarFlags.javadocJar) {
- tasks.add(javadocJar())
- }
+ tasks.add(javadocJar())
+ tasks.add(htmlDocsJar())
+
// We don't want to have an empty "proto.jar" when a project doesn't have any Proto files.
- if (hasProto() && jarFlags.publishProtoJar) {
+ if (hasProto()) {
tasks.add(protoJar())
}
@@ -315,9 +316,22 @@ internal fun Project.artifacts(jarFlags: JarFlags): Set> {
tasks.add(testJar())
}
- if (jarFlags.publishDokkaKotlinJar) {
- tasks.add(dokkaKotlinJar())
- }
-
return tasks
}
+
+/**
+ * Adds the source code and documentation JARs to the publication.
+ */
+@Suppress("unused")
+fun MavenPublication.addSourceAndDocJars(project: Project) {
+ val tasks = mutableSetOf>()
+ tasks.add(project.sourcesJar())
+ tasks.add(project.javadocJar())
+ tasks.add(project.htmlDocsJar())
+ if (project.hasProto()) {
+ tasks.add(project.protoJar())
+ }
+ tasks.forEach {
+ artifact(it)
+ }
+}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/ShadowJarExts.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/ShadowJarExts.kt
index e2e67e0..87157fd 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/ShadowJarExts.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/ShadowJarExts.kt
@@ -33,7 +33,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
*/
fun ShadowJar.handleMergingServiceFiles() {
ServiceFiles.all.forEach {
- mergeServiceFiles(it)
+ append(it)
}
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/SpinePublishing.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/SpinePublishing.kt
index 9dc7d7c..c065198 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/SpinePublishing.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/SpinePublishing.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
package io.spine.gradle.publish
import io.spine.gradle.repo.Repository
+import java.util.Locale
import org.gradle.api.Project
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.kotlin.dsl.apply
@@ -129,29 +130,26 @@ import org.gradle.kotlin.dsl.findByType
* 1. [sourcesJar] — sources from the `main` source set. Includes handcrafted and generated
* code in Java, Kotlin, and `.proto` files.
*
- * 2. [protoJar] – only `.proto` sources from the `main` source set. It's published only if
- * Proto files are actually present in the source set. Publication of this artifact is optional
- * and can be disabled via [SpinePublishing.protoJar].
+ * 2. [protoJar] – only `.proto` sources from the `main` source set. It is published only if
+ * Proto files are actually present in the source set.
*
* 3. [javadocJar] — Javadoc, generated upon Java sources from the `main` source set.
* If Javadoc for Kotlin is also needed, apply the Dokka plugin.
* It tunes the `javadoc` task to generate docs upon Kotlin sources as well.
*
- * 4. [dokkaKotlinJar] — documentation generated by Dokka for Kotlin and Java sources
+ * 4. [htmlDocsJar] — documentation generated by Dokka for Kotlin and Java sources
* using the Kotlin API mode.
*
- * 5. [dokkaJavaJar] — documentation generated by Dokka for Kotlin and Java sources
- * using the Java API mode.
- *
* Additionally, [testJar] artifact can be published. This artifact contains compilation output
* of the `test` source set. Use [SpinePublishing.testJar] to enable its publishing.
*
* @see [artifacts]
* @see SpinePublishing
*/
-fun Project.spinePublishing(block: SpinePublishing.() -> Unit) {
+fun Project.spinePublishing(block: SpinePublishing.() -> Unit): SpinePublishing {
apply()
val name = SpinePublishing::class.java.simpleName
+ .replaceFirstChar { it.lowercase(Locale.getDefault()) }
val extension = with(extensions) {
findByType() ?: create(name, project)
}
@@ -159,6 +157,7 @@ fun Project.spinePublishing(block: SpinePublishing.() -> Unit) {
block()
configured()
}
+ return extension
}
/**
@@ -186,11 +185,15 @@ open class SpinePublishing(private val project: Project) {
* The default prefix added before a module name when publishing artifacts.
*/
const val DEFAULT_PREFIX = "spine-"
+
+ /**
+ * The reserved value that means that no prefix should be added
+ * to a tool module's artifact ID.
+ */
+ const val NONE_PREFIX = "NONE"
}
- private val protoJar = ProtoJar()
private val testJar = TestJar()
- private val dokkaJar = DokkaJar()
/**
* Set of modules to be published.
@@ -256,48 +259,22 @@ open class SpinePublishing(private val project: Project) {
lateinit var destinations: Set
/**
- * A prefix to be added before the name of each artifact.
+ * A prefix to be added before the name of each artifact, if it does not belong
+ * to the Maven group `"io.spine.tools"`.
+ *
+ * @see toolArtifactPrefix
*/
var artifactPrefix: String = DEFAULT_PREFIX
/**
- * Allows disabling publishing of [protoJar] artifact, containing all Proto sources
- * from `sourceSets.main.proto`.
- *
- * Here's an example of how to disable it for some of the published modules:
+ * A prefix to be added before a module name if it belongs to
+ * the Maven group `"io.spine.tools"`.
*
- * ```kotlin
- * spinePublishing {
- * modules = setOf(
- * "subprojectA",
- * "subprojectB",
- * )
- * protoJar {
- * exclusions = setOf(
- * "subprojectB",
- * )
- * }
- * }
- * ```
- *
- * For all modules, or when the extension is configured within a published module itself:
- *
- * ```
- * spinePublishing {
- * protoJar {
- * disabled = true
- * }
- * }
- * ```
- *
- * The resulting artifact is available under the "proto" classifier.
- * For example, in Gradle 7+, one could depend on it like this:
+ * Use `"NONE"` if you need no prefix before tool module names.
*
- * ```
- * implementation("io.spine:spine-client:$version@proto")
- * ```
+ * @see artifactPrefix
*/
- fun protoJar(block: ProtoJar.() -> Unit) = protoJar.run(block)
+ var toolArtifactPrefix: String = ""
/**
* Allows enabling publishing of [testJar] artifact, containing compilation output
@@ -338,34 +315,6 @@ open class SpinePublishing(private val project: Project) {
*/
fun testJar(block: TestJar.() -> Unit) = testJar.run(block)
- /**
- * Configures publishing of [dokkaKotlinJar] and [dokkaJavaJar] artifacts,
- * containing Dokka-generated documentation.
- *
- * By default, publishing of the [dokkaKotlinJar] artifact is enabled, and [dokkaJavaJar]
- * is disabled.
- *
- * Remember that the Dokka Gradle plugin should be applied to publish this artifact as it is
- * produced by the `dokkaHtml` task. It can be done by using the
- * [io.spine.dependency.build.Dokka] dependency object or by applying the
- * `buildSrc/src/main/kotlin/dokka-for-kotlin` or
- * `buildSrc/src/main/kotlin/dokka-for-java` script plugins.
- *
- * Here's an example of how to use this option:
- *
- * ```
- * spinePublishing {
- * dokkaJar {
- * kotlin = false
- * java = true
- * }
- * }
- * ```
- *
- * The resulting artifact is available under the "dokka" classifier.
- */
- fun dokkaJar(block: DokkaJar.() -> Unit) = dokkaJar.run(block)
-
/**
* Called to notify the extension that its configuration is completed.
*
@@ -373,14 +322,13 @@ open class SpinePublishing(private val project: Project) {
* `maven-publish` plugin for each published module.
*/
internal fun configured() {
- ensureProtoJarExclusionsArePublished()
ensureTestJarInclusionsArePublished()
ensureModulesNotDuplicated()
ensureCustomPublishingNotMisused()
val projectsToPublish = projectsToPublish()
projectsToPublish.forEach { project ->
- val jarFlags = JarFlags.create(project.name, protoJar, testJar, dokkaJar)
+ val jarFlags = JarFlags.create(project.name, testJar)
project.setUpPublishing(jarFlags)
}
}
@@ -463,29 +411,32 @@ open class SpinePublishing(private val project: Project) {
/**
* Obtains an artifact ID for the given project.
*
- * It consists of a project's name and [prefix][artifactPrefix]:
- * ``.
+ * @see artifactPrefix
+ * @see toolArtifactPrefix
*/
- fun artifactId(project: Project): String = "$artifactPrefix${project.name}"
-
- /**
- * Ensures that all modules, marked as excluded from [protoJar] publishing,
- * are actually published.
- *
- * It makes no sense to tell a module don't publish [protoJar] artifact, if the module is not
- * published at all.
- */
- private fun ensureProtoJarExclusionsArePublished() {
- val nonPublishedExclusions = protoJar.exclusions.minus(modules)
- if (nonPublishedExclusions.isNotEmpty()) {
- error(
- "One or more modules are marked as" +
- " `excluded from proto JAR publication`," +
- " but they are not even published: $nonPublishedExclusions."
- )
+ fun artifactId(project: Project): String {
+ val result = if (project.isTool) {
+ check(!toolArtifactPrefix.isEmpty()) {
+ "Artifact prefix cannot be empty for tool modules. " +
+ "Please set the `toolArtifactPrefix` property in `spinePublishing`. " +
+ "Use `\"NONE\"` to have an empty prefix for tool modules."
+ }
+ val prefix =
+ if (toolArtifactPrefix == NONE_PREFIX) {
+ ""
+ } else {
+ toolArtifactPrefix
+ }
+ "$prefix${project.name}"
+ } else {
+ "$artifactPrefix${project.name}"
}
+ return result
}
+ private val Project.isTool: Boolean
+ get() = group == "io.spine.tools"
+
/**
* Ensures that all modules, marked as included into [testJar] publishing,
* are actually published.
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/publish/StandardJavaPublicationHandler.kt b/buildSrc/src/main/kotlin/io/spine/gradle/publish/StandardJavaPublicationHandler.kt
index 06d78c1..17648f8 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/publish/StandardJavaPublicationHandler.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/publish/StandardJavaPublicationHandler.kt
@@ -57,7 +57,7 @@ import org.gradle.kotlin.dsl.create
* The Maven Publish Plugin | Publications
* @see CustomPublicationHandler
*/
-internal class StandardJavaPublicationHandler private constructor(
+class StandardJavaPublicationHandler private constructor(
project: Project,
private val jarFlags: JarFlags,
destinations: Set,
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/repo/RepoSlug.kt b/buildSrc/src/main/kotlin/io/spine/gradle/repo/RepoSlug.kt
index 461c690..d4a6bfd 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/repo/RepoSlug.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/repo/RepoSlug.kt
@@ -50,7 +50,7 @@ class RepoSlug(val value: String) {
fun fromVar(): RepoSlug {
val envValue = System.getenv(environmentVariable)
if (envValue.isNullOrEmpty()) {
- throw GradleException("`REPO_SLUG` environment variable is not set.")
+ throw GradleException("`$environmentVariable` environment variable is not set.")
}
return RepoSlug(envValue)
}
@@ -62,6 +62,6 @@ class RepoSlug(val value: String) {
* Returns the GitHub URL to the project repository.
*/
fun gitHost(): String {
- return "git@github.com-publish:${value}.git"
+ return "git@github-publish:${value}.git"
}
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/repo/Repositories.kt b/buildSrc/src/main/kotlin/io/spine/gradle/repo/Repositories.kt
index 43abe47..e6c3f67 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/repo/Repositories.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/repo/Repositories.kt
@@ -99,6 +99,15 @@ val RepositoryHandler.intellijReleases: MavenArtifactRepository
val RepositoryHandler.jetBrainsCacheRedirector: MavenArtifactRepository
get() = maven("https://cache-redirector.jetbrains.com/intellij-dependencies")
+val RepositoryHandler.intellijDependencies: MavenArtifactRepository
+ get() = maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") {
+ content {
+ includeGroupByRegex("com\\.jetbrains.*")
+ includeGroupByRegex("org\\.jetbrains.*")
+ includeGroupByRegex("com\\.intellij.*")
+ }
+ }
+
/**
* Applies repositories commonly used by Spine Event Engine projects.
*/
@@ -124,6 +133,7 @@ fun RepositoryHandler.standardToSpineSdk() {
intellijReleases
jetBrainsCacheRedirector
+ intellijDependencies
maven {
url = URI(Repos.sonatypeSnapshots)
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/report/license/LicenseReporter.kt b/buildSrc/src/main/kotlin/io/spine/gradle/report/license/LicenseReporter.kt
index ec86eb5..5f18b95 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/report/license/LicenseReporter.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/report/license/LicenseReporter.kt
@@ -151,11 +151,18 @@ object LicenseReporter {
sourceProjects: Iterable,
rootProject: Project
) {
- val paths = sourceProjects.map {
- val buildDir = it.layout.buildDirectory.asFile.get()
- "$buildDir/${Paths.relativePath}/${Paths.outputFilename}"
- }
- println("Merging the license reports from the all projects.")
+ val paths = sourceProjects
+ .map {
+ val buildDir = it.layout.buildDirectory.asFile.get()
+ "$buildDir/${Paths.relativePath}/${Paths.outputFilename}"
+ }.filter {
+ val exists = File(it).exists()
+ if (!exists) {
+ rootProject.logger.debug("License report file not found: $it")
+ }
+ exists
+ }
+ println("Merging the license reports from all projects.")
val mergedContent = paths.joinToString("\n\n\n") { (File(it)).readText() }
val output = File("${rootProject.rootDir}/${Paths.outputFilename}")
output.writeText(mergedContent)
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/report/pom/InceptionYear.kt b/buildSrc/src/main/kotlin/io/spine/gradle/report/pom/InceptionYear.kt
index cb25b3d..ed94b29 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/report/pom/InceptionYear.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/report/pom/InceptionYear.kt
@@ -35,7 +35,10 @@ import org.gradle.kotlin.dsl.withGroovyBuilder
*/
internal object InceptionYear {
- private const val SPINE_INCEPTION_YEAR = "2015"
+ /**
+ * The year of the inception of Spine.
+ */
+ const val value = "2015"
/**
* Returns a string containing the inception year of Spine in a `pom.xml` format.
@@ -44,7 +47,7 @@ internal object InceptionYear {
val writer = StringWriter()
val xml = MarkupBuilder(writer)
xml.withGroovyBuilder {
- "inceptionYear" { xml.text(SPINE_INCEPTION_YEAR) }
+ "inceptionYear" { xml.text(value) }
}
return writer.toString()
}
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt b/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
index 6fb7eab..75af960 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
@@ -28,9 +28,9 @@ package io.spine.gradle.testing
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.TestDescriptor
+import org.gradle.api.tasks.testing.TestListener
import org.gradle.api.tasks.testing.TestResult
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
-import org.gradle.kotlin.dsl.KotlinClosure2
/**
* Configures logging of this [Test] task.
@@ -70,19 +70,16 @@ fun Test.configureLogging() {
>> $skippedTestCount skipped
"""
- afterSuite(
-
- // `GroovyInteroperability` is employed as `afterSuite()` has no equivalent in Kotlin DSL.
- // See issue: https://github.com/gradle/gradle/issues/5431
-
- KotlinClosure2({ descriptor, result ->
+ val listener = object : TestListener {
+ override fun afterSuite(descriptor: TestDescriptor, result: TestResult) {
// If the descriptor has no parent, then it is the root test suite,
// i.e. it includes the info about all the run tests.
-
if (descriptor.parent == null) {
logger.lifecycle(result.summary())
}
- })
- )
+ }
+ }
+
+ addTestListener(listener)
}
diff --git a/buildSrc/src/main/kotlin/jvm-module.gradle.kts b/buildSrc/src/main/kotlin/jvm-module.gradle.kts
index 7bc595c..11696c1 100644
--- a/buildSrc/src/main/kotlin/jvm-module.gradle.kts
+++ b/buildSrc/src/main/kotlin/jvm-module.gradle.kts
@@ -46,10 +46,9 @@ plugins {
id("net.ltgt.errorprone")
id("pmd-settings")
id("project-report")
- id("dokka-for-java")
kotlin("jvm")
id("detekt-code-analysis")
- id("dokka-for-kotlin")
+ id("dokka-setup")
id("org.jetbrains.kotlinx.kover")
id("module-testing")
}
@@ -160,9 +159,7 @@ fun Module.setTaskDependencies(generatedDir: String) {
}
fun Module.configureGitHubPages() {
- val docletVersion = project.version.toString()
- updateGitHubPages(docletVersion) {
- allowInternalJavadoc.set(true)
+ updateGitHubPages {
rootFolder.set(rootDir)
}
}
diff --git a/buildSrc/src/main/kotlin/kmp-module.gradle.kts b/buildSrc/src/main/kotlin/kmp-module.gradle.kts
index 7577ed5..4f7ec63 100644
--- a/buildSrc/src/main/kotlin/kmp-module.gradle.kts
+++ b/buildSrc/src/main/kotlin/kmp-module.gradle.kts
@@ -69,7 +69,6 @@ val about = ""
plugins {
kotlin("multiplatform")
id("detekt-code-analysis")
- id("io.kotest.multiplatform")
id("org.jetbrains.kotlinx.kover")
`project-report`
}
diff --git a/buildSrc/src/main/kotlin/kmp-publish.gradle.kts b/buildSrc/src/main/kotlin/kmp-publish.gradle.kts
index 53b0a21..e4c3aa1 100644
--- a/buildSrc/src/main/kotlin/kmp-publish.gradle.kts
+++ b/buildSrc/src/main/kotlin/kmp-publish.gradle.kts
@@ -59,17 +59,17 @@ val about = ""
plugins {
`maven-publish`
- id("dokka-for-kotlin")
+ id("dokka-setup")
}
publishing.publications {
named("kotlinMultiplatform") {
// Although, the "common artifact" can't be used independently
// of target artifacts, it is published with documentation.
- artifact(project.dokkaKotlinJar())
+ artifact(project.htmlDocsJar())
}
named("jvm") {
// Includes Kotlin (JVM + common) and Java documentation.
- artifact(project.dokkaKotlinJar())
+ artifact(project.htmlDocsJar())
}
}
diff --git a/buildSrc/src/main/kotlin/module.gradle.kts b/buildSrc/src/main/kotlin/module.gradle.kts
index c5db1f9..209b0c5 100644
--- a/buildSrc/src/main/kotlin/module.gradle.kts
+++ b/buildSrc/src/main/kotlin/module.gradle.kts
@@ -48,10 +48,8 @@ plugins {
id("net.ltgt.errorprone")
id("pmd-settings")
id("project-report")
- id("dokka-for-java")
kotlin("jvm")
id("detekt-code-analysis")
- id("dokka-for-kotlin")
id("org.jetbrains.kotlinx.kover")
id("module-testing")
}
@@ -165,8 +163,7 @@ fun Module.setTaskDependencies(generatedDir: String) {
fun Module.configureGitHubPages() {
val docletVersion = project.version.toString()
- updateGitHubPages(docletVersion) {
- allowInternalJavadoc.set(true)
+ updateGitHubPages {
rootFolder.set(rootDir)
}
}
diff --git a/buildSrc/src/main/kotlin/test-module.gradle.kts b/buildSrc/src/main/kotlin/test-module.gradle.kts
index 23aa4a2..d64de09 100644
--- a/buildSrc/src/main/kotlin/test-module.gradle.kts
+++ b/buildSrc/src/main/kotlin/test-module.gradle.kts
@@ -26,11 +26,14 @@
import io.spine.dependency.local.Base
import io.spine.dependency.local.Validation
+import io.spine.gradle.report.license.LicenseReporter
plugins {
java
`java-test-fixtures`
+ id("module-testing")
}
+LicenseReporter.generateReportIn(project)
dependencies {
arrayOf(
diff --git a/buildSrc/src/main/kotlin/uber-jar-module.gradle.kts b/buildSrc/src/main/kotlin/uber-jar-module.gradle.kts
index 29dba3c..f3dda52 100644
--- a/buildSrc/src/main/kotlin/uber-jar-module.gradle.kts
+++ b/buildSrc/src/main/kotlin/uber-jar-module.gradle.kts
@@ -33,7 +33,7 @@ import io.spine.gradle.publish.spinePublishing
import io.spine.gradle.report.license.LicenseReporter
plugins {
- `java-library`
+ id("module")
`maven-publish`
id("com.gradleup.shadow")
id("write-manifest")
diff --git a/buildSrc/src/test/kotlin/io/spine/gradle/docs/UpdatePluginVersionTest.kt b/buildSrc/src/test/kotlin/io/spine/gradle/docs/UpdatePluginVersionTest.kt
new file mode 100644
index 0000000..1674b3d
--- /dev/null
+++ b/buildSrc/src/test/kotlin/io/spine/gradle/docs/UpdatePluginVersionTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2026, TeamDev. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and/or binary forms, with or without
+ * modification, must retain the above copyright notice and the following
+ * disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.spine.gradle.docs
+
+import io.kotest.matchers.string.shouldContain
+import java.io.File
+import org.gradle.testfixtures.ProjectBuilder
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.DisplayName
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.io.TempDir
+
+@DisplayName("`UpdatePluginVersion` should")
+class UpdatePluginVersionTest {
+
+ @TempDir
+ lateinit var tempDir: File
+
+ private lateinit var buildFile: File
+
+ @BeforeEach
+ fun setUp() {
+ val subDir = File(tempDir, "subproject")
+ subDir.mkdir()
+ buildFile = File(subDir, "build.gradle.kts")
+ buildFile.writeText("""
+ plugins {
+ id("io.spine.validation") version "1.0.0"
+ id("other-plugin") version "0.1.0"
+ }
+ """.trimIndent())
+ }
+
+ @Test
+ fun `update plugin version in build file`() {
+ val project = ProjectBuilder.builder().build()
+ val task = project.tasks.register("updatePluginVersion", UpdatePluginVersion::class.java) {
+ directory.set(tempDir)
+ version.set("2.0.0-TEST")
+ pluginId.set("io.spine.validation")
+ }
+ task.get().update()
+
+ val updatedContent = buildFile.readText()
+ updatedContent shouldContain """id("io.spine.validation") version "2.0.0-TEST""""
+ updatedContent shouldContain """id("other-plugin") version "0.1.0""""
+ }
+
+ @Test
+ fun `update 'kotlin' plugin version when 'kotlinVersion' is set`() {
+ // Overwrite with a file that uses kotlin("jvm") syntax
+ buildFile.writeText(
+ """
+ plugins {
+ kotlin("jvm") version "1.9.10"
+ id("io.spine.validation") version "1.0.0"
+ }
+ """.trimIndent()
+ )
+
+ val project = ProjectBuilder.builder().build()
+ val task = project.tasks.register("updatePluginVersion", UpdatePluginVersion::class.java) {
+ directory.set(tempDir)
+ version.set("2.0.0-TEST")
+ pluginId.set("io.spine.validation")
+ kotlinVersion.set("2.2.21")
+ }
+ task.get().update()
+
+ val updatedContent = buildFile.readText()
+ updatedContent shouldContain """kotlin("jvm") version "2.2.21""""
+ updatedContent shouldContain """id("io.spine.validation") version "2.0.0-TEST""""
+ }
+
+ @Test
+ fun `handle multiple spaces between id and version`() {
+ buildFile.writeText("""
+ plugins {
+ id("io.spine.validation") version "1.0.0"
+ }
+ """.trimIndent())
+
+ val project = ProjectBuilder.builder().build()
+ val task = project.tasks.register("updatePluginVersion", UpdatePluginVersion::class.java) {
+ directory.set(tempDir)
+ version.set("2.0.0-TEST")
+ pluginId.set("io.spine.validation")
+ }
+
+ task.get().update()
+
+ val updatedContent = buildFile.readText()
+ updatedContent shouldContain """id("io.spine.validation") version "2.0.0-TEST""""
+ }
+}
diff --git a/buildSrc/src/test/kotlin/io/spine/gradle/publish/SpinePublishingTest.kt b/buildSrc/src/test/kotlin/io/spine/gradle/publish/SpinePublishingTest.kt
new file mode 100644
index 0000000..37f58e0
--- /dev/null
+++ b/buildSrc/src/test/kotlin/io/spine/gradle/publish/SpinePublishingTest.kt
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2026, TeamDev. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and/or binary forms, with or without
+ * modification, must retain the above copyright notice and the following
+ * disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.spine.gradle.publish
+
+import io.kotest.assertions.throwables.shouldThrow
+import io.kotest.matchers.collections.shouldContain
+import io.kotest.matchers.collections.shouldHaveSize
+import io.kotest.matchers.shouldBe
+import io.kotest.matchers.string.shouldContain
+import io.spine.gradle.repo.Repository
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.create
+import org.gradle.testfixtures.ProjectBuilder
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.DisplayName
+import org.junit.jupiter.api.Nested
+import org.junit.jupiter.api.Test
+
+@DisplayName("`SpinePublishing` should")
+class SpinePublishingTest {
+
+ private lateinit var project: Project
+ private lateinit var extension: SpinePublishing
+
+ @BeforeEach
+ fun setUp() {
+ project = ProjectBuilder.builder().build()
+ extension = project.spinePublishing { }
+ }
+
+ @Nested
+ inner class `calculate 'artifactId'` {
+
+ @Test
+ fun `with default prefix for non-tool projects`() {
+ val subproject = ProjectBuilder.builder()
+ .withParent(project)
+ .withName("base")
+ .build()
+ subproject.group = "io.spine"
+
+ extension.artifactId(subproject) shouldBe "spine-base"
+ }
+
+ @Test
+ fun `with custom prefix for non-tool projects`() {
+ extension.artifactPrefix = "custom-"
+ val subproject = ProjectBuilder.builder()
+ .withParent(project)
+ .withName("core")
+ .build()
+ subproject.group = "io.spine"
+
+ extension.artifactId(subproject) shouldBe "custom-core"
+ }
+
+ @Test
+ fun `with tool prefix for tool projects`() {
+ extension.toolArtifactPrefix = "tool-"
+ val toolProject = ProjectBuilder.builder()
+ .withParent(project)
+ .withName("model-compiler")
+ .build()
+ toolProject.group = "io.spine.tools"
+
+ extension.artifactId(toolProject) shouldBe "tool-model-compiler"
+ }
+
+ @Test
+ fun `without prefix for tool projects if 'NONE' is specified`() {
+ extension.toolArtifactPrefix = "NONE"
+ val toolProject = ProjectBuilder.builder()
+ .withParent(project)
+ .withName("proto-js")
+ .build()
+ toolProject.group = "io.spine.tools"
+
+ extension.artifactId(toolProject) shouldBe "proto-js"
+ }
+
+ @Test
+ fun `throwing IllegalStateException if tool prefix is empty for tool projects`() {
+ extension.toolArtifactPrefix = ""
+ val toolProject = ProjectBuilder.builder()
+ .withParent(project)
+ .withName("tool")
+ .build()
+ toolProject.group = "io.spine.tools"
+
+ shouldThrow {
+ extension.artifactId(toolProject)
+ }
+ }
+ }
+
+ @Nested
+ inner class `validate configuration` {
+
+ @Test
+ fun `ensuring 'testJar' inclusions are published`() {
+ extension.modules = setOf("pub-module")
+ extension.testJar {
+ inclusions = setOf("non-pub-module")
+ }
+
+ val exception = shouldThrow {
+ extension.configured()
+ }
+ exception.message!! shouldContain "non-pub-module"
+ }
+
+ @Test
+ fun `ensuring 'customPublishing' is not misused with modules`() {
+ extension.modules = setOf("some-module")
+ extension.customPublishing = true
+
+ val exception = shouldThrow {
+ extension.configured()
+ }
+ exception.message!! shouldContain "customPublishing"
+ }
+
+ @Test
+ fun `ensuring modules are not duplicated in root and subproject`() {
+ val rootProject = project
+ val subproject = ProjectBuilder.builder()
+ .withParent(rootProject)
+ .withName("sub")
+ .build()
+
+ // Root project already has the 'spinePublishing' extension created in 'setUp'.
+ // Let's use it instead of creating a second one with a different name.
+ extension.modules = setOf("sub")
+
+ // Subproject's extension must be named 'SpinePublishing'
+ // to be found by SpinePublishing::class.java.simpleName
+ val extensionName = SpinePublishing::class.java.simpleName
+ val subExtension = subproject.extensions.create(extensionName, subproject)
+
+ val exception = shouldThrow {
+ subExtension.configured()
+ }
+ exception.message!! shouldContain "already configured in a root project"
+ }
+ }
+
+ @Nested
+ inner class `identify 'projectsToPublish'` {
+
+ @Test
+ fun `as the project itself if no modules are specified`() {
+ val projects = extension.invokeProjectsToPublish()
+ projects shouldHaveSize 1
+ projects shouldContain project
+ }
+
+ @Test
+ fun `as the specified modules`() {
+ val sub1 = ProjectBuilder.builder().withParent(project).withName("sub1").build()
+ val sub2 = ProjectBuilder.builder().withParent(project).withName("sub2").build()
+
+ extension.modules = setOf("sub1", "sub2")
+
+ val projects = extension.invokeProjectsToPublish()
+ projects shouldHaveSize 2
+ projects shouldContain sub1
+ projects shouldContain sub2
+ }
+
+ @Test
+ fun `including modules with custom publishing`() {
+ val sub1 = ProjectBuilder.builder().withParent(project).withName("sub1").build()
+ val sub2 = ProjectBuilder.builder().withParent(project).withName("sub2").build()
+
+ extension.modules = setOf("sub1")
+ extension.modulesWithCustomPublishing = setOf("sub2")
+
+ val projects = extension.invokeProjectsToPublish()
+ projects shouldHaveSize 2
+ projects shouldContain sub1
+ projects shouldContain sub2
+ }
+ }
+
+ @Nested
+ inner class `resolve 'publishTo' repositories` {
+
+ @Test
+ fun `from the extension itself if destinations are initialized`() {
+ val repo = Repository(
+ "test-repo",
+ "https://example.com/release",
+ "https://example.com/snapshot"
+ )
+ extension.destinations = setOf(repo)
+
+ val repos = project.invokePublishTo(extension)
+ repos shouldHaveSize 1
+ repos shouldContain repo
+ }
+
+ @Test
+ fun `from the parent project if not specified locally`() {
+ val repo = Repository(
+ "parent-repo",
+ "https://example.com/release",
+ "https://example.com/snapshot"
+ )
+ // Root project has its extension named 'spinePublishing' from setUp.
+ extension.destinations = setOf(repo)
+
+ val subproject = ProjectBuilder.builder().withParent(project).withName("sub").build()
+ // Subproject has no local 'spinePublishing' extension.
+
+ val repos = subproject.invokePublishTo(extension)
+ repos shouldHaveSize 1
+ repos shouldContain repo
+ }
+ }
+}
+
+/**
+ * Accesses private/internal methods of [SpinePublishing] for testing purposes.
+ */
+private fun SpinePublishing.invokeProjectsToPublish(): Collection {
+ val method = SpinePublishing::class.java.getDeclaredMethod("projectsToPublish")
+ method.isAccessible = true
+ @Suppress("UNCHECKED_CAST")
+ return method.invoke(this) as Collection
+}
+
+private fun Project.invokePublishTo(extension: SpinePublishing): Set {
+ val method = SpinePublishing::class.java.getDeclaredMethod("publishTo", Project::class.java)
+ method.isAccessible = true
+ @Suppress("UNCHECKED_CAST")
+ return method.invoke(extension, this) as Set
+}
diff --git a/config b/config
index c2504f2..4a3b103 160000
--- a/config
+++ b/config
@@ -1 +1 @@
-Subproject commit c2504f24673ac232481a8b59352707d0443b0efd
+Subproject commit 4a3b103fb0579d6fe6addd9acd4f241de26bb967
diff --git a/dependencies.md b/dependencies.md
index 4104a49..4a81ba5 100644
--- a/dependencies.md
+++ b/dependencies.md
@@ -1,6 +1,6 @@
-# Dependencies of `io.spine.tools:spine-testlib:2.0.0-SNAPSHOT.211`
+# Dependencies of `io.spine.tools:base-testlib:2.0.0-SNAPSHOT.212`
## Runtime
1. **Group** : com.google.auto.value. **Name** : auto-value-annotations. **Version** : 1.10.2.
@@ -31,11 +31,11 @@
* **Project URL:** [https://github.com/google/guava/](https://github.com/google/guava/)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.guava. **Name** : guava. **Version** : 33.4.8-jre.
+1. **Group** : com.google.guava. **Name** : guava. **Version** : 33.5.0-jre.
* **Project URL:** [https://github.com/google/guava](https://github.com/google/guava)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.guava. **Name** : guava-testlib. **Version** : 33.4.8-jre.
+1. **Group** : com.google.guava. **Name** : guava-testlib. **Version** : 33.5.0-jre.
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
1. **Group** : com.google.guava. **Name** : listenablefuture. **Version** : 9999.0-empty-to-avoid-conflict-with-guava.
@@ -45,15 +45,15 @@
* **Project URL:** [https://github.com/google/j2objc/](https://github.com/google/j2objc/)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.protobuf. **Name** : protobuf-java. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-java. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
-1. **Group** : com.google.protobuf. **Name** : protobuf-java-util. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-java-util. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
-1. **Group** : com.google.protobuf. **Name** : protobuf-kotlin. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-kotlin. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
@@ -72,27 +72,27 @@
1. **Group** : io.github.java-diff-utils. **Name** : java-diff-utils. **Version** : 4.12.
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : io.kotest. **Name** : kotest-assertions-core. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-core. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-core-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-core-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-shared. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-shared. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-shared-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-shared-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-common. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-common. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-common-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-common-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
@@ -117,15 +117,15 @@
* **Project URL:** [https://github.com/JetBrains/java-annotations](https://github.com/JetBrains/java-annotations)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-bom. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-bom. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-reflect. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-reflect. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -173,15 +173,15 @@
* **Project URL:** [http://jspecify.org/](http://jspecify.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.junit. **Name** : junit-bom. **Version** : 5.13.2.
+1. **Group** : org.junit. **Name** : junit-bom. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-api. **Version** : 5.13.2.
+1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-api. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.platform. **Name** : junit-platform-commons. **Version** : 1.13.2.
+1. **Group** : org.junit.platform. **Name** : junit-platform-commons. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
@@ -195,49 +195,40 @@
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
## Compile, tests, and tooling
-1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.12.7.
+1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.15.3.
* **Project URL:** [https://github.com/FasterXML/jackson-bom](https://github.com/FasterXML/jackson-bom)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-annotations. **Version** : 2.12.7.
- * **Project URL:** [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
- * **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-annotations. **Version** : 2.15.3.
+ * **Project URL:** [https://github.com/FasterXML/jackson](https://github.com/FasterXML/jackson)
+ * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-core. **Version** : 2.12.7.
+1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-core. **Version** : 2.15.3.
* **Project URL:** [https://github.com/FasterXML/jackson-core](https://github.com/FasterXML/jackson-core)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
- * **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+ * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-databind. **Version** : 2.12.7.1.
- * **Project URL:** [http://github.com/FasterXML/jackson](http://github.com/FasterXML/jackson)
+1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-databind. **Version** : 2.15.3.
+ * **Project URL:** [https://github.com/FasterXML/jackson](https://github.com/FasterXML/jackson)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
- * **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+ * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.jackson.dataformat. **Name** : jackson-dataformat-xml. **Version** : 2.12.7.
+1. **Group** : com.fasterxml.jackson.dataformat. **Name** : jackson-dataformat-xml. **Version** : 2.15.3.
* **Project URL:** [https://github.com/FasterXML/jackson-dataformat-xml](https://github.com/FasterXML/jackson-dataformat-xml)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.jackson.module. **Name** : jackson-module-jaxb-annotations. **Version** : 2.12.7.
- * **Project URL:** [https://github.com/FasterXML/jackson-modules-base](https://github.com/FasterXML/jackson-modules-base)
- * **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
- * **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-1. **Group** : com.fasterxml.jackson.module. **Name** : jackson-module-kotlin. **Version** : 2.12.7.
+1. **Group** : com.fasterxml.jackson.module. **Name** : jackson-module-kotlin. **Version** : 2.15.3.
* **Project URL:** [https://github.com/FasterXML/jackson-module-kotlin](https://github.com/FasterXML/jackson-module-kotlin)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
- * **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+ * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.fasterxml.woodstox. **Name** : woodstox-core. **Version** : 6.2.4.
+1. **Group** : com.fasterxml.woodstox. **Name** : woodstox-core. **Version** : 6.5.1.
* **Project URL:** [https://github.com/FasterXML/woodstox](https://github.com/FasterXML/woodstox)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.github.ben-manes.caffeine. **Name** : caffeine. **Version** : 2.9.3.
- * **Project URL:** [https://github.com/ben-manes/caffeine](https://github.com/ben-manes/caffeine)
- * **License:** [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-
1. **Group** : com.github.ben-manes.caffeine. **Name** : caffeine. **Version** : 3.0.5.
* **Project URL:** [https://github.com/ben-manes/caffeine](https://github.com/ben-manes/caffeine)
* **License:** [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -309,11 +300,11 @@
* **Project URL:** [https://github.com/google/guava/](https://github.com/google/guava/)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.guava. **Name** : guava. **Version** : 33.4.8-jre.
+1. **Group** : com.google.guava. **Name** : guava. **Version** : 33.5.0-jre.
* **Project URL:** [https://github.com/google/guava](https://github.com/google/guava)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.guava. **Name** : guava-testlib. **Version** : 33.4.8-jre.
+1. **Group** : com.google.guava. **Name** : guava-testlib. **Version** : 33.5.0-jre.
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
1. **Group** : com.google.guava. **Name** : listenablefuture. **Version** : 9999.0-empty-to-avoid-conflict-with-guava.
@@ -323,19 +314,19 @@
* **Project URL:** [https://github.com/google/j2objc/](https://github.com/google/j2objc/)
* **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : com.google.protobuf. **Name** : protobuf-java. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-java. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
-1. **Group** : com.google.protobuf. **Name** : protobuf-java-util. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-java-util. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
-1. **Group** : com.google.protobuf. **Name** : protobuf-kotlin. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protobuf-kotlin. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
-1. **Group** : com.google.protobuf. **Name** : protoc. **Version** : 4.31.1.
+1. **Group** : com.google.protobuf. **Name** : protoc. **Version** : 4.34.1.
* **Project URL:** [https://developers.google.com/protocol-buffers/](https://developers.google.com/protocol-buffers/)
* **License:** [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -356,6 +347,10 @@
* **Project URL:** [https://checkstyle.org/](https://checkstyle.org/)
* **License:** [LGPL-2.1+](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt)
+1. **Group** : com.soywiz.korlibs.korte. **Name** : korte-jvm. **Version** : 4.0.10.
+ * **Project URL:** [https://github.com/korlibs/korge-next](https://github.com/korlibs/korge-next)
+ * **License:** [MIT](https://raw.githubusercontent.com/korlibs/korge-next/master/korge/LICENSE.txt)
+
1. **Group** : commons-beanutils. **Name** : commons-beanutils. **Version** : 1.9.4.
* **Project URL:** [https://commons.apache.org/proper/commons-beanutils/](https://commons.apache.org/proper/commons-beanutils/)
* **License:** [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -491,50 +486,30 @@
* **Project URL:** [https://detekt.dev](https://detekt.dev)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : io.kotest. **Name** : kotest-assertions-core. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-core. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-core-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-core-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-shared. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-shared. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-assertions-shared-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-assertions-shared-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-common. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-common. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.kotest. **Name** : kotest-common-jvm. **Version** : 6.0.3.
+1. **Group** : io.kotest. **Name** : kotest-common-jvm. **Version** : 6.1.11.
* **Project URL:** [https://github.com/kotest/kotest](https://github.com/kotest/kotest)
* **License:** [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
-1. **Group** : io.opentelemetry. **Name** : opentelemetry-api. **Version** : 1.41.0.
- * **Project URL:** [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
- * **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-1. **Group** : io.opentelemetry. **Name** : opentelemetry-context. **Version** : 1.41.0.
- * **Project URL:** [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java)
- * **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-1. **Group** : jakarta.activation. **Name** : jakarta.activation-api. **Version** : 1.2.1.
- * **Project URL:** [https://www.eclipse.org](https://www.eclipse.org)
- * **License:** [EDL 1.0](http://www.eclipse.org/org/documents/edl-v10.php)
- * **License:** [Eclipse Public License v. 2.0](https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt)
- * **License:** [GNU General Public License, version 2 with the GNU Classpath Exception](https://www.gnu.org/software/classpath/license.html)
-
-1. **Group** : jakarta.xml.bind. **Name** : jakarta.xml.bind-api. **Version** : 2.3.2.
- * **Project URL:** [https://www.eclipse.org](https://www.eclipse.org)
- * **License:** [Eclipse Distribution License - v 1.0](http://www.eclipse.org/org/documents/edl-v10.php)
- * **License:** [Eclipse Public License v. 2.0](https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt)
- * **License:** [GNU General Public License, version 2 with the GNU Classpath Exception](https://www.gnu.org/software/classpath/license.html)
-
1. **Group** : javax.inject. **Name** : javax.inject. **Version** : 1.
* **Project URL:** [http://code.google.com/p/atinject/](http://code.google.com/p/atinject/)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -593,23 +568,6 @@
* **Project URL:** [https://github.com/apiguardian-team/apiguardian](https://github.com/apiguardian-team/apiguardian)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.bouncycastle. **Name** : bcpg-jdk18on. **Version** : 1.80.
- * **Project URL:** [https://www.bouncycastle.org/download/bouncy-castle-java/](https://www.bouncycastle.org/download/bouncy-castle-java/)
- * **License:** [Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
- * **License:** [Bouncy Castle Licence](https://www.bouncycastle.org/licence.html)
-
-1. **Group** : org.bouncycastle. **Name** : bcpkix-jdk18on. **Version** : 1.80.
- * **Project URL:** [https://www.bouncycastle.org/download/bouncy-castle-java/](https://www.bouncycastle.org/download/bouncy-castle-java/)
- * **License:** [Bouncy Castle Licence](https://www.bouncycastle.org/licence.html)
-
-1. **Group** : org.bouncycastle. **Name** : bcprov-jdk18on. **Version** : 1.80.
- * **Project URL:** [https://www.bouncycastle.org/download/bouncy-castle-java/](https://www.bouncycastle.org/download/bouncy-castle-java/)
- * **License:** [Bouncy Castle Licence](https://www.bouncycastle.org/licence.html)
-
-1. **Group** : org.bouncycastle. **Name** : bcutil-jdk18on. **Version** : 1.80.
- * **Project URL:** [https://www.bouncycastle.org/download/bouncy-castle-java/](https://www.bouncycastle.org/download/bouncy-castle-java/)
- * **License:** [Bouncy Castle Licence](https://www.bouncycastle.org/licence.html)
-
1. **Group** : org.checkerframework. **Name** : checker-compat-qual. **Version** : 2.5.3.
* **Project URL:** [https://checkerframework.org](https://checkerframework.org)
* **License:** [GNU General Public License, version 2 (GPL2), with the classpath exception](http://www.gnu.org/software/classpath/license.html)
@@ -667,27 +625,31 @@
* **Project URL:** [https://github.com/JetBrains/markdown](https://github.com/JetBrains/markdown)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : analysis-kotlin-descriptors. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : analysis-kotlin-symbols. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : analysis-markdown. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : analysis-markdown. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : dokka-base. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : dokka-base. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : dokka-core. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : dokka-core. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : kotlin-as-java-plugin. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : javadoc-plugin. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.dokka. **Name** : templating-plugin. **Version** : 2.0.0.
+1. **Group** : org.jetbrains.dokka. **Name** : kotlin-as-java-plugin. **Version** : 2.1.0.
+ * **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
+ * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
+
+1. **Group** : org.jetbrains.dokka. **Name** : templating-plugin. **Version** : 2.1.0.
* **Project URL:** [https://github.com/Kotlin/dokka](https://github.com/Kotlin/dokka)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -695,23 +657,31 @@
* **Project URL:** [https://github.com/JetBrains/intellij-deps-trove4j](https://github.com/JetBrains/intellij-deps-trove4j)
* **License:** [GNU LESSER GENERAL PUBLIC LICENSE 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
-1. **Group** : org.jetbrains.kotlin. **Name** : abi-tools. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : abi-tools. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : abi-tools-api. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : abi-tools-api. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-bom. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-bom. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-api. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-api. **Version** : 2.3.20.
+ * **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
+ * **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-compat. **Version** : 2.3.20.
+ * **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
+ * **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-cri-impl. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-impl. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-build-tools-impl. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -719,15 +689,15 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-compiler-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-compiler-embeddable. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-compiler-runner. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-compiler-runner. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-daemon-client. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-daemon-client. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -735,15 +705,19 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-daemon-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-daemon-embeddable. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-klib-commonizer-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-klib-abi-reader. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-metadata-jvm. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-klib-commonizer-embeddable. **Version** : 2.3.20.
+ * **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
+ * **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-metadata-jvm. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -751,7 +725,7 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-reflect. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-reflect. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -759,23 +733,23 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-script-runtime. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-script-runtime. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-common. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-common. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-compiler-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-compiler-embeddable. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-compiler-impl-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-compiler-impl-embeddable. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-jvm. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-scripting-jvm. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -783,7 +757,7 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -791,7 +765,7 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib-common. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib-common. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -799,17 +773,21 @@
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib-jdk7. **Version** : 2.3.20.
+ * **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
+ * **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+
1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib-jdk8. **Version** : 2.0.21.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlin. **Name** : swift-export-embeddable. **Version** : 2.2.20.
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-stdlib-jdk8. **Version** : 2.3.20.
* **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
* **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlinx. **Name** : atomicfu. **Version** : 0.23.1.
- * **Project URL:** [https://github.com/Kotlin/kotlinx.atomicfu](https://github.com/Kotlin/kotlinx.atomicfu)
- * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
+1. **Group** : org.jetbrains.kotlin. **Name** : kotlin-tooling-core. **Version** : 2.3.20.
+ * **Project URL:** [https://kotlinlang.org/](https://kotlinlang.org/)
+ * **License:** [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
1. **Group** : org.jetbrains.kotlinx. **Name** : atomicfu. **Version** : 0.29.0.
* **Project URL:** [https://github.com/Kotlin/kotlinx.atomicfu](https://github.com/Kotlin/kotlinx.atomicfu)
@@ -863,26 +841,14 @@
* **Project URL:** [https://github.com/Kotlin/kotlinx.html](https://github.com/Kotlin/kotlinx.html)
* **License:** [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-bom. **Version** : 1.7.3.
- * **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
- * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-
1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-core. **Version** : 1.4.1.
* **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-core. **Version** : 1.7.3.
- * **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
- * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-
1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-core-jvm. **Version** : 1.4.1.
* **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-core-jvm. **Version** : 1.7.3.
- * **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
- * **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
-
1. **Group** : org.jetbrains.kotlinx. **Name** : kotlinx-serialization-json. **Version** : 1.4.1.
* **Project URL:** [https://github.com/Kotlin/kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
* **License:** [The Apache Software License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -899,7 +865,7 @@
* **Project URL:** [http://jspecify.org/](http://jspecify.org/)
* **License:** [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-1. **Group** : org.junit. **Name** : junit-bom. **Version** : 5.13.2.
+1. **Group** : org.junit. **Name** : junit-bom. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
@@ -907,27 +873,27 @@
* **Project URL:** [https://junit-pioneer.org/](https://junit-pioneer.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-api. **Version** : 5.13.2.
+1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-api. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-engine. **Version** : 5.13.2.
+1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-engine. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-params. **Version** : 5.13.2.
+1. **Group** : org.junit.jupiter. **Name** : junit-jupiter-params. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.platform. **Name** : junit-platform-commons. **Version** : 1.13.2.
+1. **Group** : org.junit.platform. **Name** : junit-platform-commons. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.platform. **Name** : junit-platform-engine. **Version** : 1.13.2.
+1. **Group** : org.junit.platform. **Name** : junit-platform-engine. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
-1. **Group** : org.junit.platform. **Name** : junit-platform-launcher. **Version** : 1.13.2.
+1. **Group** : org.junit.platform. **Name** : junit-platform-launcher. **Version** : 6.0.3.
* **Project URL:** [https://junit.org/](https://junit.org/)
* **License:** [Eclipse Public License v2.0](https://www.eclipse.org/legal/epl-v20.html)
@@ -982,6 +948,6 @@
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 10 19:29:47 WEST 2025** using
+This report was generated on **Mon Apr 06 17:18:07 WEST 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 93bcb69..49ad30c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -9,7 +9,7 @@ org.gradle.parallel=true
#org.gradle.caching=true
# Dokka plugin eats more memory than usual. Therefore, all builds should have enough.
-org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -XX:+UseParallelGC
+org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -XX:+UseParallelGC -Dfile.encoding=UTF-8
# suppress inspection "UnusedProperty"
# The below property enables generation of XML reports for tests.
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 8bdaf60..d997cfc 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2e11132..c61a118 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index 23d15a9..739907d 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright © 2015-2021 the original authors.
+# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -114,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@@ -172,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
diff --git a/gradlew.bat b/gradlew.bat
index db3a6ac..c4bdd3a 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -70,11 +70,10 @@ goto fail
:execute
@rem Setup the command line
-set CLASSPATH=
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/pom.xml b/pom.xml
index acad9b6..aba8411 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject.
-->
io.spine.tools
testlib
-2.0.0-SNAPSHOT.211
+2.0.0-SNAPSHOT.212
2015
@@ -32,31 +32,31 @@ all modules and does not describe the project structure per-subproject.
com.google.guava
guava
- 33.4.8-jre
+ 33.5.0-jre
compile
com.google.guava
guava-testlib
- 33.4.8-jre
+ 33.5.0-jre
compile
com.google.protobuf
protobuf-java
- 4.31.1
+ 4.34.1
compile
com.google.protobuf
protobuf-java-util
- 4.31.1
+ 4.34.1
compile
com.google.protobuf
protobuf-kotlin
- 4.31.1
+ 4.34.1
compile
@@ -80,7 +80,7 @@ all modules and does not describe the project structure per-subproject.
io.kotest
kotest-assertions-core
- 6.0.3
+ 6.1.11
compile
@@ -92,13 +92,13 @@ all modules and does not describe the project structure per-subproject.
org.jetbrains.kotlin
kotlin-bom
- 2.2.20
+ 2.3.20
compile
org.jetbrains.kotlin
kotlin-stdlib
- 2.2.20
+ 2.3.20
compile
@@ -116,13 +116,13 @@ all modules and does not describe the project structure per-subproject.
org.junit
junit-bom
- 5.13.2
+ 6.0.3
compile
org.junit.jupiter
junit-jupiter-api
- 5.13.2
+ 6.0.3
compile
@@ -146,7 +146,7 @@ all modules and does not describe the project structure per-subproject.
io.spine.tools
spine-testlib
- 2.0.0-SNAPSHOT.210
+ 2.0.0-SNAPSHOT.211
test
@@ -158,13 +158,13 @@ all modules and does not describe the project structure per-subproject.
org.junit.jupiter
junit-jupiter-engine
- 5.13.2
+ 6.0.3
test
org.junit.jupiter
junit-jupiter-params
- 5.13.2
+ 6.0.3
test
@@ -192,7 +192,7 @@ all modules and does not describe the project structure per-subproject.
com.google.protobuf
protoc
- 4.31.1
+ 4.34.1
com.puppycrawl.tools
@@ -219,16 +219,6 @@ all modules and does not describe the project structure per-subproject.
pmd-java
7.12.0
-
- org.bouncycastle
- bcpg-jdk18on
- 1.80
-
-
- org.bouncycastle
- bcpkix-jdk18on
- 1.80
-
org.checkerframework
checker-qual
@@ -248,62 +238,57 @@ all modules and does not describe the project structure per-subproject.
org.jetbrains.dokka
all-modules-page-plugin
- 2.0.0
+ 2.1.0
org.jetbrains.dokka
- analysis-kotlin-descriptors
- 2.0.0
+ analysis-kotlin-symbols
+ 2.1.0
org.jetbrains.dokka
dokka-base
- 2.0.0
+ 2.1.0
org.jetbrains.dokka
dokka-core
- 2.0.0
+ 2.1.0
org.jetbrains.dokka
- kotlin-as-java-plugin
- 2.0.0
+ javadoc-plugin
+ 2.1.0
org.jetbrains.dokka
templating-plugin
- 2.0.0
+ 2.1.0
org.jetbrains.kotlin
abi-tools
- 2.2.20
+ 2.3.20
org.jetbrains.kotlin
- kotlin-build-tools-impl
- 2.2.20
+ kotlin-build-tools-compat
+ 2.3.20
org.jetbrains.kotlin
- kotlin-compiler-embeddable
- 2.2.20
+ kotlin-build-tools-impl
+ 2.3.20
org.jetbrains.kotlin
kotlin-klib-commonizer-embeddable
- 2.2.20
+ 2.3.20
org.jetbrains.kotlin
kotlin-scripting-compiler-embeddable
- 2.2.20
-
-
- org.jetbrains.kotlin
- swift-export-embeddable
- 2.2.20
+ 2.3.20
diff --git a/src/test/kotlin/io/spine/testing/logging/mute/MuteLoggingExtensionSpec.kt b/src/test/kotlin/io/spine/testing/logging/mute/MuteLoggingExtensionSpec.kt
index 76a9010..7c49f3c 100644
--- a/src/test/kotlin/io/spine/testing/logging/mute/MuteLoggingExtensionSpec.kt
+++ b/src/test/kotlin/io/spine/testing/logging/mute/MuteLoggingExtensionSpec.kt
@@ -47,7 +47,6 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExecutableInvoker
import org.junit.jupiter.api.extension.ExtensionContext
-import org.junit.jupiter.api.extension.MediaType
import org.junit.jupiter.api.extension.TestInstances
import org.junit.jupiter.api.function.ThrowingConsumer
import org.junit.jupiter.api.parallel.ExecutionMode
@@ -153,13 +152,13 @@ private class LoggingStub {
private class StubContext(private val executionThrowable: Throwable?) : ExtensionContext {
override fun getParent(): Optional = Optional.empty()
- override fun getRoot(): ExtensionContext? = null
- override fun getUniqueId(): String? = null
- override fun getDisplayName(): String? = null
+ override fun getRoot(): ExtensionContext = nothing()
+ override fun getUniqueId(): String = ""
+ override fun getDisplayName(): String = ""
override fun getTags(): Set = ImmutableSet.of()
override fun getElement(): Optional = Optional.empty()
override fun getTestClass(): Optional> = Optional.empty()
- override fun getEnclosingTestClasses(): List?> = emptyList()
+ override fun getEnclosingTestClasses(): List> = emptyList()
override fun getTestInstanceLifecycle(): Optional = Optional.empty()
override fun getTestInstance(): Optional = Optional.empty()
override fun getTestInstances(): Optional = Optional.empty()
@@ -169,30 +168,36 @@ private class StubContext(private val executionThrowable: Throwable?) : Extensio
Optional.ofNullable(executionThrowable)
override fun getConfigurationParameter(key: String): Optional = Optional.empty()
-
override fun getConfigurationParameter(
key: String,
- transformer: Function
- ): Optional = Optional.empty()
+ transformer: Function
+ ): Optional = nothing()
override fun publishReportEntry(map: Map) = Unit
override fun publishFile(
- name: String?,
- mediaType: MediaType?,
- action: ThrowingConsumer?
- ) = Unit
+ name: String,
+ mediaType: org.junit.jupiter.api.MediaType,
+ action: ThrowingConsumer
+ ): Unit = nothing()
override fun publishDirectory(
- name: String?,
- action: ThrowingConsumer?
- ) = Unit
+ name: String,
+ action: ThrowingConsumer
+ ): Unit = nothing()
+
+ override fun getStore(namespace: ExtensionContext.Namespace): ExtensionContext.Store = nothing()
- override fun getStore(namespace: ExtensionContext.Namespace): ExtensionContext.Store? = null
override fun getStore(
- scope: ExtensionContext.StoreScope?,
- namespace: ExtensionContext.Namespace?
- ): ExtensionContext.Store? = null
+ scope: ExtensionContext.StoreScope,
+ namespace: ExtensionContext.Namespace
+ ): ExtensionContext.Store {
+ nothing()
+ }
override fun getExecutionMode(): ExecutionMode = ExecutionMode.SAME_THREAD
- override fun getExecutableInvoker(): ExecutableInvoker? = null
+ override fun getExecutableInvoker(): ExecutableInvoker = nothing()
+
+ private fun nothing(): Nothing {
+ TODO("Stub method should not be called.")
+ }
}
diff --git a/version.gradle.kts b/version.gradle.kts
index c568351..f934e9f 100644
--- a/version.gradle.kts
+++ b/version.gradle.kts
@@ -24,4 +24,4 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-val versionToPublish: String by extra("2.0.0-SNAPSHOT.211")
+val versionToPublish: String by extra("2.0.0-SNAPSHOT.212")