Skip to content

Fix the buildDependants task - #805

Merged
alexander-yevsyukov merged 2 commits into
masterfrom
fix-config-tester-paths
Oct 19, 2026
Merged

alexander-yevsyukov merged 2 commits into
masterfrom
fix-config-tester-paths

Conversation

@alexander-yevsyukov

Copy link
Copy Markdown
Contributor

./gradlew buildDependants — the only check config has against its real
consumers — could not check out a single repository, and had been dead for a long
time. I hit this while trying to verify the dependency pins of #799 and had to fall
back to a standalone resolution probe.

Four defects, each of which alone was enough to break the task.

1. Relative paths were resolved against the Gradle daemon

config-tester.gradle.kts passed Paths.get("./") and File("./tmp"). Both are
resolved against user.dir, which for a daemon build is ~/.gradle/daemon/<version>/.
The repositories were checked out there, and the child build aborted with
"Directory '/Users/…/.gradle/daemon/9.8.1/tmp/base' does not contain a Gradle build".

Both paths now come from layout.projectDirectory. The tempFolder parameter lost its
File("./tmp") default so the same hazard cannot return, and ConfigTester now requires
both paths to be absolute.

2. A Stream was traversed twice

copyRecursively() filtered the walked tree for directories, then filtered the same
stream
for files — IllegalStateException: stream has already been operated upon or closed. Only the directories were created, so the overlaid buildSrc was an empty
skeleton and the repository under test failed with unresolved references. This one could
never have worked, on any path.

3. The overlay copied build output and Git metadata

The whole project tree was copied into each checked-out repository, including
buildSrc/build and .git — the latter holds the IPC sockets of the Git file system
monitor, which cannot be copied at all (Files.copy throws).

The tree is now walked with pruning, so a skipped folder is not descended into.
.git, .gradle and .kotlin are skipped at any depth; build is skipped only next to
a Gradle build script, so source packages such as io/spine/dependency/build are copied
as usual. A link that does not resolve is skipped rather than failing the whole
overlay — config has such links whenever .agents/shared is not checked out.

Measured on one checkout: the copied config overlay went from 4.3 GB to 3.8 MB.

4. The overlay replaced the module.gradle.kts of the repository

config ships that script as an empty template that each project replaces by its own, and
config/migrate preserves a project's script when installing buildSrc into it. The test
build did not, so every module of a repository under test lost java-library, Kotlin and
Dokka, failing with "Unresolved reference testImplementation". The script is now
preserved, exactly as migrate does it.

Verification

  • ./gradlew detekt and ./gradlew -p buildSrc build pass.
  • ClonedRepoSpec adds 7 cases over the copying rules and the preserved script.
    All of them fail against the previous version of ConfigTester.
  • A real ./gradlew clean buildDependants now checks out base into the project's own
    tmp/, overlays buildSrc and config, and base builds green.

What this PR does not fix

With the task working again, it immediately reports a genuine incompatibility: base-types
at master references ToolBase.lib, which io.spine.dependency.local.ToolBase no longer
declares, so its build script does not compile. That is a real downstream finding — the
kind this task exists to surface — and belongs in its own change.

Symbolic links to folders are still copied as empty folders (pre-existing; the tree is
walked without following links). This is now stated in the KDoc.

🤖 Generated with Claude Code

The task could not check out a single repository, and had been dead for
a long time. Four defects, each of which alone was enough to break it.

1. Relative paths were resolved against the Gradle daemon.

`config-tester.gradle.kts` passed `Paths.get("./")` and `File("./tmp")`
to `ConfigTester`. Both are resolved against `user.dir`, which for
a daemon build is `~/.gradle/daemon/<version>/`. The repositories were
checked out there, and the child build aborted with "does not contain
a Gradle build". Both paths now come from `layout.projectDirectory`, and
the `tempFolder` parameter lost its `File("./tmp")` default, so that
the same hazard cannot return. `ConfigTester` now requires both paths
to be absolute.

2. A `Stream` was traversed twice.

`copyRecursively()` filtered the walked tree for directories, and then
filtered the same stream for files, which threw `IllegalStateException:
stream has already been operated upon or closed`. Only the directories
were created, so the overlaid `buildSrc` was an empty skeleton.

3. The overlay copied build output and Git metadata.

The whole project tree was copied into each checked out repository,
including `buildSrc/build` and `.git`. The latter holds the IPC sockets
of the Git file system monitor, which cannot be copied at all. The tree
is now walked with pruning, so that such a folder is not descended into.

4. The overlay replaced the `module.gradle.kts` of the repository.

`config` ships this script as an empty template that each project
replaces by its own, and `config/migrate` preserves the script of
a project when installing `buildSrc` into it. The test build did not,
so every module of a repository under test lost `java-library`, Kotlin
and Dokka, failing with "Unresolved reference `testImplementation`".

`ClonedRepoSpec` covers the copying rules and the preserved script.
All of its cases fail against the previous version of `ConfigTester`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T15:09:34.121770Z 27d2c35 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

No blocking issues remain; regression tests cover the repaired overlay behavior, and the reported downstream incompatibility is outside this change.

No open issues 🎉

What changed in this PR

Restores buildDependants, allowing config changes to be checked against downstream repositories.

Changes:

  • Resolves checkout and source paths against the project directory.
  • Repairs recursive copying, excludes generated files and Git metadata, and preserves consumer module scripts.
  • Adds seven regression tests and updates usage documentation.
File Description
README.md Documents project-relative path resolution.
buildSrc/​src/​test/​kotlin/​io/​spine/​gradle/​ClonedRepoSpec.kt Tests copying exclusions and module-script preservation.
buildSrc/​src/​main/​kotlin/​io/​spine/​gradle/​ConfigTester.kt Repairs overlays and requires absolute paths.
buildSrc/​src/​main/​kotlin/​config-tester.gradle.kts Supplies project-rooted absolute paths.

Review effort: Balanced

@alexander-yevsyukov
alexander-yevsyukov merged commit b449406 into master Oct 19, 2026
3 checks passed
@alexander-yevsyukov
alexander-yevsyukov deleted the fix-config-tester-paths branch October 19, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants