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
19 changes: 19 additions & 0 deletions .github/workflows/build-on-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,22 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
verbose: true

# The Codecov CLI ships a set of "file fixes" with every upload. For
# `.kt` files — never `.java` — they mark each line holding nothing
# but a brace or a parenthesis as non-code. JaCoCo, however, does
# measure one such line: it attributes a Kotlin lambda body's
# instructions to the body's closing `}`, through the synthetic
# `$lambda$N` that an `invokedynamic` lambda compiles to. The fixes
# thus discard roughly a tenth of the measured lines, which would be
# harmless if every ingestion applied them. Not every one does: when
# Codecov re-processes a stored upload, the second pass leaves them
# unapplied, so one and the same report can be ingested on either
# line basis. That switch moves the `src/main/**` project status by
# about 0.7 percentage points, fourteen times the threshold in
# `.codecov.yml`, and it has been seen on `master`, whose commits
# are the `target: auto` baselines — so it can shift a pull
# request's delta either way. Sending no fixes makes both ingestion
# paths agree, at the price of counting a lambda-closing brace as a
# coverable line.
disable_file_fixes: true
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@a0cbbbfe66c12475224563439fb6deb3da71ba58
uses: SpineEventEngine/config/.github/workflows/publishing.yml@604420cd7eab82b382c9a5c1d812be454552c27c
permissions:
contents: read
packages: write
Expand Down
34 changes: 23 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,29 @@ Shared skills, scripts, and guidelines come from the `.agents/shared` submodule
(and some shallow clones / cloud checkouts) start with NO submodules checked out, so
those symlinks dangle and no skills are found. Bootstrap such a tree with
**`./init-submodules`** — a root script that materializes the missing
*config-managed* submodules at their pinned commits: `config` itself, plus every
submodule that declares a tracked `branch` in `.gitmodules` (`.agents/shared`, and
any shared submodule added later) — the same rule `./config/pull` uses to decide
what it floats. Submodules the consumer owns (a Hugo theme, a vendored library,
doc-example submodules, …) declare no tracked branch and are left untouched, so the
automatic `SessionStart` run never tries to clone — or fail on credentials for — a
submodule this project does not manage. It depends on no pre-existing `config`
submodule, so it works before `./config/pull` (which lives inside the `config`
submodule) can. Claude Code runs it automatically via a `SessionStart` hook; other
agents and humans run it by hand, then `./config/pull` to float the shared submodules
to their branch tips.
*config-managed* submodules at the tip of their branch (`master` for `config`, the
tracked `branch` for the rest): `config` itself, plus every submodule that declares
a tracked `branch` in `.gitmodules` (`.agents/shared`, and any shared submodule
added later) — the same rule `./config/pull` uses to decide what it floats. It
deliberately does not stop at the commit the superproject pins for such a
submodule: nothing keeps that pin current — `ignore = all` hides the submodule from
`git status`, and `./config/pull` floats the on-disk copy without committing the
moved gitlink — so materializing the pin as-is means months-old hook scripts,
skills, and guidelines. If the float fails — a branch the remote does not have,
say — a warning is printed and the submodule is left wherever the steps that
did succeed put it, at worst the pin, so a session still starts with a usable
tree; it is not retried on a later run, which is why that warning points at
`./config/pull`. With no network at all the clone itself fails and the
submodule is left uninitialized, as it was before. Submodules the consumer owns
(a Hugo theme, a vendored library, doc-example submodules, …) declare no tracked
branch and are left untouched, so the automatic `SessionStart` run never tries
to clone — or fail on credentials for — a submodule this project does not
manage. A submodule that is already checked out is left exactly as it is, which
keeps repeated runs cheap and offline-safe and never rewinds a tree someone
parked on a particular commit; run `./config/pull` to float those. It depends on
no pre-existing `config` submodule, so it works before `./config/pull` (which
lives inside the `config` submodule) can. Claude Code runs it automatically via
a `SessionStart` hook; other agents and humans run it by hand.

## Commit and history safety

Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ 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.21"
val kotlinEmbeddedVersion = "2.4.10"

/**
* The version of Guava used in `buildSrc`.
Expand Down
32 changes: 29 additions & 3 deletions buildSrc/src/main/kotlin/DokkaExts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,45 @@ private fun abbreviationPattern(abbreviation: String): Regex {
private val wordStart = Regex("(?=\\p{javaUpperCase})")

/**
* Disables Dokka and Javadoc tasks in this `Project`.
* Disables the Dokka and Javadoc tasks generating the documentation of this `Project`.
*
* This function could be useful to improve build speed when building subprojects containing
* test environments or integration test projects.
*
* The JARs packing the documentation stay enabled, as they do under
* [skipDokkaWhenPublishingToMavenLocal]. A publication declares one artifact
* file per JAR, and a JAR that a disabled task never writes would be missing
* both when publishing and when the published files are attested. With nothing
* generated to pack, such a JAR costs almost nothing: it contains only
* a manifest, or the output of an earlier Dokka run.
*/
@Suppress("unused")
fun Project.disableDocumentationTasks() {
gradle.taskGraph.whenReady {
tasks.forEach { task ->
val lowercaseName = task.name.lowercase()
if (lowercaseName.contains("dokka") || lowercaseName.contains("javadoc")) {
if (task.generatesDocumentation()) {
task.enabled = false
}
}
}
}

/**
* Tells if this task generates documentation, rather than packing already generated
* documentation into a JAR.
*
* A [Jar] task is recognized by its type rather than by its name, so that
* `javadocJar` and `htmlDocsJar` are treated alike — as is any documentation JAR
* added later, whatever it is called. Any other task generates documentation if
* `dokka` or `javadoc` occurs in its name, ignoring case.
*
* [selectsDocsTask] keeps matching the same JARs by name, because the names it
* is given come from the command line rather than from the task graph.
*/
private fun Task.generatesDocumentation(): Boolean {
if (this is Jar) {
return false
}
return name.contains("dokka", ignoreCase = true)
|| name.contains("javadoc", ignoreCase = true)
}
10 changes: 6 additions & 4 deletions buildSrc/src/main/kotlin/config-tester.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ import io.spine.gradle.SpineRepos
import io.spine.gradle.SpineTaskGroup
import io.spine.gradle.cleanFolder
import java.nio.file.Path
import java.nio.file.Paths

// A reference to `config` to use along with the `ConfigTester`.
val config: Path = Paths.get("./")
//
// Both paths below are resolved against the project directory, because a relative path
// would be resolved against the working directory of the Gradle daemon instead.
val config: Path = layout.projectDirectory.asFile.toPath()

// A temp folder to use to check out the sources of other repositories with the `ConfigTester`.
val tempFolder = File("./tmp")
val tempFolder = layout.projectDirectory.dir("tmp").asFile

// Creates a Gradle task that checks out and builds the selected Spine repositories
// with the local version of `config` and `config/buildSrc`.
ConfigTester(config, tasks, tempFolder)
ConfigTester(config = config, tasks = tasks, tempFolder = tempFolder)
.addRepo(SpineRepos.baseTypes) // Builds `base-types` at `master`.
.addRepo(SpineRepos.base) // Builds `base` at `master`.
.addRepo(SpineRepos.coreJvm) // Builds `core-jvm` at `master`.
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ object Kotlin : DependencyWithBom() {
* This is the version of Kotlin we use for writing code that does not depend on Gradle.
*/
@Suppress("MemberVisibilityCanBePrivate") // used directly from the outside.
const val runtimeVersion = "2.4.21"
const val runtimeVersion = "2.4.10"

override val version = runtimeVersion
override val group = "org.jetbrains.kotlin"
Expand All @@ -43,7 +43,7 @@ object Kotlin : DependencyWithBom() {
* [embedded into Gradle](https://docs.gradle.org/current/userguide/compatibility.html#kotlin),
* which the Gradle version determines on its own.
*/
const val embeddedVersion = "2.4.21"
const val embeddedVersion = "2.4.10"

/**
* The version of the JetBrains annotations library, which is a transitive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package io.spine.dependency.lib
// https://github.com/square/kotlinpoet
@Suppress("unused", "ConstPropertyName")
object KotlinPoet {
private const val version = "2.4.0"
private const val version = "2.3.0"
const val lib = "com.squareup:kotlinpoet:$version"
const val ksp = "com.squareup:kotlinpoet-ksp:$version"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2026 CodeMatters, Lda.
*
* 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
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/

package io.spine.dependency.lib

import io.spine.dependency.Dependency

/**
* The Kotlin Multiplatform API and SDK for OpenTelemetry.
*
* The project is currently in the alpha stage, and its API is marked
* with `@io.opentelemetry.kotlin.ExperimentalApi`. Modules using these artifacts
* must opt in to that marker.
*
* The project does not publish a BOM, so the version is embedded in each
* artifact coordinate below.
*
* @see <a href="https://github.com/open-telemetry/opentelemetry-kotlin">GitHub project</a>
* @see <a href="https://opentelemetry.io/docs/languages/kotlin/">Kotlin documentation</a>
*/
@Suppress("unused")
object OpenTelemetryKotlin : Dependency() {

// https://central.sonatype.com/artifact/io.opentelemetry.kotlin/api
//
// The project is in the alpha stage, so bump this version only together
// with the code that consumes it.
override val version = "0.4.0"
override val group = "io.opentelemetry.kotlin"

/**
* The Kotlin Multiplatform API surface (traces, metrics, logs).
*
* This is the artifact production code compiles against; the SDK artifacts
* below are for applications and tests.
*/
val api = "$group:api:$version"

/**
* A no-op implementation of the [api] artifact.
*/
val noop = "$group:noop:$version"

/**
* The Kotlin SDK API: span processors, exporters, samplers, and the
* configuration DSL.
*
* This artifact exposes the SDK types on the compile classpath, while the
* `createOpenTelemetry { }` entry point that instantiates them lives in
* [implementation]. Applications and tests configure an `OpenTelemetry`
* instance using these two artifacts; production code needs only
* the [api] artifact.
*/
val core = "$group:core:$version"

/**
* The Kotlin SDK implementation, including the `createOpenTelemetry { }`
* entry point.
*
* Use it together with [core].
*/
val implementation = "$group:implementation:$version"

/**
* The compatibility bridge to the OpenTelemetry Java SDK.
*/
val compat = "$group:compat:$version"

override val modules: List<String> = listOf(
"$group:api",
"$group:noop",
"$group:core",
"$group:implementation",
"$group:compat",
)
}
9 changes: 6 additions & 3 deletions buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ package io.spine.dependency.local
*
* @see <a href="https://github.com/SpineEventEngine/base-libraries">spine-base-libraries</a>
*/
@Suppress("ConstPropertyName", "unused")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
"unused" /* Some subprojects do not use all Base artifacts. */,
)
object Base {
const val version = "2.0.0-SNAPSHOT.460"
const val versionForBuildScript = "2.0.0-SNAPSHOT.460"
const val version = "2.0.0-SNAPSHOT.461"
const val versionForBuildScript = "2.0.0-SNAPSHOT.461"
const val group = Spine.group
private const val prefix = "spine"
const val libModule = "$prefix-base"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package io.spine.dependency.local
*
* @see <a href="https://github.com/SpineEventEngine/base-types">spine-base-types</a>
*/
@Suppress("ConstPropertyName")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
)
object BaseTypes {
const val version = "2.0.0-SNAPSHOT.225"
const val group = Spine.group
Expand Down
4 changes: 3 additions & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/local/Change.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package io.spine.dependency.local
*
* @see <a href="https://github.com/SpineEventEngine/change">spine-change</a>
*/
@Suppress("ConstPropertyName")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
)
object Change {
const val version = "2.0.0-SNAPSHOT.208"
const val group = Spine.group
Expand Down
7 changes: 5 additions & 2 deletions buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ typealias CoreJava = CoreJvm
*
* See [`SpineEventEngine/core-jvm`](https://github.com/SpineEventEngine/core-jvm/).
*/
@Suppress("ConstPropertyName", "unused")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
"unused" /* Some subprojects do not use all CoreJvm artifacts. */,
)
object CoreJvm {
const val group = Spine.group
const val version = "2.0.0-SNAPSHOT.567"
const val version = "2.0.0-SNAPSHOT.571"

const val coreArtifact = "spine-core"
const val clientArtifact = "spine-client"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ package io.spine.dependency.local
@Suppress(
"MemberVisibilityCanBePrivate" /* The properties are used directly by other subprojects. */,
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
"unused"
"unused" /* Some subprojects do not use the CoreJvm Compiler directly. */,
)
object CoreJvmCompiler {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package io.spine.dependency.local
* See [`SpineEventEngine/dokka-tools`](https://github.com/SpineEventEngine/dokka-tools/).
*/
@Suppress(
"unused" /* Some subprojects do not use the Dokka tools directly. */,
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
)
object DokkaTools {
Expand Down
7 changes: 5 additions & 2 deletions buildSrc/src/main/kotlin/io/spine/dependency/local/Logging.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ package io.spine.dependency.local
*
* @see <a href="https://github.com/SpineEventEngine/logging">spine-logging</a>
*/
@Suppress("ConstPropertyName", "unused")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
"unused" /* Some subprojects do not use all Logging artifacts. */,
)
object Logging {
const val version = "2.0.0-SNAPSHOT.426"
const val version = "2.0.0-SNAPSHOT.427"
const val group = Spine.group

const val loggingArtifact = "spine-logging"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ package io.spine.dependency.local
)
object ProtoTap {
const val group = Spine.toolsGroup
const val version = "0.17.2"
const val version = "0.17.3"
const val gradlePluginId = "io.spine.prototap"
const val api = "$group:prototap-api:$version"
const val gradlePlugin = "$group:prototap-gradle-plugin:$version"
Expand Down
6 changes: 4 additions & 2 deletions buildSrc/src/main/kotlin/io/spine/dependency/local/Reflect.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package io.spine.dependency.local
*
* @see <a href="https://github.com/SpineEventEngine/reflect">spine-reflect</a>
*/
@Suppress("ConstPropertyName")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
)
object Reflect {
const val version = "2.0.0-SNAPSHOT.201"
const val version = "2.0.0-SNAPSHOT.202"
const val group = Spine.group
const val artifact = "spine-reflect"
const val lib = "$group:$artifact:$version"
Expand Down
4 changes: 3 additions & 1 deletion buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ package io.spine.dependency.local
/**
* Defines Maven groups for the Spine SDK artifacts.
*/
@Suppress("unused", "ConstPropertyName")
@Suppress(
"ConstPropertyName" /* We use a custom convention for artifact properties. */,
)
object Spine {
const val group = "io.spine"
const val toolsGroup = "io.spine.tools"
Expand Down
Loading
Loading