Skip to content

Support Gradle Project Isolation #847

Description

@skhokhlov

Summary

The plugin is not compatible with Gradle's Project Isolation. This issue tracks making it Isolation-capable. The enabling refactor is tracked separately in #848 (migration to an explicit aggregator setup); this issue defines the goal and the acceptance bar.

Why we're incompatible today

Project Isolation forbids a project's build logic from reading or mutating another project's state at configuration time. Our multi-project support does exactly that: the plugin is applied once at the root, and the root then iterates its subprojects, configures tasks on them, and wires their outputs back together. That cross-project configuration is the core violation. It is also — less obviously — the mechanism that currently establishes the dependency edges from the aggregate root component to each subproject, so any redesign has to consciously preserve that behavior rather than inherit it for free.

What has to change (architecturally)

  1. No cross-project access at configuration time. Each project must configure only itself. The plugin therefore moves to a per-project application model every project that should contribute a BOM applies the plugin and, in its own configuration, publishes its Direct BOM as a consumable artifact (a variant).
  2. Aggregation stays variant/artifact-based. The aggregate task consumes member BOMs through normal variant-aware dependency resolution over a resolvable configuration. This is the path Gradle's configuration cache is designed to serialize, and it carries real task dependencies, so members are guaranteed built before aggregation runs.
  3. The aggregate task owns the root -> member dependency edges, synthesized from the members it actually merged — not inherited from cross-project traversal.
  4. A shared mutable BuildService is explicitly NOT the mechanism. A registry that projects write to at configuration time and the aggregator reads back fails on two counts: its accumulated state is not part of the service parameters, so it is not restored on a configuration-cache hit; and it assumes every subproject has been configured before the task graph is built — precisely the guarantee Isolation and configuration-on-demand remove.

Scope boundary

A structure-blind "apply to everything and aggregate the whole tree" workflow (e.g. a CI init script that iterates all projects) is inherently cross-project and therefore incompatible with Isolation by construction. That convenience remains a user-side, Isolation-disabled concern; the plugin itself targets Isolation-correctness for the explicit, per-project setup.

Acceptance criteria

  • A functional test that enables Project Isolation (-Dorg.gradle.unsafe.isolated-projects=true), applies the plugin per project, declares aggregation members explicitly, runs the aggregate task, and asserts: build success, all members present, and the root->member edges. Version-gated to Gradle versions where Isolation is stable.
  • Existing --configuration-cache coverage stays green.
  • Existing multi-module / skipped-project / "root connected to subprojects" specs stay green (output-contract regression guard).
  • No claim of Isolation support lands without the test above.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions