autonomousapps / autonomousapps/dependency-analysis-gradle-plugin

FR: Plugin suggests explicit versions when using a Platform for central version management

Open
#1,658 4 comments 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.