Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"Bash(git switch:*)",
"Bash(git checkout:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git restore:*)",
"Bash(git stash:*)",
"Bash(git fetch:*)",
Expand Down Expand Up @@ -48,7 +49,15 @@
"Bash(gh release create:*)"
],
"ask": [
"Bash(git commit:*)",
"Bash(git push --force*)",
"Bash(git push * --force*)",
"Bash(git push -f*)",
"Bash(git push * -f*)",
"Bash(git push -uf*)",
"Bash(git push * -uf*)",
"Bash(git push * +*)",
"Bash(git push --mirror*)",
"Bash(git push * --mirror*)",
"Bash(git rebase:*)",
"Bash(git merge:*)",
"Bash(git cherry-pick:*)",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ on:
jobs:
publish:
name: Publish to Maven repositories
uses: SpineEventEngine/config/.github/workflows/publishing.yml@8fddc6f17507209855ccd33706cca429b2473876
uses: SpineEventEngine/config/.github/workflows/publishing.yml@a0cbbbfe66c12475224563439fb6deb3da71ba58
permissions:
contents: read
packages: write
Expand Down
8 changes: 4 additions & 4 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ val grGitVersion = "5.3.3"
* This version may change from the [version of Kotlin][io.spine.dependency.lib.Kotlin.version]
* used by the project.
*/
val kotlinEmbeddedVersion = "2.4.10"
val kotlinEmbeddedVersion = "2.4.21"

/**
* The version of Guava used in `buildSrc`.
*
* 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.7.1-jre"
val guavaVersion = "33.7.2-jre"

/**
* The version of ErrorProne Gradle plugin.
Expand Down Expand Up @@ -132,7 +132,7 @@ val kotestJvmPluginVersion = "0.4.11"
/**
* @see [io.spine.dependency.test.Kover]
*/
val koverVersion = "0.9.9"
val koverVersion = "0.9.11"

/**
* The version of the Shadow Plugin.
Expand Down Expand Up @@ -175,7 +175,7 @@ val junitVersion = "6.1.3"
*
* @see [io.spine.dependency.test.Kotest]
*/
val kotestVersion = "6.2.4"
val kotestVersion = "6.2.5"

configurations.all {
resolutionStrategy {
Expand Down
118 changes: 117 additions & 1 deletion buildSrc/src/main/kotlin/DokkaExts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,28 @@

import io.spine.dependency.local.DokkaTools
import io.spine.gradle.SpineTaskGroup
import io.spine.gradle.github.pages.TaskName
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.execution.TaskExecutionGraph
import org.gradle.api.publish.maven.tasks.PublishToMavenLocal
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
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.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.withType
import org.jetbrains.dokka.gradle.DokkaExtension
import org.jetbrains.dokka.gradle.engine.parameters.DokkaSourceSetSpec
import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier
import org.jetbrains.dokka.gradle.engine.plugins.DokkaHtmlPluginParameters
import org.jetbrains.dokka.gradle.tasks.DokkaBaseTask

/**
* To exclude pieces of code annotated with `@Internal` from the documentation
Expand Down Expand Up @@ -205,18 +212,127 @@ fun Project.htmlDocsJar(): TaskProvider<Jar> = tasks.getOrCreate("htmlDocsJar")

/**
* Tells if this task belongs to the execution graph that contains
* the `publish` and `dokkaGenerate` tasks.
* the `publish` or `dokkaGenerate` tasks.
*
* 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 process and its results.
*
* The predicate reaches the task graph through [Task.getProject]. Called from an `onlyIf`
* spec or a task action, it does so at execution time, which Gradle deprecates and
* the configuration cache does not support. Also, the predicate holds whenever the graph
* contains a Dokka task, since Dokka 2.x names its tasks `dokkaGenerate…`.
* [skipDokkaWhenPublishingToMavenLocal] avoids both problems.
*/
@Deprecated(message = "Please use `Project.skipDokkaWhenPublishingToMavenLocal()` instead.")
fun Task.isInPublishingGraph(): Boolean =
project.gradle.taskGraph.allTasks.any {
it.name == "publish" || it.name.contains("dokkaGenerate")
}

/**
* Configures the Dokka tasks of this project to be skipped in a build that publishes
* to Maven Local only.
*
* Such a build usually feeds integration tests, which need the published code,
* but not its documentation. So the Dokka tasks are skipped when the execution graph
* contains a [PublishToMavenLocal] task and no task that ships the documentation
* elsewhere: `publish`, a [PublishToMavenRepository] task, or `updateGitHubPages`.
* They still run if a task named on the command line selects a documentation task of
* the graph: one that has `dokka` in its name, ignoring case, or a documentation JAR,
* `javadocJar` or `htmlDocsJar`. The name may be the full one, e.g., `dokkaGenerate`,
* or a camel-case abbreviation, e.g., `dGPJ` for `dokkaGeneratePublicationJavadoc`.
* Without task names, a documentation request cannot be ruled out, so the tasks run too.
* This is the case of an included build, as Gradle does not pass it the tasks named
* on the command line.
*
* Any other build runs the Dokka tasks in its graph. When the tasks are skipped,
* the documentation JARs they feed, such as `javadocJar`, contain only a manifest,
* or the output of an earlier Dokka run.
*
* The `onlyIf` spec added to the tasks is evaluated at execution time, when it must not
* call [Task.getProject] to reach the task graph: Gradle deprecates that, and
* the configuration cache does not support it. So the graph is scanned at configuration
* time, once it is ready, and the spec reads the result from a property, which
* a configuration cache entry stores along with the tasks.
*/
fun Project.skipDokkaWhenPublishingToMavenLocal() {
// The project path is dropped, so that, e.g., `:dokka-extensions:build`
// is not taken for a Dokka request.
val requestedNames = gradle.startParameter.taskNames
.map { it.substringAfterLast(':') }
.filter { it.isNotEmpty() }
val docsNeeded = objects.property<Boolean>()
gradle.taskGraph.whenReady {
val docsRequested = requestedNames.isEmpty() || selectsDocsTask(requestedNames)
docsNeeded.set(docsRequested || !publishesToMavenLocalOnly())
}
tasks.withType<DokkaBaseTask>().configureEach {
onlyIf("documentation is needed beyond Maven Local") { docsNeeded.get() }
}
}

/**
* The names of the lifecycle tasks that ship the documentation beyond Maven Local.
*/
private val docsShippingTaskNames = setOf("publish", TaskName.updateGitHubPages)

/**
* Tells if this graph publishes to Maven Local and does not contain a task that ships
* the documentation elsewhere.
*/
private fun TaskExecutionGraph.publishesToMavenLocalOnly(): Boolean {
val tasks = allTasks
return tasks.any { it is PublishToMavenLocal }
&& tasks.none { it is PublishToMavenRepository || it.name in docsShippingTaskNames }
}

/**
* The names of the tasks that pack the documentation into JARs.
*/
private val docsJarTaskNames = setOf("javadocJar", "htmlDocsJar")

/**
* Tells if any of the given names, taken from the command line, selects
* a documentation task of this graph.
*
* A documentation task is one that has `dokka` in its name, ignoring case,
* or a documentation JAR. The command line keeps a task name as typed, so the name
* may be a camel-case abbreviation that Gradle resolves, e.g., `dGPJ`
* for `dokkaGeneratePublicationJavadoc`.
*/
private fun TaskExecutionGraph.selectsDocsTask(names: List<String>): Boolean {
val docsTaskNames = allTasks.map { it.name }.filter {
it.contains("dokka", ignoreCase = true) || it in docsJarTaskNames
}
return names.any { name ->
val pattern = abbreviationPattern(name)
docsTaskNames.any { pattern.containsMatchIn(it) }
}
}

/**
* Creates the pattern for the task names that the given camel-case abbreviation selects.
*
* Follows the matching of Gradle: each word of the abbreviation starts a word of
* the task name, in the same order, and the task name may go on after the last one.
* Unlike Gradle, which prefers exact and case-sensitive matches, the pattern
* ignores case, so it may select more tasks, never fewer.
*/
private fun abbreviationPattern(abbreviation: String): Regex {
val words = abbreviation.split(wordStart).filter { it.isNotEmpty() }
val pattern = words.joinToString(separator = "[\\p{javaLowerCase}\\p{Digit}]*", prefix = "^") {
Regex.escape(it)
}
return Regex(pattern, RegexOption.IGNORE_CASE)
}

/**
* Matches the position before an upper-case letter, where a word of a camel-case name starts.
*/
private val wordStart = Regex("(?=\\p{javaUpperCase})")

/**
* Disables Dokka and Javadoc tasks in this `Project`.
*
Expand Down
6 changes: 1 addition & 5 deletions buildSrc/src/main/kotlin/dokka-setup.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ dependencies {
useDokkaWithSpineExtensions()
}

tasks.withType<DokkaBaseTask>().configureEach {
onlyIf {
isInPublishingGraph()
}
}
skipDokkaWhenPublishingToMavenLocal()

// The Dokka Javadoc format does not support Kotlin Multiplatform source sets, so its
// publication task fails for KMP modules ("No source set found for <module>/jvmMain").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ package io.spine.dependency.build
// https://www.mojohaus.org/animal-sniffer/animal-sniffer-maven-plugin/
@Suppress("unused", "ConstPropertyName")
object AnimalSniffer {
private const val version = "1.27"
private const val version = "1.28"
const val lib = "org.codehaus.mojo:animal-sniffer-annotations:$version"
}
15 changes: 12 additions & 3 deletions buildSrc/src/main/kotlin/io/spine/dependency/build/CheckStyle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@ object CheckStyle {
/**
* The version to be used in the project.
*
* `10.12.1` is the last version in `10.12.0`, which does not introduce
* capability conflict over `google-collections` with Guava.
* `12.3.1` is the last release that runs on Java 17, which our builds use
* to run Checkstyle. `13.0.0` and later require Java 21.
*
* `12.3.1` depends on Doxia, which Checkstyle uses only to generate its own
* website. Through Doxia, it brings two versions each of `commons-lang3` and
* `httpcore`. `forceVersions()` enables `failOnVersionConflict()` in the
* `checkstyle` configuration too, so Gradle would reject the graph.
* [CheckStyleConfig][io.spine.gradle.checkstyle.CheckStyleConfig] therefore
* excludes the `org.apache.maven.doxia` group from the `checkstyle` configuration.
* Releases from `13.11.0` on no longer depend on Doxia, so the exclusion can go
* once we run Checkstyle on Java 21.
*
* @see <a href="https://checkstyle.sourceforge.io/releasenotes.html">Checkstyle</a>
*/
const val version = "10.12.1"
const val version = "12.3.1"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package io.spine.dependency.build
// https://checkerframework.org/
@Suppress("unused", "ConstPropertyName")
object CheckerFramework {
private const val version = "4.2.2"
private const val version = "4.3.1"
const val annotations = "org.checkerframework:checker-qual:$version"
@Suppress("unused")
val dataflow = listOf(
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/build/Ksp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import io.spine.dependency.Dependency
*/
@Suppress("unused")
object Ksp : Dependency() {
override val version = "2.3.11"
override val version = "2.3.12"
val dogfoodingVersion = version
override val group = "com.google.devtools.ksp"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ package io.spine.dependency.build
*/
@Suppress("ConstPropertyName")
object PluginPublishPlugin {
const val version = "2.1.1"
const val version = "2.2.1"
const val id = "com.gradle.plugin-publish"
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/build/Pmd.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ package io.spine.dependency.build
// https://github.com/pmd/pmd/releases
@Suppress("unused", "ConstPropertyName")
object Pmd {
const val version = "7.27.0"
const val version = "7.28.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ package io.spine.dependency.lib
object ApacheHttp {

// https://hc.apache.org/downloads.cgi
const val core = "org.apache.httpcomponents:httpcore:4.4.14"
const val core = "org.apache.httpcomponents:httpcore:4.4.16"
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/lib/Asm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package io.spine.dependency.lib
// https://asm.ow2.io/
@Suppress("unused", "ConstPropertyName")
object Asm {
private const val version = "9.10.1"
private const val version = "9.11"
const val group = "org.ow2.asm"
const val lib = "$group:asm:$version"

Expand Down
28 changes: 27 additions & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/lib/BouncyCastle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,31 @@ package io.spine.dependency.lib
// https://www.bouncycastle.org/java.html
@Suppress("unused", "ConstPropertyName")
object BouncyCastle {
const val libPkcsJdk15 = "org.bouncycastle:bcpkix-jdk15on:1.68"

/**
* The PKIX library, pinned to `bcpkix-jdk15on:1.70`, the last release of
* the `-jdk15on` artifacts.
*
* Newer releases are published as `bcpkix-jdk18on`. They carry the same
* `org.bouncycastle` classes, yet Gradle sees them as a different module
* and resolves no conflict between the two.
*
* The [IntelliJ Platform][IntelliJ.version] stays at `213.7172.53` for now.
* Its `ide-impl` module depends on the `-jdk15on` artifacts through two paths:
*
* - `marketplace-zip-signer:0.1.3` requires `bcpkix-jdk15on:1.64`.
* - `remote-dev-util` requires `bcpg-jdk15on:1.69`, which requires
* `bcprov-jdk15on:1.69`.
*
* Staying on `-jdk15on` lets Gradle resolve `bcpkix-jdk15on` and
* `bcprov-jdk15on` to `1.70`, the version of this library. With
* `bcpkix-jdk18on` instead, a project that also has the IntelliJ Platform
* on its classpath would get two copies of the BouncyCastle classes.
*
* The two paths also disagree on the version. That is why `tool-base`
* leaves BouncyCastle out of the POM of its IntelliJ Platform uber JAR.
*
* Revisit this pin when [IntelliJ.version] changes.
*/
const val libPkcsJdk15 = "org.bouncycastle:bcpkix-jdk15on:1.70"
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ package io.spine.dependency.lib
*/
@Suppress("unused")
object Caffeine {
private const val version = "3.2.4"
private const val version = "3.3.1"
const val lib = "com.github.ben-manes.caffeine:caffeine:$version"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ package io.spine.dependency.lib
// https://commons.apache.org/proper/commons-codec/changes-report.html
@Suppress("unused", "ConstPropertyName")
object CommonsCodec {
private const val version = "1.22.1"
private const val version = "1.23.0"
const val lib = "commons-codec:commons-codec:$version"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ package io.spine.dependency.lib
// https://firebase.google.com/docs/admin/setup#java
@Suppress("unused", "ConstPropertyName")
object Firebase {
private const val adminVersion = "9.10.0"
private const val adminVersion = "9.11.0"
const val admin = "com.google.firebase:firebase-admin:$adminVersion"
}
Loading
Loading