autonomousapps / autonomousapps/dependency-analysis-gradle-plugin
FR: Plugin suggests explicit versions when using a Platform for central version management
- Dominant language
- Kotlin
- Stars
- 2.2k
- Forks
- 158
- Avg merge
- 16h 25m
- Merged PRs (30d)
- 46
Description
## Problem Description
When using Gradle's Java Platform plugin for centralized version management, the `projectHealth` task suggests adding dependencies **with explicit versions**, even though the versions should be managed centrally through the platform.
This defeats the purpose of using a platform for centralized dependency version management and can lead to version conflicts or inconsistencies.
## Current Behavior
See attached demo project:
[dependency-analysis.zip](https://github.com/user-attachments/files/26114498/dependency-analysis.zip)
**Setup:**
- A multi-module Gradle project with:
- A `platform` module using the `java-platform` plugin to define version constraints
- An `app` module that depends on the platform and declares dependencies without versions
**Platform module** (`platform/build.gradle`):
```groovy
plugins {
id 'java-platform'
id 'com.autonomousapps.dependency-analysis'
}
dependencies {
constraints {
api 'org.apache.commons:commons-lang3:3.12.0'
api 'com.google.guava:guava:33.5.0-jre'
api 'org.slf4j:slf4j-api:2.0.9'
}
}
```
**App module** (`app/build.gradle`):
```groovy
plugins {
id 'java-library'
id 'com.autonomousapps.dependency-analysis'
}
dependencies {
implementation platform(project(':platform'))
implementation 'com.google.guava:guava' // No version - managed by platform
}
```
**Code using transitive dependency** (`app/src/main/java/com/example/Foo.java`):
```java
package com.example;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.internal.InternalFutures;
import org.jspecify.annotations.NonNull;
public class Foo {
@NonNull
@Beta
String bar() {
InternalFutures.tryInternalFastPathGetFailure(null);
return "Hello World";
}
}
```
**Project Health Report Output:**
```
These transitive dependencies should be declared directly:
implementation 'com.google.guava:failureaccess:1.0.3'
```
## Expected Behavior
The `projectHealth` task should detect that versions are managed through a platform and suggest dependencies **without explicit versions**:
```
These transitive dependencies should be declared directly:
implementation 'com.google.guava:failureaccess'
```
## Why This Matters
1. **Version Management Consistency**: Using explicit versions in consuming modules bypasses the platform's version constraints, creating potential version conflicts
2. **Maintainability**: One of the main benefits of using a platform is having a single source of truth for all dependency versions
3. **Best Practices**: Gradle's official documentation recommends managing versions through platforms, and the advice should align with this best practice
## Proposed Solution
The plugin should:
1. Detect when a project uses a `platform(...)` dependency
2. Check if the suggested dependency's version is defined in the platform's constraints
3. If yes, suggest the dependency declaration without an explicit version
Alternatively, as a quick fix a flag could be added to suggest dependencies without versions
Contributor guide
Research direction
Reproduce the projectHealth report with the attached demo, starting from platform/build.gradle, app/build.gradle, and the Foo.java usage shown in the issue. Trace how the task formats the suggested failureaccess dependency and verify that, when its version is supplied by the platform constraints, the completed report omits the explicit version.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy, java, kotlin
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100