Credit Spine Compiler codegen execution to coverage#727
Conversation
Port the `buildSrc` helpers from SpineEventEngine/validation#317: - `enableSpineCompilerCoverage()` attaches the standalone JaCoCo agent to the forked `launch*SpineCompiler` JVMs and declares each per-task `.exec` as a cacheable task output. - `KoverConfig` feeds those exec files into the root report's `additionalBinaryReports`, so out-of-process codegen execution is credited to the coverage Codecov ingests. - The JaCoCo agent coordinate is centralized as `Jacoco.agent`, shared with `enableTestKitCoverage()`. Deviations from the source PR: KDoc generalized (no validation-specific module names), duplicate helpers merged (`execFiles`, and the Kover task predicate now reuses `consumesCoverageBinaryReports()` from `SiblingCoverage.kt`), and an early-return guard makes `enableSpineCompilerCoverage()` idempotent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extend the `porting-buildsrc-from-consumer-repos` memory with the two adaptations this port surfaced: `config`-only detekt coverage of `buildSrc`, and generalizing consumer-specific KDoc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Ports Spine Compiler out-of-process coverage wiring into config’s buildSrc so consumer repositories can optionally attribute codegen/plugin execution in forked launch*SpineCompiler JVMs to their root Kover/JaCoCo coverage reports.
Changes:
- Add
enableSpineCompilerCoverage()to attach the JaCoCo agent tolaunch*SpineCompilerJavaExectasks and publish per-task.execoutputs. - Extend
KoverConfigto include compiler-produced.execfiles in the root aggregated report, and deduplicate exec-file discovery logic. - Centralize JaCoCo agent coordinates as
Jacoco.agentand reuse it from existing TestKit coverage helper.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| buildSrc/src/main/kotlin/io/spine/gradle/testing/TestKitCoverage.kt | Switches TestKit agent dependency to the new centralized Jacoco.agent coordinate. |
| buildSrc/src/main/kotlin/io/spine/gradle/testing/SpineCompilerCoverage.kt | Introduces the new helper that instruments forked Spine Compiler JavaExec launch tasks and wires root Kover tasks to depend on them. |
| buildSrc/src/main/kotlin/io/spine/gradle/report/coverage/SiblingCoverage.kt | Promotes consumesCoverageBinaryReports() for reuse and updates KDoc to include compiler-produced binary data. |
| buildSrc/src/main/kotlin/io/spine/gradle/report/coverage/KoverConfig.kt | Adds compiler .exec files to root additionalBinaryReports and consolidates exec-file listing logic. |
| buildSrc/src/main/kotlin/io/spine/dependency/test/Jacoco.kt | Adds Jacoco.agent Maven coordinate constant for the standalone runtime agent JAR. |
| .agents/tasks/port-compiler-coverage.md | Adds an agent task log documenting the port rationale and verification steps. |
| .agents/memory/project/porting-buildsrc-from-consumer-repos.md | Documents recurring porting adaptations (detekt and KDoc generalization) for future ports. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82e0c5bb2a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Address Copilot review feedback on PR #727: the `-javaagent` argument is added in `doFirst`, so the agent coordinate was not part of the `launch*SpineCompiler` task fingerprint. A JaCoCo version bump would then leave the cacheable launch tasks UP-TO-DATE/FROM-CACHE, serving a stale `.exec` written by the previous agent. Declare the agent *coordinate* (`Jacoco.agent`) as an `inputs.property` so a version bump invalidates the tasks and regenerates the exec. The coordinate string — not the resolved absolute JAR path — is tracked, so the cache key stays machine-independent, preserving the cross-machine cache reuse the `doFirst` attachment was designed to protect. This also brings the helper to parity with `enableTestKitCoverage()`, which already declares its agent as a task input. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address Codex review feedback (P2) on PR #727: the root report gathered Spine Compiler coverage by scanning every subproject's `build/jacoco-compiler/` directory. In an un-`clean`ed workspace a stale `.exec` from a removed `launch*SpineCompiler` task — or from a module that stopped enabling the helper — lingered and was still credited, inflating the root coverage. Collect the `.exec` files from the declared outputs of each subproject's currently configured launch tasks instead of scanning the directory. A removed task is no longer in the collection, and a task whose module disabled the helper no longer declares an exec output, so neither stale file is credited. This mirrors the existing `SiblingCoverage.execFilesOf` pattern (map current tasks, not a directory) while preserving the launch tasks' cacheability — unlike `enableTestKitCoverage()`, which wipes its directory and must therefore disable caching. `isSpineCompilerLaunchTask()` is promoted to `internal` for reuse by `KoverConfig`; `COMPILER_COVERAGE_DIR` is no longer needed there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@alexander-yevsyukov this is going to be a long wait :( |
Here's what we have in the ruleset for this repo:
I think we're having a GitHub issue here. |
This was a org-wide ruleset which applied after we upgraded our org to Team. I've turned it off. |



What & why
Ports the
buildSrccoverage helpers fromvalidation#317
into
config, so every consumer repo receives them via./config/pull.The Spine Compiler runs plugin code — renderers, option generators, and
other codegen plugins — in a forked
launch*SpineCompilerJVM during thebuild, which Kover/JaCoCo do not instrument. That out-of-process execution is
otherwise reported at ~0% line coverage even though each repo's
.protofixtures exercise it on every build. In
validation, wiring this in took theroot report from 12% → 86%. This change distributes the mechanism; each
consumer opts in with a single
subprojects { enableSpineCompilerCoverage() }line in its own root build script (that wiring stays consumer-owned and is
not part of this PR).
How
enableSpineCompilerCoverage()(newbuildSrc/.../gradle/testing/SpineCompilerCoverage.kt) attaches-javaagent:<JaCoCo agent>=destfile=…/<task>.exec,append=falseto everylaunch*SpineCompilerJavaExectask, one exec file per launch variant..execis declared as a task output, so the launch tasks staycacheable: a
JavaExecblocks until the fork exits and the agent flusheson exit, so the file is on disk when the action returns. Coverage survives
both an
UP-TO-DATEskip and aFROM-CACHEhit — unlike the TestKit workerdaemon, which is why
enableTestKitCoverage()must instead disable caching.KoverConfigfeeds the exec files into the root report'sadditionalBinaryReports(the report Codecov ingests) and orders thekover*Report/kover*Verifytasks after the launch tasks.Jacoco.agent, shared withenableTestKitCoverage()(which previously inlined the same literal).Deviations from the source PR (behavior identical)
java/contextmodules,
JavaValidationPlugin) removed, since these files land in ~40 repos.configruns detekt overbuildSrc(consumersdon't); the verbatim port tripped
TooManyFunctions. The twintestKitExecFiles/compilerExecFileshelpers are now oneexecFiles(project, dirName), and the Kover-task predicate reuses thepre-existing
consumesCoverageBinaryReports()fromSiblingCoverage.kt(promoted
private→internal) rather than duplicating it.enableSpineCompilerCoverage()safe to call more than once per project; without it a second call would
append a second
-javaagent:and double-load the agent in the fork.Verification
JAVA_HOME=17 ./gradlew :buildSrc:build detekt— green (tests included).config's root has nobuildlifecycle task and does not registerdokkaGenerate, so this is the applicable command.version.gradle.ktsinconfig, so the version-bump gate is notapplicable.
spine-code-review,kotlin-engineer,review-docs,dependency-audit— all APPROVE.🤖 Generated with Claude Code