From e0e0b0940a542b2ef70a6596d4f6b48648932abb Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 19 Jun 2026 16:23:11 +0100 Subject: [PATCH 1/7] Migrate to JSpecify --- .../java/io/spine/web/firebase/FirebaseCredentials.java | 2 +- .../src/main/java/io/spine/web/firebase/package-info.java | 4 ++-- .../java/io/spine/web/firebase/query/package-info.java | 4 ++-- .../java/io/spine/web/firebase/rest/package-info.java | 4 ++-- .../io/spine/web/firebase/subscription/package-info.java | 4 ++-- .../java/io/spine/web/firebase/given/package-info.java | 4 ++-- .../main/java/io/spine/web/test/given/package-info.java | 4 ++-- .../src/main/java/io/spine/web/given/KnownRequest.java | 8 ++++---- .../src/main/java/io/spine/web/given/KnownResponse.java | 2 +- .../main/java/io/spine/web/given/MemoizingResponse.java | 2 +- .../src/main/java/io/spine/web/given/MockedRequest.java | 2 +- .../src/main/java/io/spine/web/given/MockedResponse.java | 2 +- .../src/main/java/io/spine/web/given/package-info.java | 4 ++-- web/src/main/java/io/spine/web/command/package-info.java | 4 ++-- web/src/main/java/io/spine/web/future/Completion.java | 2 +- web/src/main/java/io/spine/web/future/FutureObserver.java | 2 +- web/src/main/java/io/spine/web/future/package-info.java | 4 ++-- web/src/main/java/io/spine/web/package-info.java | 4 ++-- web/src/main/java/io/spine/web/parser/package-info.java | 4 ++-- web/src/main/java/io/spine/web/query/package-info.java | 4 ++-- .../main/java/io/spine/web/subscription/package-info.java | 4 ++-- .../io/spine/web/subscription/servlet/package-info.java | 4 ++-- .../java/io/spine/web/command/given/package-info.java | 4 ++-- web/src/test/java/io/spine/web/given/package-info.java | 4 ++-- .../test/java/io/spine/web/query/given/package-info.java | 4 ++-- 25 files changed, 45 insertions(+), 45 deletions(-) diff --git a/firebase-web/src/main/java/io/spine/web/firebase/FirebaseCredentials.java b/firebase-web/src/main/java/io/spine/web/firebase/FirebaseCredentials.java index 5f450706a..2e23fdc8d 100644 --- a/firebase-web/src/main/java/io/spine/web/firebase/FirebaseCredentials.java +++ b/firebase-web/src/main/java/io/spine/web/firebase/FirebaseCredentials.java @@ -32,7 +32,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.common.annotations.VisibleForTesting; import io.spine.annotation.Internal; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import java.io.IOException; import java.io.InputStream; diff --git a/firebase-web/src/main/java/io/spine/web/firebase/package-info.java b/firebase-web/src/main/java/io/spine/web/firebase/package-info.java index 1cf8d8b13..c7a2de212 100644 --- a/firebase-web/src/main/java/io/spine/web/firebase/package-info.java +++ b/firebase-web/src/main/java/io/spine/web/firebase/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.firebase; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/firebase-web/src/main/java/io/spine/web/firebase/query/package-info.java b/firebase-web/src/main/java/io/spine/web/firebase/query/package-info.java index e0694c6e8..4c3dc4cca 100644 --- a/firebase-web/src/main/java/io/spine/web/firebase/query/package-info.java +++ b/firebase-web/src/main/java/io/spine/web/firebase/query/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.firebase.query; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/firebase-web/src/main/java/io/spine/web/firebase/rest/package-info.java b/firebase-web/src/main/java/io/spine/web/firebase/rest/package-info.java index ed14d1723..3656759fa 100644 --- a/firebase-web/src/main/java/io/spine/web/firebase/rest/package-info.java +++ b/firebase-web/src/main/java/io/spine/web/firebase/rest/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.firebase.rest; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/firebase-web/src/main/java/io/spine/web/firebase/subscription/package-info.java b/firebase-web/src/main/java/io/spine/web/firebase/subscription/package-info.java index b64ba5de4..693f34adb 100644 --- a/firebase-web/src/main/java/io/spine/web/firebase/subscription/package-info.java +++ b/firebase-web/src/main/java/io/spine/web/firebase/subscription/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.firebase.subscription; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/firebase-web/src/test/java/io/spine/web/firebase/given/package-info.java b/firebase-web/src/test/java/io/spine/web/firebase/given/package-info.java index 7ac74c19d..8d30cea95 100644 --- a/firebase-web/src/test/java/io/spine/web/firebase/given/package-info.java +++ b/firebase-web/src/test/java/io/spine/web/firebase/given/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.firebase.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/integration-tests/test-app/src/main/java/io/spine/web/test/given/package-info.java b/integration-tests/test-app/src/main/java/io/spine/web/test/given/package-info.java index d1fc8b4b2..c30d5c70b 100644 --- a/integration-tests/test-app/src/main/java/io/spine/web/test/given/package-info.java +++ b/integration-tests/test-app/src/main/java/io/spine/web/test/given/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.test.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/testutil-web/src/main/java/io/spine/web/given/KnownRequest.java b/testutil-web/src/main/java/io/spine/web/given/KnownRequest.java index 1810d0d1e..4c1b92ac7 100644 --- a/testutil-web/src/main/java/io/spine/web/given/KnownRequest.java +++ b/testutil-web/src/main/java/io/spine/web/given/KnownRequest.java @@ -28,8 +28,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.net.MediaType; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.NotNull; +import org.jspecify.annotations.Nullable; import java.io.BufferedReader; import java.io.ByteArrayInputStream; @@ -139,7 +139,7 @@ public long getContentLengthLong() { } @Override - public @NonNull String getContentType() { + public @NotNull String getContentType() { return type.toString(); } @@ -153,7 +153,7 @@ public BufferedReader getReader() { } @Override - public @NonNull String getRequestURI() { + public @NotNull String getRequestURI() { return uri; } diff --git a/testutil-web/src/main/java/io/spine/web/given/KnownResponse.java b/testutil-web/src/main/java/io/spine/web/given/KnownResponse.java index 53372b427..f736d557f 100644 --- a/testutil-web/src/main/java/io/spine/web/given/KnownResponse.java +++ b/testutil-web/src/main/java/io/spine/web/given/KnownResponse.java @@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import java.io.PrintWriter; import java.io.Writer; diff --git a/testutil-web/src/main/java/io/spine/web/given/MemoizingResponse.java b/testutil-web/src/main/java/io/spine/web/given/MemoizingResponse.java index 1078ac7fe..258752696 100644 --- a/testutil-web/src/main/java/io/spine/web/given/MemoizingResponse.java +++ b/testutil-web/src/main/java/io/spine/web/given/MemoizingResponse.java @@ -27,7 +27,7 @@ package io.spine.web.given; import com.google.common.collect.ImmutableSet; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import java.io.PrintWriter; import java.io.StringWriter; diff --git a/testutil-web/src/main/java/io/spine/web/given/MockedRequest.java b/testutil-web/src/main/java/io/spine/web/given/MockedRequest.java index 1d5c25e14..85b5a771f 100644 --- a/testutil-web/src/main/java/io/spine/web/given/MockedRequest.java +++ b/testutil-web/src/main/java/io/spine/web/given/MockedRequest.java @@ -26,7 +26,7 @@ package io.spine.web.given; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; diff --git a/testutil-web/src/main/java/io/spine/web/given/MockedResponse.java b/testutil-web/src/main/java/io/spine/web/given/MockedResponse.java index 9faa0b864..d258a7600 100644 --- a/testutil-web/src/main/java/io/spine/web/given/MockedResponse.java +++ b/testutil-web/src/main/java/io/spine/web/given/MockedResponse.java @@ -26,7 +26,7 @@ package io.spine.web.given; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; diff --git a/testutil-web/src/main/java/io/spine/web/given/package-info.java b/testutil-web/src/main/java/io/spine/web/given/package-info.java index 0f29244bb..f86d1a650 100644 --- a/testutil-web/src/main/java/io/spine/web/given/package-info.java +++ b/testutil-web/src/main/java/io/spine/web/given/package-info.java @@ -28,9 +28,9 @@ * This package declares the routines designed to simplify testing of the web API exposed by Spine. */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/command/package-info.java b/web/src/main/java/io/spine/web/command/package-info.java index bf6fd5b3b..fb09019e4 100644 --- a/web/src/main/java/io/spine/web/command/package-info.java +++ b/web/src/main/java/io/spine/web/command/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.command; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/future/Completion.java b/web/src/main/java/io/spine/web/future/Completion.java index bc0a10c93..212b82bec 100644 --- a/web/src/main/java/io/spine/web/future/Completion.java +++ b/web/src/main/java/io/spine/web/future/Completion.java @@ -27,7 +27,7 @@ package io.spine.web.future; import com.google.common.flogger.FluentLogger; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.annotations.Nullable; import java.util.concurrent.CompletionStage; diff --git a/web/src/main/java/io/spine/web/future/FutureObserver.java b/web/src/main/java/io/spine/web/future/FutureObserver.java index 9d5c997d9..963bbe275 100644 --- a/web/src/main/java/io/spine/web/future/FutureObserver.java +++ b/web/src/main/java/io/spine/web/future/FutureObserver.java @@ -28,7 +28,7 @@ import io.grpc.stub.StreamObserver; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; import java.util.concurrent.CompletableFuture; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/web/src/main/java/io/spine/web/future/package-info.java b/web/src/main/java/io/spine/web/future/package-info.java index 43e2cc534..28d021b02 100644 --- a/web/src/main/java/io/spine/web/future/package-info.java +++ b/web/src/main/java/io/spine/web/future/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.future; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/package-info.java b/web/src/main/java/io/spine/web/package-info.java index cbe8685d0..2d8ec1b53 100644 --- a/web/src/main/java/io/spine/web/package-info.java +++ b/web/src/main/java/io/spine/web/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/parser/package-info.java b/web/src/main/java/io/spine/web/parser/package-info.java index 0185b775c..a27709223 100644 --- a/web/src/main/java/io/spine/web/parser/package-info.java +++ b/web/src/main/java/io/spine/web/parser/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.parser; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/query/package-info.java b/web/src/main/java/io/spine/web/query/package-info.java index ae8f14603..fbd2f9717 100644 --- a/web/src/main/java/io/spine/web/query/package-info.java +++ b/web/src/main/java/io/spine/web/query/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.query; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/subscription/package-info.java b/web/src/main/java/io/spine/web/subscription/package-info.java index cf37bda69..7a6add6f3 100644 --- a/web/src/main/java/io/spine/web/subscription/package-info.java +++ b/web/src/main/java/io/spine/web/subscription/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.subscription; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/main/java/io/spine/web/subscription/servlet/package-info.java b/web/src/main/java/io/spine/web/subscription/servlet/package-info.java index c151e829b..93e0bd528 100644 --- a/web/src/main/java/io/spine/web/subscription/servlet/package-info.java +++ b/web/src/main/java/io/spine/web/subscription/servlet/package-info.java @@ -30,9 +30,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.subscription.servlet; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/test/java/io/spine/web/command/given/package-info.java b/web/src/test/java/io/spine/web/command/given/package-info.java index a9130248e..a3d321ea4 100644 --- a/web/src/test/java/io/spine/web/command/given/package-info.java +++ b/web/src/test/java/io/spine/web/command/given/package-info.java @@ -25,9 +25,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.command.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/test/java/io/spine/web/given/package-info.java b/web/src/test/java/io/spine/web/given/package-info.java index d5bd254c5..54821b568 100644 --- a/web/src/test/java/io/spine/web/given/package-info.java +++ b/web/src/test/java/io/spine/web/given/package-info.java @@ -29,9 +29,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; diff --git a/web/src/test/java/io/spine/web/query/given/package-info.java b/web/src/test/java/io/spine/web/query/given/package-info.java index ff3bd1879..798464ddb 100644 --- a/web/src/test/java/io/spine/web/query/given/package-info.java +++ b/web/src/test/java/io/spine/web/query/given/package-info.java @@ -25,9 +25,9 @@ */ @CheckReturnValue -@ParametersAreNonnullByDefault +@NullMarked package io.spine.web.query.given; import com.google.errorprone.annotations.CheckReturnValue; -import javax.annotation.ParametersAreNonnullByDefault; +import import org.jspecify.annotations.NullMarked; From cc43654c44ed4d6b0a799623dba238f6b92a445f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 19 Jun 2026 16:30:56 +0100 Subject: [PATCH 2/7] Update `config` --- .codecov.yml | 6 +- .github/workflows/build-on-ubuntu.yml | 47 +- .github/workflows/build-on-windows.yml | 30 +- .github/workflows/check-links.yml | 216 + .github/workflows/ensure-reports-updated.yml | 35 + .../workflows/gradle-wrapper-validation.yml | 9 +- .github/workflows/increment-guard.yml | 35 +- .github/workflows/publish.yml | 19 +- ...move-obsolete-artifacts-from-packages.yaml | 73 + .idea/codeStyles/Project.xml | 3 +- .idea/copyright/TeamDev_Open_Source.xml | 2 +- .idea/dictionaries/common.xml | 8 +- .idea/inspectionProfiles/Project_Default.xml | 78 +- .idea/live-templates/README.md | 27 + .idea/live-templates/Spine.xml | 58 + .idea/live-templates/User.xml | 11 + .idea/misc.xml | 28 +- .lift.toml | 1 - build.gradle.kts | 90 +- buildSrc/build.gradle.kts | 213 +- buildSrc/quality/checkstyle-suppressions.xml | 42 + buildSrc/quality/checkstyle.xml | 86 + buildSrc/quality/detekt-config.yml | 35 + buildSrc/quality/pmd.xml | 97 + .../OpenCensus.kt => settings.gradle.kts} | 18 +- buildSrc/src/main/kotlin/BuildExtensions.kt | 349 ++ .../AutoService.kt => BuildSettings.kt} | 23 +- .../gradle => }/DependencyResolution.kt | 152 +- .../src/main/kotlin/DocumentationSettings.kt | 94 + buildSrc/src/main/kotlin/DokkaExts.kt | 248 + buildSrc/src/main/kotlin/LicenseSettings.kt | 43 + buildSrc/src/main/kotlin/Strings.kt | 50 + .../src/main/kotlin/config-tester.gradle.kts | 60 + .../kotlin/detekt-code-analysis.gradle.kts | 85 + .../src/main/kotlin/dokka-for-java.gradle.kts | 96 - .../FileFilter.kt => dokka-setup.gradle.kts} | 45 +- .../kotlin/io/spine/dependency/Dependency.kt | 137 + .../PathMarker.kt => dependency/boms/Boms.kt} | 62 +- .../io/spine/dependency/boms/BomsPlugin.kt | 185 + .../kotlinx/AtomicFu.kt} | 39 +- .../kotlinx/Coroutines.kt} | 40 +- .../io/spine/dependency/kotlinx/DateTime.kt | 34 + .../kotlinx/KotlinX.kt} | 13 +- .../spine/dependency/kotlinx/Serialization.kt | 73 + .../JavaJwt.kt => dependency/lib/Aedile.kt} | 16 +- .../lib}/ApacheHttp.kt | 8 +- .../lib}/AppEngine.kt | 12 +- .../kotlin/io/spine/dependency/lib/Asm.kt | 43 + .../lib/Auto.kt} | 45 +- .../lib}/BouncyCastle.kt | 8 +- .../io/spine/dependency/lib/Caffeine.kt | 43 + .../CheckStyle.kt => dependency/lib/Clikt.kt} | 14 +- .../lib}/CommonsCli.kt | 15 +- .../lib}/CommonsCodec.kt | 10 +- .../lib}/CommonsLogging.kt | 13 +- .../lib/Coroutines.kt} | 49 +- .../dependency => dependency/lib}/Firebase.kt | 12 +- .../dependency => dependency/lib}/Flogger.kt | 21 +- .../lib}/GoogleApis.kt | 12 +- .../lib}/GoogleCloud.kt | 8 +- .../kotlin/io/spine/dependency/lib/Grpc.kt | 82 + .../lib/GrpcKotlin.kt} | 26 +- .../dependency => dependency/lib}/Gson.kt | 13 +- .../dependency => dependency/lib}/Guava.kt | 17 +- .../lib}/HttpClient.kt | 18 +- .../io/spine/dependency/lib/IntelliJ.kt | 89 + .../dependency => dependency/lib}/J2ObjC.kt | 28 +- .../kotlin/io/spine/dependency/lib/Jackson.kt | 133 + .../lib/JavaDiffUtils.kt} | 27 +- .../kotlin/io/spine/dependency/lib/JavaJwt.kt | 46 + .../dependency => dependency/lib}/JavaPoet.kt | 13 +- .../dependency => dependency/lib}/JavaX.kt | 15 +- .../dependency/lib/JetBrainsAnnotations.kt | 42 + .../dependency => dependency/lib}/Klaxon.kt | 11 +- .../kotlin/io/spine/dependency/lib/Kotlin.kt | 120 + .../io/spine/dependency/lib/KotlinPoet.kt | 35 + .../lib}/KotlinSemver.kt | 10 +- .../kotlin/io/spine/dependency/lib/KotlinX.kt | 60 + .../kotlin/io/spine/dependency/lib/Log4j2.kt | 42 + .../dependency => dependency/lib}/Netty.kt | 22 +- .../TaskName.kt => dependency/lib/Okio.kt} | 21 +- .../lib/PalantirJavaFormat.kt} | 22 +- .../TestJar.kt => dependency/lib/Plexus.kt} | 34 +- .../dependency => dependency/lib}/Protobuf.kt | 44 +- .../dependency => dependency/lib}/Roaster.kt | 23 +- .../dependency => dependency/lib}/Slf4J.kt | 25 +- .../kotlin/io/spine/dependency/local/Base.kt | 46 + .../io/spine/dependency/local/BaseTypes.kt | 40 + .../Okio.kt => dependency/local/Change.kt} | 21 +- .../io/spine/dependency/local/Compiler.kt | 193 + .../io/spine/dependency/local/CoreJvm.kt | 58 + .../spine/dependency/local/CoreJvmCompiler.kt | 80 + .../io/spine/dependency/local/Logging.kt | 57 + .../spine/dependency/local/ModelCompiler.kt | 40 + .../io/spine/dependency/local/ProtoTap.kt | 46 + .../io/spine/dependency/local/Reflect.kt | 40 + .../kotlin/io/spine/dependency/local/Spine.kt | 36 + .../Plexus.kt => dependency/local/TestLib.kt} | 20 +- .../kotlin/io/spine/dependency/local/Time.kt | 74 + .../io/spine/dependency/local/ToolBase.kt | 67 + .../io/spine/dependency/local/Validation.kt | 68 + .../dependency => dependency/test}/AssertK.kt | 13 +- .../io/spine/dependency/test/Hamcrest.kt | 40 + .../kotlin/io/spine/dependency/test/JUnit.kt | 103 + .../test/Jacoco.kt} | 18 +- .../kotlin/io/spine/dependency/test/Kotest.kt | 57 + .../dependency/test/KotlinCompileTesting.kt | 40 + .../kotlin/io/spine/dependency/test/Kover.kt | 35 + .../test/OpenTest4J.kt} | 18 +- .../test/SystemLambda.kt} | 16 +- .../test}/TestKitTruth.kt | 19 +- .../dependency => dependency/test}/Truth.kt | 15 +- .../markup => docs}/MarkdownDocument.kt | 12 +- .../io/spine/{internal => }/gradle/Build.kt | 6 +- .../io/spine/{internal => }/gradle/Clean.kt | 6 +- .../gradle/Runtime.kt => gradle/Cli.kt} | 69 +- .../{internal => }/gradle/ConfigTester.kt | 75 +- .../gradle/ProjectExtensions.kt | 32 +- .../spine/{internal => }/gradle/RunBuild.kt | 8 +- .../spine/{internal => }/gradle/RunGradle.kt | 40 +- .../kotlin/io/spine/gradle/SpineTaskGroup.kt | 49 + .../{internal => }/gradle/StringExtensions.kt | 6 +- .../spine/{internal => }/gradle/TaskName.kt | 6 +- .../spine/{internal => }/gradle/base/Tasks.kt | 10 +- .../gradle/checkstyle/CheckStyleConfig.kt | 21 +- .../{internal => }/gradle/dart/DartContext.kt | 6 +- .../gradle/dart/DartEnvironment.kt | 10 +- .../gradle/dart/DartExtension.kt | 14 +- .../gradle/dart/plugin/DartPlugins.kt | 14 +- .../gradle/dart/plugin/Protobuf.kt | 19 +- .../{internal => }/gradle/dart/task/Build.kt | 29 +- .../gradle/dart/task/DartTasks.kt | 39 +- .../gradle/dart/task/IntegrationTest.kt | 25 +- .../gradle/dart/task/Publish.kt | 33 +- .../spine/gradle/docs/UpdatePluginVersion.kt | 126 + .../{internal => }/gradle/fs/LazyTempPath.kt | 29 +- .../github/pages => gradle/git}/Branch.kt | 19 +- .../kotlin/io/spine/gradle/git/Repository.kt | 331 + .../kotlin/io/spine/gradle/git/UserInfo.kt | 42 + .../gradle/github/pages/AuthorEmail.kt | 12 +- .../github/pages/RepositoryExtensions.kt | 67 + .../io/spine/gradle/github/pages/SshKey.kt | 124 + .../github/pages/TaskName.kt} | 26 +- .../io/spine/gradle/github/pages/Update.kt | 160 + .../gradle/github/pages/UpdateGitHubPages.kt | 209 + .../pages/UpdateGitHubPagesExtension.kt | 83 +- .../kotlin/io/spine/gradle/java/Linters.kt | 61 + .../spine/{internal => }/gradle/java/Tasks.kt | 8 +- .../{internal => }/gradle/javac/ErrorProne.kt | 8 +- .../{internal => }/gradle/javac/Javac.kt | 6 +- .../{internal => }/gradle/javadoc/Encoding.kt | 6 +- .../gradle/javadoc/ExcludeInternalDoclet.kt | 26 +- .../gradle/javadoc/JavadocConfig.kt | 41 +- .../gradle/javadoc/JavadocTag.kt | 6 +- .../gradle/javascript/JsContext.kt | 11 +- .../gradle/javascript/JsEnvironment.kt | 8 +- .../gradle/javascript/JsExtension.kt | 14 +- .../gradle/javascript/plugin/Idea.kt | 8 +- .../gradle/javascript/plugin/JsPlugins.kt | 14 +- .../gradle/javascript/plugin/McJs.kt | 6 +- .../gradle/javascript/plugin/Protobuf.kt | 18 +- .../gradle/javascript/task/Assemble.kt | 37 +- .../gradle/javascript/task/Check.kt | 33 +- .../gradle/javascript/task/Clean.kt | 25 +- .../gradle/javascript/task/IntegrationTest.kt | 24 +- .../gradle/javascript/task/JsTasks.kt | 42 +- .../gradle/javascript/task/LicenseReport.kt | 22 +- .../gradle/javascript/task/Publish.kt | 35 +- .../gradle/javascript/task/Webpack.kt | 25 +- .../gradle/kotlin/KotlinConfig.kt | 30 +- .../gradle/publish/CheckVersionIncrement.kt | 52 +- .../gradle/publish/CloudArtifactRegistry.kt | 16 +- .../gradle/publish/CloudRepo.kt | 11 +- .../publish/CustomPublicationHandler.kt | 70 + .../gradle/publish/GitHubPackages.kt | 61 +- .../io/spine/gradle/publish/IncrementGuard.kt | 112 + .../kotlin/io/spine/gradle/publish/JarDsl.kt | 73 + .../io/spine/gradle/publish/ProtoExts.kt | 93 + .../gradle/publish/PublicationHandler.kt | 287 + .../io/spine/gradle/publish/PublishingExts.kt | 364 ++ .../publish/PublishingRepos.kt} | 22 +- .../io/spine/gradle/publish/ShadowJarExts.kt | 82 + .../spine/gradle/publish/SpinePublishing.kt | 492 ++ .../publish/StandardJavaPublicationHandler.kt | 133 + .../Pmd.kt => gradle/repo/Credentials.kt} | 18 +- .../gradle => gradle/repo}/RepoSlug.kt | 13 +- .../io/spine/gradle/repo/Repositories.kt | 231 + .../kotlin/io/spine/gradle/repo/Repository.kt | 138 + .../gradle/report/coverage/KoverConfig.kt | 390 ++ .../gradle/report/coverage/SiblingCoverage.kt | 114 + .../gradle/report/license/Configuration.kt | 6 +- .../gradle/report/license/LicenseReporter.kt | 72 +- .../report/license/MarkdownReportRenderer.kt | 13 +- .../report/license/ModuleDataExtensions.kt | 15 +- .../gradle/report/license/Paths.kt | 28 +- .../report/license/ProjectDependencies.kt | 8 +- .../gradle/report/license/Tasks.kt | 6 +- .../gradle/report/license/Template.kt | 27 +- .../gradle/report/pom/DependencyScope.kt | 6 +- .../gradle/report/pom/DependencyWriter.kt | 77 +- .../gradle/report/pom/InceptionYear.kt | 13 +- .../gradle/report/pom/MarkupExtensions.kt | 6 +- .../gradle/report/pom/ModuleDependency.kt | 29 +- .../gradle/report/pom/PomFormatting.kt | 10 +- .../gradle/report/pom/PomGenerator.kt | 46 +- .../gradle/report/pom/PomXmlWriter.kt | 26 +- .../gradle/report/pom/ProjectMetadata.kt | 6 +- .../gradle/report/pom/ScopedDependency.kt | 66 +- .../gradle/report/pom/SpineLicense.kt | 6 +- .../gradle/report/pom/VersionComparator.kt | 115 + .../{internal => }/gradle/testing/Logging.kt | 23 +- .../gradle/testing/Multiproject.kt | 16 +- .../{internal => }/gradle/testing/Tasks.kt | 34 +- .../spine/gradle/testing/TestKitCoverage.kt | 159 + .../internal/dependency/CommonsCollections.kt | 38 - .../io/spine/internal/dependency/Dokka.kt | 76 - .../spine/internal/dependency/ErrorProne.kt | 59 - .../io/spine/internal/dependency/FindBugs.kt | 39 - .../io/spine/internal/dependency/Grpc.kt | 45 - .../io/spine/internal/dependency/JUnit.kt | 53 - .../io/spine/internal/dependency/Jackson.kt | 47 - .../io/spine/internal/dependency/Kotlin.kt | 41 - .../spine/internal/dependency/OsDetector.kt | 35 - .../io/spine/internal/dependency/ThreeTen.kt | 37 - .../io/spine/internal/gradle/Repositories.kt | 242 - .../io/spine/internal/gradle/Scripts.kt | 60 - .../io/spine/internal/gradle/VersionWriter.kt | 149 - .../internal/gradle/dokka/DokkaExtensions.kt | 61 - .../internal/gradle/github/pages/Update.kt | 197 - .../gradle/github/pages/UpdateGitHubPages.kt | 202 - .../gradle/javadoc/TaskContainerExtensions.kt | 40 - .../gradle/protobuf/ProtoTaskExtensions.kt | 119 - .../internal/gradle/publish/Artifacts.kt | 135 - .../internal/gradle/publish/IncrementGuard.kt | 92 - .../gradle/publish/MavenJavaPublication.kt | 155 - .../gradle/publish/PublishingConfig.kt | 125 - .../gradle/publish/SpinePublishing.kt | 409 -- .../io/spine/internal/gradle/publish/Tasks.kt | 110 - .../gradle/report/coverage/CodebaseFilter.kt | 113 - .../gradle/report/coverage/FileExtensions.kt | 129 - .../gradle/report/coverage/JacocoConfig.kt | 226 - .../src/main/kotlin/jacoco-kmm-jvm.gradle.kts | 87 + .../main/kotlin/jacoco-kotlin-jvm.gradle.kts | 80 + .../src/main/kotlin/jvm-module.gradle.kts | 176 + .../src/main/kotlin/kmp-module.gradle.kts | 193 + .../src/main/kotlin/kmp-publish.gradle.kts | 75 + .../src/main/kotlin/module-testing.gradle.kts | 120 + buildSrc/src/main/kotlin/module.gradle.kts | 31 + .../src/main/kotlin/pmd-settings.gradle.kts | 8 +- .../src/main/kotlin/test-module.gradle.kts | 57 + .../main/kotlin/uber-jar-module.gradle.kts | 207 + .../src/main/kotlin/write-manifest.gradle.kts | 169 + .../resources/dokka/styles/custom-styles.css | 8 +- .../gradle/docs/UpdatePluginVersionTest.kt | 119 + .../gradle/publish/IncrementGuardTest.kt | 79 + .../gradle/publish/SpinePublishingTest.kt | 260 + .../report/coverage/FileExtensionsTest.kt | 128 + .../license/DependencyReportOutputTest.kt | 104 + .../gradle/report/pom/DependencyWriterSpec.kt | 312 + .../report/pom/VersionComparatorSpec.kt | 87 + client-js/build.gradle.kts | 24 +- config | 2 +- firebase-web/build.gradle.kts | 14 +- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 6 +- gradlew | 50 +- gradlew.bat | 59 +- integration-tests/js-tests/build.gradle.kts | 14 +- integration-tests/test-app/build.gradle.kts | 2 +- license-report.md | 5308 ----------------- testutil-web/build.gradle.kts | 2 +- web/build.gradle.kts | 12 +- 272 files changed, 12341 insertions(+), 10044 deletions(-) create mode 100644 .github/workflows/check-links.yml create mode 100644 .github/workflows/ensure-reports-updated.yml create mode 100644 .github/workflows/remove-obsolete-artifacts-from-packages.yaml create mode 100644 .idea/live-templates/README.md create mode 100644 .idea/live-templates/Spine.xml create mode 100644 .idea/live-templates/User.xml delete mode 100644 .lift.toml create mode 100644 buildSrc/quality/checkstyle-suppressions.xml create mode 100644 buildSrc/quality/checkstyle.xml create mode 100644 buildSrc/quality/detekt-config.yml create mode 100644 buildSrc/quality/pmd.xml rename buildSrc/{src/main/kotlin/io/spine/internal/dependency/OpenCensus.kt => settings.gradle.kts} (79%) create mode 100644 buildSrc/src/main/kotlin/BuildExtensions.kt rename buildSrc/src/main/kotlin/{io/spine/internal/dependency/AutoService.kt => BuildSettings.kt} (65%) rename buildSrc/src/main/kotlin/{io/spine/internal/gradle => }/DependencyResolution.kt (53%) create mode 100644 buildSrc/src/main/kotlin/DocumentationSettings.kt create mode 100644 buildSrc/src/main/kotlin/DokkaExts.kt create mode 100644 buildSrc/src/main/kotlin/LicenseSettings.kt create mode 100644 buildSrc/src/main/kotlin/Strings.kt create mode 100644 buildSrc/src/main/kotlin/config-tester.gradle.kts create mode 100644 buildSrc/src/main/kotlin/detekt-code-analysis.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/dokka-for-java.gradle.kts rename buildSrc/src/main/kotlin/{io/spine/internal/gradle/report/coverage/FileFilter.kt => dokka-setup.gradle.kts} (61%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/Dependency.kt rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/report/coverage/PathMarker.kt => dependency/boms/Boms.kt} (55%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/boms/BomsPlugin.kt rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/publish/ProtoJar.kt => dependency/kotlinx/AtomicFu.kt} (60%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/publish/PublishingRepos.kt => dependency/kotlinx/Coroutines.kt} (55%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/kotlinx/DateTime.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/AutoCommon.kt => dependency/kotlinx/KotlinX.kt} (80%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/kotlinx/Serialization.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/JavaJwt.kt => dependency/lib/Aedile.kt} (75%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/ApacheHttp.kt (88%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/AppEngine.kt (84%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Asm.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/CheckerFramework.kt => dependency/lib/Auto.kt} (54%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/BouncyCastle.kt (88%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Caffeine.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/CheckStyle.kt => dependency/lib/Clikt.kt} (80%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/CommonsCli.kt (77%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/CommonsCodec.kt (86%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/CommonsLogging.kt (78%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/publish/ProtoLocators.kt => dependency/lib/Coroutines.kt} (52%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Firebase.kt (80%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Flogger.kt (68%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/GoogleApis.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/GoogleCloud.kt (90%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Grpc.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/LicenseReport.kt => dependency/lib/GrpcKotlin.kt} (67%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Gson.kt (79%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Guava.kt (77%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/HttpClient.kt (85%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/IntelliJ.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/J2ObjC.kt (66%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Jackson.kt rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/publish/DokkaJar.kt => dependency/lib/JavaDiffUtils.kt} (66%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/JavaJwt.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/JavaPoet.kt (79%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/JavaX.kt (74%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/JetBrainsAnnotations.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Klaxon.kt (83%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Kotlin.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/KotlinPoet.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/KotlinSemver.kt (85%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/KotlinX.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/lib/Log4j2.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Netty.kt (67%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/report/coverage/TaskName.kt => dependency/lib/Okio.kt} (74%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/HttpComponents.kt => dependency/lib/PalantirJavaFormat.kt} (69%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/publish/TestJar.kt => dependency/lib/Plexus.kt} (63%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Protobuf.kt (60%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Roaster.kt (65%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/lib}/Slf4J.kt (64%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Base.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/BaseTypes.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/Okio.kt => dependency/local/Change.kt} (71%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Logging.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/ModelCompiler.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/ProtoTap.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Reflect.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Spine.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/Plexus.kt => dependency/local/TestLib.kt} (71%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Time.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/test}/AssertK.kt (83%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/test/Hamcrest.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/test/JUnit.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/AutoValue.kt => dependency/test/Jacoco.kt} (78%) create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/test/Kotest.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/test/KotlinCompileTesting.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/dependency/test/Kover.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/Jetty.kt => dependency/test/OpenTest4J.kt} (73%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/AnimalSniffer.kt => dependency/test/SystemLambda.kt} (75%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/test}/TestKitTruth.kt (70%) rename buildSrc/src/main/kotlin/io/spine/{internal/dependency => dependency/test}/Truth.kt (75%) rename buildSrc/src/main/kotlin/io/spine/{internal/markup => docs}/MarkdownDocument.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/Build.kt (90%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/Clean.kt (92%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/Runtime.kt => gradle/Cli.kt} (53%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/ConfigTester.kt (82%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/ProjectExtensions.kt (75%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/RunBuild.kt (89%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/RunGradle.kt (84%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/SpineTaskGroup.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/StringExtensions.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/TaskName.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/base/Tasks.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/checkstyle/CheckStyleConfig.kt (80%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/DartContext.kt (92%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/DartEnvironment.kt (95%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/DartExtension.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/plugin/DartPlugins.kt (89%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/plugin/Protobuf.kt (78%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/task/Build.kt (87%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/task/DartTasks.kt (76%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/task/IntegrationTest.kt (81%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/dart/task/Publish.kt (86%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/docs/UpdatePluginVersion.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/fs/LazyTempPath.kt (82%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/github/pages => gradle/git}/Branch.kt (77%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/git/Repository.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/git/UserInfo.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/github/pages/AuthorEmail.kt (85%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/github/pages/RepositoryExtensions.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/github/pages/SshKey.kt rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/report/coverage/FileExtension.kt => gradle/github/pages/TaskName.kt} (65%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/github/pages/Update.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/github/pages/UpdateGitHubPages.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/github/pages/UpdateGitHubPagesExtension.kt (53%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/java/Linters.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/java/Tasks.kt (88%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javac/ErrorProne.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javac/Javac.kt (94%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javadoc/Encoding.kt (90%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javadoc/ExcludeInternalDoclet.kt (81%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javadoc/JavadocConfig.kt (80%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javadoc/JavadocTag.kt (90%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/JsContext.kt (86%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/JsEnvironment.kt (97%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/JsExtension.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/plugin/Idea.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/plugin/JsPlugins.kt (88%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/plugin/McJs.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/plugin/Protobuf.kt (85%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/Assemble.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/Check.kt (87%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/Clean.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/IntegrationTest.kt (88%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/JsTasks.kt (73%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/LicenseReport.kt (83%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/Publish.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/javascript/task/Webpack.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/kotlin/KotlinConfig.kt (76%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/publish/CheckVersionIncrement.kt (71%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/publish/CloudArtifactRegistry.kt (88%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/publish/CloudRepo.kt (86%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/CustomPublicationHandler.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/publish/GitHubPackages.kt (62%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/IncrementGuard.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/JarDsl.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/ProtoExts.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt rename buildSrc/src/main/kotlin/io/spine/{internal/gradle/github/pages/TaskName.kt => gradle/publish/PublishingRepos.kt} (72%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/ShadowJarExts.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/SpinePublishing.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/publish/StandardJavaPublicationHandler.kt rename buildSrc/src/main/kotlin/io/spine/{internal/dependency/Pmd.kt => gradle/repo/Credentials.kt} (79%) rename buildSrc/src/main/kotlin/io/spine/{internal/gradle => gradle/repo}/RepoSlug.kt (84%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/repo/Repositories.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/repo/Repository.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/report/coverage/KoverConfig.kt create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/report/coverage/SiblingCoverage.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/Configuration.kt (92%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/LicenseReporter.kt (59%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/MarkdownReportRenderer.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/ModuleDataExtensions.kt (92%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/Paths.kt (63%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/ProjectDependencies.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/Tasks.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/license/Template.kt (81%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/DependencyScope.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/DependencyWriter.kt (64%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/InceptionYear.kt (86%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/MarkupExtensions.kt (91%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/ModuleDependency.kt (79%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/PomFormatting.kt (93%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/PomGenerator.kt (67%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/PomXmlWriter.kt (78%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/ProjectMetadata.kt (96%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/ScopedDependency.kt (69%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/report/pom/SpineLicense.kt (93%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/report/pom/VersionComparator.kt rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/testing/Logging.kt (84%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/testing/Multiproject.kt (83%) rename buildSrc/src/main/kotlin/io/spine/{internal => }/gradle/testing/Tasks.kt (69%) create mode 100644 buildSrc/src/main/kotlin/io/spine/gradle/testing/TestKitCoverage.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/CommonsCollections.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/Dokka.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/ErrorProne.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/FindBugs.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/Grpc.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/JUnit.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/Jackson.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/Kotlin.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/OsDetector.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/dependency/ThreeTen.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/Repositories.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/Scripts.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/VersionWriter.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/dokka/DokkaExtensions.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/github/pages/Update.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/github/pages/UpdateGitHubPages.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/javadoc/TaskContainerExtensions.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/protobuf/ProtoTaskExtensions.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/Artifacts.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/IncrementGuard.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/MavenJavaPublication.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/PublishingConfig.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/SpinePublishing.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/publish/Tasks.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/report/coverage/CodebaseFilter.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/report/coverage/FileExtensions.kt delete mode 100644 buildSrc/src/main/kotlin/io/spine/internal/gradle/report/coverage/JacocoConfig.kt create mode 100644 buildSrc/src/main/kotlin/jacoco-kmm-jvm.gradle.kts create mode 100644 buildSrc/src/main/kotlin/jacoco-kotlin-jvm.gradle.kts create mode 100644 buildSrc/src/main/kotlin/jvm-module.gradle.kts create mode 100644 buildSrc/src/main/kotlin/kmp-module.gradle.kts create mode 100644 buildSrc/src/main/kotlin/kmp-publish.gradle.kts create mode 100644 buildSrc/src/main/kotlin/module-testing.gradle.kts create mode 100644 buildSrc/src/main/kotlin/module.gradle.kts create mode 100644 buildSrc/src/main/kotlin/test-module.gradle.kts create mode 100644 buildSrc/src/main/kotlin/uber-jar-module.gradle.kts create mode 100644 buildSrc/src/main/kotlin/write-manifest.gradle.kts create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/docs/UpdatePluginVersionTest.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/publish/IncrementGuardTest.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/publish/SpinePublishingTest.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/report/coverage/FileExtensionsTest.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/report/license/DependencyReportOutputTest.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/report/pom/DependencyWriterSpec.kt create mode 100644 buildSrc/src/test/kotlin/io/spine/gradle/report/pom/VersionComparatorSpec.kt delete mode 100644 license-report.md diff --git a/.codecov.yml b/.codecov.yml index b5739f89b..e05fc77b6 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -12,15 +12,15 @@ coverage: - "**/test/**/*" status: # https://docs.codecov.com/docs/github-checks#yaml-configuration-for-github-checks-and-codecov - patch: false + patch: off # https://docs.codecov.com/docs/commit-status project: default: target: auto threshold: 0.05% - base: auto paths: - - "src" + - "src/main/**/*" + - "**/src/main/**" if_ci_failed: error informational: false only_pulls: true diff --git a/.github/workflows/build-on-ubuntu.yml b/.github/workflows/build-on-ubuntu.yml index 01252d9f6..6884a40f7 100644 --- a/.github/workflows/build-on-ubuntu.yml +++ b/.github/workflows/build-on-ubuntu.yml @@ -1,40 +1,57 @@ -name: Build under Ubuntu +name: Ubuntu CI on: push jobs: build: + name: Build on Ubuntu runs-on: ubuntu-latest + concurrency: # Avoid canceling in-progress runs for the same branch. + group: ubuntu-ci-${{ github.ref }} + cancel-in-progress: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 + with: + submodules: 'true' - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v5 with: - java-version: 11 + java-version: 17 distribution: zulu - cache: gradle - - uses: actions/setup-node@v2 - with: - node-version: 'lts/*' + - uses: gradle/actions/setup-gradle@v6 - - name: Pull config - run: git submodule update --init --recursive + # Mirrors the pagefile step in build-on-windows.yml. The Linux runner + # ships with effectively no swap, so a memory peak becomes an instant + # OOM kill; this gives the kernel somewhere to fall back to. + - name: Add swap space + uses: pierotofy/set-swap-space@v1.0 + with: + swap-size-gb: 8 - - name: Build project and run tests + - name: Build project, run tests shell: bash run: ./gradlew build --stacktrace + # `build` does not run Dokka — its tasks are gated to the publishing + # graph — so `dokkaGenerate` is appended to surface documentation + # warnings on each push, before merge, instead of only in the post-merge + # `Publish` job. `failOnWarning` is enabled in the Dokka setup. + - name: Check documentation + run: ./gradlew dokkaGenerate --stacktrace + # See: https://github.com/marketplace/actions/junit-report-action - name: Publish Test Report - uses: mikepenz/action-junit-report@v2.8.4 + uses: mikepenz/action-junit-report@v4.0.3 if: always() # always run even if the previous step fails with: - report_paths: '**/build/test-results/test/TEST-*.xml' + report_paths: '**/build/test-results/**/TEST-*.xml' + require_tests: true # will fail workflow if test reports not found - name: Upload code coverage report - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v4 with: - fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true verbose: true diff --git a/.github/workflows/build-on-windows.yml b/.github/workflows/build-on-windows.yml index 3506d13d6..0a07cfab6 100644 --- a/.github/workflows/build-on-windows.yml +++ b/.github/workflows/build-on-windows.yml @@ -1,35 +1,37 @@ -name: Build under Windows +name: Windows CI on: pull_request jobs: build: runs-on: windows-latest + name: Build on Windows steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 + with: + submodules: recursive + fetch-depth: 0 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v5 with: - java-version: 11 + java-version: 17 distribution: zulu - cache: gradle - - uses: actions/setup-node@v2 - with: - node-version: 'lts/*' + - uses: gradle/actions/setup-gradle@v6 - - name: Pull config - run: git submodule update --init --recursive + # See: https://github.com/al-cheb/configure-pagefile-action + - name: Configure Pagefile + uses: al-cheb/configure-pagefile-action@v1.3 - name: Build project and run tests shell: cmd - # For the reason on `--no-daemon` see https://github.com/actions/cache/issues/454 - run: gradlew.bat build --stacktrace --no-daemon + run: gradlew.bat build --stacktrace # See: https://github.com/marketplace/actions/junit-report-action - name: Publish Test Report - uses: mikepenz/action-junit-report@v2.8.4 + uses: mikepenz/action-junit-report@v4.0.3 if: always() # always run even if the previous step fails with: - report_paths: '**/build/test-results/test/TEST-*.xml' + report_paths: '**/build/test-results/**/TEST-*.xml' + require_tests: true diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml new file mode 100644 index 000000000..6755ff910 --- /dev/null +++ b/.github/workflows/check-links.yml @@ -0,0 +1,216 @@ +name: Check Links + +# Trigger only when the docs site, the link checker config, or this workflow +# itself changes — unrelated PRs do not need to pay the build+check cost. +on: + pull_request: + paths: + - 'docs/**' + - 'site/**' + - 'lychee.toml' + - '.github/workflows/check-links.yml' + workflow_dispatch: + +env: + HUGO_VERSION: 0.161.1 + LYCHEE_RELEASE: "lychee-x86_64-unknown-linux-gnu.tar.gz" + LYCHEE_VERSION_TAG: "lychee-v0.24.2" + # SHA256 of the above tarball, pinned at download time. Update alongside + # LYCHEE_VERSION_TAG whenever the binary is upgraded. + LYCHEE_SHA256: "1f4e0ef7f6554a6ed33dd7ac144fb2e1bbed98598e7af973042fc5cd43951c9a" + # Force Hugo to write its module cache where the cache step actually + # restores from. Hugo's default on Linux is `~/.cache/hugo_cache` + # (or `$TMPDIR/hugo_cache_$USER`), neither of which matches the + # `path: /tmp/hugo_cache` cache step below — without this env var, + # the cache would silently never hit. + HUGO_CACHEDIR: /tmp/hugo_cache + +jobs: + check-links: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + steps: + - name: Checkout + uses: actions/checkout@v6 + + # Detect the Hugo site root (`docs/` or `site/`) by looking for a Hugo + # config file. Hugo config may live directly in the site root or in a + # `config/` or `config/_default/` subdirectory (both layouts are valid). + # Outputs `present=true|false` and `work_dir` (the directory where + # `npm ci` / `hugo` commands should run — either `$dir/_preview` for + # repos that use a separate preview sub-tree, or `$dir` for repos whose + # Node/Hugo setup lives at the site root). + # When neither directory has a Hugo config, the job short-circuits to a + # success so that this shared workflow stays green on repos that do not + # host a Hugo site at all. + - name: Detect docs site + id: docs + run: | + for dir in docs site; do + for cfg in hugo.toml hugo.yaml \ + config/hugo.toml config/hugo.yaml \ + config/_default/hugo.toml config/_default/hugo.yaml; do + if [ -f "$dir/$cfg" ]; then + if [ -f "$dir/_preview/package-lock.json" ]; then + echo "work_dir=$dir/_preview" >> "$GITHUB_OUTPUT" + echo "present=true" >> "$GITHUB_OUTPUT" + echo "::notice::Hugo site found under $dir/ (work_dir: $dir/_preview)" + elif [ -f "$dir/package-lock.json" ]; then + echo "work_dir=$dir" >> "$GITHUB_OUTPUT" + echo "present=true" >> "$GITHUB_OUTPUT" + echo "::notice::Hugo site found under $dir/ (work_dir: $dir)" + else + echo "present=false" >> "$GITHUB_OUTPUT" + echo "::notice::Hugo config found in $dir/ but no package-lock.json found — skipping link check." + fi + exit 0 + fi + done + done + echo "present=false" >> "$GITHUB_OUTPUT" + echo "::notice::No Hugo site found under docs/ or site/ — skipping link check." + + - name: Setup Hugo + if: steps.docs.outputs.present == 'true' + uses: peaceiris/actions-hugo@v3 + with: + hugo-version: ${{ env.HUGO_VERSION }} + extended: true + + # `actions/setup-node@v4` ships with built-in npm caching that hashes + # the lockfile and restores `~/.npm`. We use that instead of a + # standalone `actions/cache@v4` block so there is only one source of + # truth for the cache key (no drift between two layers). + - name: Setup Node + if: steps.docs.outputs.present == 'true' + uses: actions/setup-node@v4 + with: + node-version: '26' + cache: 'npm' + cache-dependency-path: ${{ steps.docs.outputs.work_dir }}/package-lock.json + + # `HUGO_CACHEDIR=/tmp/hugo_cache` (set in `env:` above) makes Hugo + # actually write to the path this step restores from. The key hashes + # both possible go.sum locations so adding/removing a Hugo module + # invalidates the cache deterministically regardless of site root. + - name: Cache Hugo Modules + if: steps.docs.outputs.present == 'true' + uses: actions/cache@v4 + with: + path: /tmp/hugo_cache + key: ${{ runner.os }}-hugomod-${{ hashFiles('docs/**/go.sum', 'site/**/go.sum') }} + restore-keys: | + ${{ runner.os }}-hugomod- + + - name: Install Dependencies + if: steps.docs.outputs.present == 'true' + working-directory: ${{ steps.docs.outputs.work_dir }} + run: npm ci + + - name: Build docs preview site + if: steps.docs.outputs.present == 'true' + working-directory: ${{ steps.docs.outputs.work_dir }} + run: hugo -e development + + # Cache Lychee results to avoid hitting rate limits. + # Key on the lychee.toml hash so that exclude-list edits (e.g. removing + # an exclude pattern) invalidate the cache deterministically; otherwise + # stale `200 OK` entries for the now-checked URLs would be trusted until + # `max_cache_age` expires. + - name: Cache Lychee results + if: steps.docs.outputs.present == 'true' + uses: actions/cache@v4 + with: + path: .lycheecache + key: cache-lychee-${{ runner.os }}-${{ hashFiles('lychee.toml') }} + restore-keys: | + cache-lychee-${{ runner.os }}- + + # The cache key includes LYCHEE_VERSION_TAG so a version bump + # automatically pulls a fresh binary instead of reusing the old one. + # The restore-keys fallback lets a release-filename tweak (rare) reuse + # the existing cached binary for the same version-tag instead of paying + # for a fresh download. + - name: Cache Lychee executable + if: steps.docs.outputs.present == 'true' + id: cache-lychee + uses: actions/cache@v4 + with: + path: lychee + key: ${{ runner.os }}-${{ env.LYCHEE_VERSION_TAG }}-${{ env.LYCHEE_RELEASE }} + restore-keys: | + ${{ runner.os }}-${{ env.LYCHEE_VERSION_TAG }}- + + # We use Lychee directly instead of a GitHub Action because it + # must have access to the local Hugo server, which is not visible + # from the Docker-based action. + # + # `if:` gating uses `hashFiles('lychee/lychee')` rather than + # `steps.cache-lychee.outputs.cache-hit != 'true'`. Per `actions/cache` + # docs, `cache-hit` is only `'true'` on an EXACT key match — a restore + # via `restore-keys` reports `cache-hit == 'false'`, even though the + # binary is present in the workspace. Re-downloading in that case + # would defeat the point of the fallback. `hashFiles` returns an empty + # string when the file is absent, so this guard runs the download iff + # neither the exact key nor any restore-key restored the binary. + - name: Download Lychee executable + uses: robinraju/release-downloader@v1.7 + if: steps.docs.outputs.present == 'true' && hashFiles('lychee/lychee') == '' + with: + repository: "lycheeverse/lychee" + tag: ${{ env.LYCHEE_VERSION_TAG }} + fileName: ${{ env.LYCHEE_RELEASE }} + + - name: Verify Lychee checksum + if: steps.docs.outputs.present == 'true' && hashFiles('lychee/lychee') == '' + run: | + echo "${{ env.LYCHEE_SHA256 }} ${{ env.LYCHEE_RELEASE }}" | sha256sum --check --strict + + # The v0.24.2 tarball contains a top-level directory + # (e.g. `lychee-x86_64-unknown-linux-gnu/lychee`), so `--strip-components=1` + # flattens it to `lychee/lychee` — matching what the companion + # `check-links` skill does locally and what the next step expects. + - name: Extract Lychee executable + if: steps.docs.outputs.present == 'true' && hashFiles('lychee/lychee') == '' + run: | + mkdir -p lychee && + tar -xzf ${{ env.LYCHEE_RELEASE }} --strip-components=1 -C lychee + + # 1. In the generated HTML, some inner links will have absolute URLs and + # the link checker will attempt to fetch them. That's why we need + # a server. Sadly, link checkers have no settings to address this. + # 2. Output redirection is necessary for nohup in GitHub Actions. + # 3. Sleep + `curl` readiness check make sure the server is actually + # serving HTTP before the next step runs Lychee. Without the curl + # probe a silent startup failure (port already bound, missing + # Hugo module, build error surfacing after `nohup` returns 0) + # would manifest 60 s later as "every URL unreachable" Lychee + # errors instead of pointing at the real cause. Mirrors the + # `pgrep -F` guard in the companion `check-links` skill. + # 4. `--port 1313` is set explicitly (not relying on Hugo's default) so + # the coupling with `--base-url http://localhost:1313/` in the next + # Lychee step is visible — change one, change the other. + - name: Start Hugo server + if: steps.docs.outputs.present == 'true' + working-directory: ${{ steps.docs.outputs.work_dir }} + run: | + nohup hugo server \ + --environment development \ + --port 1313 \ + > nohup.out 2> nohup.err < /dev/null & + sleep 5 + if ! curl -sf http://localhost:1313/ > /dev/null; then + echo "ERROR: Hugo server did not respond on port 1313." >&2 + echo "--- stdout ---" >&2; cat nohup.out >&2 || true + echo "--- stderr ---" >&2; cat nohup.err >&2 || true + exit 1 + fi + + - name: Check links + if: steps.docs.outputs.present == 'true' + run: | + ./lychee/lychee --config lychee.toml --timeout 60 \ + --base-url http://localhost:1313/ \ + '${{ steps.docs.outputs.work_dir }}/public/**/*.html' diff --git a/.github/workflows/ensure-reports-updated.yml b/.github/workflows/ensure-reports-updated.yml new file mode 100644 index 000000000..20deb3f69 --- /dev/null +++ b/.github/workflows/ensure-reports-updated.yml @@ -0,0 +1,35 @@ +# Ensures that the license report files were modified in this PR. +# +# The check runs only for pull requests targeting a default (`master`/`main`) or +# a release-line (e.g. `2.x-jdk8-master`) branch. The report files embed the project +# version, so they are refreshed by the branches which bump it. Pull requests +# targeting auxiliary branches are not checked. +# +# The base branch is checked inside the job rather than via the `branches` filter: +# a workflow skipped by branch filtering leaves its check in the `Pending` state, +# blocking PRs which require it, while a job skipped via `if` reports `skipped`, +# which satisfies required status checks. + +name: License Reports + +on: + pull_request: + +jobs: + check: + name: Ensure license reports are updated + runs-on: ubuntu-latest + # Default and release-line branches, e.g. `master`, `main`, `2.x-jdk8-master`. + if: endsWith(github.base_ref, 'master') || endsWith(github.base_ref, 'main') + + steps: + - uses: actions/checkout@v6 + with: + # Configure the checkout of all branches so that it is possible to run the comparison. + fetch-depth: 0 + # Check out the `config` submodule to fetch the required script file. + submodules: true + + - name: Check that dependency report files are modified + shell: bash + run: chmod +x ./config/scripts/ensure-reports-updated.sh && ./config/scripts/ensure-reports-updated.sh diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 72435c635..fc0872b4c 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -1,4 +1,4 @@ -name: Validate Gradle Wrapper +name: Gradle Wrapper validation on: push: branches: @@ -9,10 +9,11 @@ on: jobs: validation: - name: Validation + name: Validate Gradle Wrapper runs-on: ubuntu-latest steps: - name: Checkout latest code - uses: actions/checkout@v2 + uses: actions/checkout@v6 + - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v4 diff --git a/.github/workflows/increment-guard.yml b/.github/workflows/increment-guard.yml index c96b081b0..f20b4bed6 100644 --- a/.github/workflows/increment-guard.yml +++ b/.github/workflows/increment-guard.yml @@ -1,28 +1,39 @@ -# Ensures that the current lib version is not yet published but executing the Gradle +# Ensures that the current lib version is not yet published by executing the Gradle # `checkVersionIncrement` task. +# +# The check runs only for pull requests targeting a default (`master`/`main`) or +# a release-line (e.g. `2.x-jdk8-master`) branch. It is the responsibility of a branch +# which aims to merge into such a branch to bump the version. Auxiliary branches +# do not deal with the versions in the release cycle and are not guarded. +# +# The base branch is checked inside the job rather than via the `branches` filter: +# a workflow skipped by branch filtering leaves its check in the `Pending` state, +# blocking PRs which require it, while a job skipped via `if` reports `skipped`, +# which satisfies required status checks. -name: Check version increment +name: Version Guard on: - push: - branches: - - '**' + pull_request: jobs: - build: + check: + name: Check version increment runs-on: ubuntu-latest + # Default and release-line branches, e.g. `master`, `main`, `2.x-jdk8-master`. + if: endsWith(github.base_ref, 'master') || endsWith(github.base_ref, 'main') steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 + with: + submodules: 'true' - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v5 with: - java-version: 11 + java-version: 17 distribution: zulu - cache: gradle - - name: Pull config - run: git submodule update --init --recursive + - uses: gradle/actions/setup-gradle@v6 - name: Check version is not yet published shell: bash diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c8954df48..df8f6cd01 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,21 +6,20 @@ on: jobs: publish: + name: Publish to Maven repositories runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + steps: + - uses: actions/checkout@v6 with: - java-version: 11 - distribution: zulu - cache: gradle + submodules: 'true' - - uses: actions/setup-node@v2 + - uses: actions/setup-java@v5 with: - node-version: 'lts/*' + java-version: 17 + distribution: zulu - - run: git submodule update --init --recursive + - uses: gradle/actions/setup-gradle@v6 - name: Decrypt CloudRepo credentials run: ./config/scripts/decrypt.sh "$CLOUDREPO_CREDENTIALS_KEY" ./.github/keys/cloudrepo.properties.gpg ./cloudrepo.properties @@ -62,6 +61,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/.github/workflows/remove-obsolete-artifacts-from-packages.yaml b/.github/workflows/remove-obsolete-artifacts-from-packages.yaml new file mode 100644 index 000000000..62242c7bb --- /dev/null +++ b/.github/workflows/remove-obsolete-artifacts-from-packages.yaml @@ -0,0 +1,73 @@ +# +# Periodically removes obsolete artifacts from GitHub Packages. +# +# Only non-release artifacts—those containing "SNAPSHOT" in their version name—are eligible +# for removal. The latest non-release artifacts will be retained, with the exact number determined +# by the `VERSION_COUNT_TO_KEEP` environment variable. +# +# Please note the following details: +# +# 1. An artifact cannot be deleted if it is public and has been downloaded more than 5,000 times. +# In this scenario, contact GitHub support for further assistance. +# +# 2. This workflow only applies to artifacts published from this repository. +# +# 3. A maximum of 100 artifacts can be removed per run from each package; +# if there are more than 100 obsolete artifacts, either manually restart the workflow +# or wait for the next scheduled removal. +# +# 4. When artifacts with version `x.x.x-SNAPSHOT` are published, GitHub automatically appends +# the current timestamp, resulting in versions like `x.x.x-SNAPSHOT.20241024.173759`. +# All such artifacts are grouped into one package and treated as a single package +# in GitHub Packages with the version `x.x.x-SNAPSHOT`. Consequently, it is not possible +# to remove obsolete versions within a package; only the entire package can be deleted. +# + +name: Remove obsolete Maven artifacts from GitHub Packages + +on: + schedule: + - cron: '0 0 * * *' # Run every day at midnight. + +env: + VERSION_COUNT_TO_KEEP: 5 # Number of most recent SNAPSHOT versions to retain. + +jobs: + retrieve-package-names: + name: Retrieve package names + runs-on: ubuntu-latest + outputs: + package-names: ${{ steps.request-package-names.outputs.package-names }} + steps: + - uses: actions/checkout@v6 + with: + submodules: 'true' + + - name: Retrieve the names of packages + id: request-package-names + shell: bash + run: | + repoName=$(echo ${{ github.repository }} | cut -d '/' -f2) + chmod +x ./config/scripts/request-package-names.sh + ./config/scripts/request-package-names.sh ${{ github.token }} \ + $repoName ${{ github.repository_owner }} ./package-names.json + echo "package-names=$(<./package-names.json)" >> $GITHUB_OUTPUT + + delete-obsolete-artifacts: + name: Delete obsolete artifacts + needs: retrieve-package-names + runs-on: ubuntu-latest + strategy: + matrix: + package-name: ${{ fromJson(needs.retrieve-package-names.outputs.package-names) }} + steps: + - name: Remove obsolete artifacts from '${{ matrix.package-name }}' package + uses: actions/delete-package-versions@v5 + with: + owner: ${{ github.repository_owner }} + package-name: ${{ matrix.package-name }} + package-type: 'maven' + token: ${{ github.token }} + min-versions-to-keep: ${{ env.VERSION_COUNT_TO_KEEP }} + # Ignores artifacts that do not contain the word "SNAPSHOT". + ignore-versions: '^(?!.+SNAPSHOT).*$' diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 809943cce..f60c2734a 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,5 +1,6 @@ + - + \ No newline at end of file diff --git a/.idea/copyright/TeamDev_Open_Source.xml b/.idea/copyright/TeamDev_Open_Source.xml index 14d7385ef..cea7fede3 100644 --- a/.idea/copyright/TeamDev_Open_Source.xml +++ b/.idea/copyright/TeamDev_Open_Source.xml @@ -1,6 +1,6 @@ - diff --git a/.idea/dictionaries/common.xml b/.idea/dictionaries/common.xml index c6d06b803..d1c3a7bfe 100644 --- a/.idea/dictionaries/common.xml +++ b/.idea/dictionaries/common.xml @@ -5,6 +5,7 @@ arraybuffer aspx bytebuffer + callees closeables cqrs dartdocs @@ -23,6 +24,8 @@ handshaker hohpe idempotency + jspecify + kotest lempira liskov melnik @@ -44,15 +47,18 @@ processmanager procman proto's + protodata protos sfixed stderr stringifier stringifiers + substituter switchman testutil threeten tuples + unicast unregister unregistering unregisters @@ -62,4 +68,4 @@ yevsyukov - + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index d4e24101b..7be402da6 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -27,6 +27,9 @@