Skip to content

adityabhaskar/Gradle-dependency-graphs

Repository files navigation

Gradle 🐘 dependency graph visualisation plugin

Maven metadata URL License Language Publish Plugin to Portal Pre Merge Checks

A Gradle Plugin that generates dependency graphs showing the relationship between modules in your project.

The plugin generates a graph visualising the dependencies across the whole project. It also generates sub-graphs for each module within the project. For projects with a large number of modules, I find the sub-graphs tend to be a lot more useful.

The graphs are generated in the mermaid.js format so they are automatically displayed by Github.

This plugin is a derivation of Jake Wharton's project dependency graph script available here.

The plugin is available in the Gradle plugins repository.

How to use

Apply the plugin

Apply the plugin to your project's root build.gradle.kts

Kotlin:

plugins {
  id("io.github.adityabhaskar.dependencygraph") version "<version>"
}

Groovy:

plugins {
  id "io.github.adityabhaskar.dependencygraph" version "<version>"
}

See here for applying without the plugins DSL block.

Using the plugin

The plugin adds a new Gradle task - dependencyGraph. Running the task will generate the dependency graphs for all modules in the project.

./gradlew dependencyGraph

Configuring the plugin

Optionally configure the plugin in the same build.gradle.kts if you want to change the defaults

dependencyGraphConfig {
    graphDirection.set(Direction.LeftToRight)

    showLegend.set(ShowLegend.OnlyInRootGraph)

    ignoreModules.set(listOf(":example:system-test", ":example:test-fixtures"))

    repoRootUrl.set("https://github.com/adityabhaskar/Gradle-dependency-graphs")

    mainBranchName.set("main")

    graphFileName.set("dependencyGraph.md")
}

Configuration options

All configuration options are optional with sensible defaults.

Config option Type Default value Description
graphDirection Direction Direction.LeftToRight The direction in which the graph should be laid out.
Options:
  • Direction.LeftToRight
  • Direction.TopToBottom
  • Direction.BottomToTop
  • Direction.RightToLeft
showLegend ShowLegend ShowLegend.OnlyInRootGraph Whether to show a legend. When enabled, the graph with contain a legend identifying different types of modules β€” current/root, java/kotlin, Android and multiplatform β€” and different type of dependencies - direct, indirect & transitive.
Options:
  • ShowLegend.Always
  • ShowLegend.OnlyInRootGraph
  • ShowLegend.Never
graphFileName String dependencyGraph.md Name of the file in which the graph is saved.
Note: If the provided filename does not end in .md, then the extension will be appended.
ignoreModules List<String> emptyList() A list of modules to be ignored when generating the graph. This may be used, for instance to remove system test modules to see only the production graph.
Provide the full path of the modules you want to ignore, e.g. :live-feature:ui instead of :test-ui.
shouldLinkModuleText Boolean true Whether to add sub-graph links to module names in graphs. The links are useful for quickly navigating between graphs and sub-graphs.
Note: For links to work repoRootUrl and mainBranchName need to be provided
repoRootUrl String "" Github URL for your repository. E.g. https://github.com/adityabhaskar/Gradle-dependency-graphs
The URL is used for adding links to modules to allow navigation to a module's subgraph just by clicking on it. If no URL is provided, then links are not added to the graph.
mainBranchName String main Name of your main branch, e.g. master.
This is combined with the repoRootUrl to create clickable URLs. The URLs are used for adding links to graph to allow navigation to a module's subgraph by clicking on a module. If no repoRootUrl is provided, then links are not added to the graph.

Dependency graphs

Project wide dependency graph

The plugin will generate one graph at the root of the project for all modules in the project (except any ignored).

Sample root project graph with a legend:

%%{ init: { 'theme': 'base' } }%%
graph LR;

%% Styling for module nodes by type
classDef rootNode stroke-width:4px;
classDef mppNode fill:#ffd2b3,color:#333333;
classDef andNode fill:#baffc9,color:#333333;
classDef javaNode fill:#ffb3ba,color:#333333;

%% Modules
subgraph  
  direction LR;
  :example:feature{{<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/feature/dependencyGraph.md' style='text-decoration:auto'>:example:feature</a>}}:::javaNode;
  :example:models{{<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/models/dependencyGraph.md' style='text-decoration:auto'>:example:models</a>}}:::javaNode;
  :example:ui[<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/ui/dependencyGraph.md' style='text-decoration:auto'>:example:ui</a>]:::javaNode;
end

%% Dependencies
:example:ui===>:example:models

%% Dependents
:example:feature-.->:example:ui
Loading

Submodule dependency graph

Further, the plugin will generate a graph for every module's dependencies within that module's root folder. This graph will include:

  1. Direct dependents of the module, and
  2. Direct and indirect dependencies of the module

Dependents are identified with a dashed line.

Sample sub graph for the module :example:domain without a legend:

%%{ init: { 'theme': 'base' } }%%
graph LR;

%% Styling for module nodes by type
classDef rootNode stroke-width:4px;
classDef mppNode fill:#ffd2b3,color:#333333;
classDef andNode fill:#baffc9,color:#333333;
classDef javaNode fill:#ffb3ba,color:#333333;

%% Modules
subgraph  
  direction LR;
  :example:data{{<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/data/dependencyGraph.md' style='text-decoration:auto'>:example:data</a>}}:::javaNode;
  :example:domain[<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/domain/dependencyGraph.md' style='text-decoration:auto'>:example:domain</a>]:::javaNode;
  :example:feature{{<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/feature/dependencyGraph.md' style='text-decoration:auto'>:example:feature</a>}}:::javaNode;
  :example:models{{<a href='https://github.com/adityabhaskar/Gradle-dependency-graphs/blob/main/example/models/dependencyGraph.md' style='text-decoration:auto'>:example:models</a>}}:::javaNode;
end

%% Dependencies
:example:data--->:example:models
:example:domain==API===>:example:models
:example:domain===>:example:data

%% Dependents
:example:feature-.->:example:domain
Loading

CI integration

This section is a work in progress

Create a PR with changed graphs

The update-graphs-pr.yaml action creates a new PR with changed dependency graphs when module dependencies change on main.

  1. The action runs the plugin task ./gradlew :example:dependencyGraph to generate fresh dependency graphs.
  2. A simple script - .github/ci-scripts/changed_files.sh - collects all the changed graph files so they can be listed in the PR body.
  3. We use the peter-evans/create-pull-request action to create a PR only if there are any changed graphs.

Sample PR with changed graphs: #16

Commit changed graphs automatically

TBD: Github action that will automatically commit any new dependency graphs to main.

Contributing 🀝

Feel free to open a issue or submit a pull request for any bugs/improvements.

License πŸ“„

This template is licensed under the MIT License - see the License file for details.