Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganise whole project #3

Merged
merged 8 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 34 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,20 @@ individual modules with the help of [Mermaid](https://mermaid.js.org/).

```mermaid
graph TD
vd2a57d(app) -->|api| ved7802(exporter)
vd2a57d(app) -->|api| v1bc49d(importer)
vd2a57d(app) -->|implementation| va74ad8(core)
vd2a57d(app) -->|implementation| v1bc49d(importer)
v80f88a(dependency-plugin) -->|implementation| v8ebf3d(dependency-model)
ved7802(exporter) -->|api| vf8b0b9(graph)
v1bc49d(importer) -->|api| v8ebf3d(dependency-model)
v1bc49d(importer) -->|api| vf8b0b9(graph)
v1bc49d(importer) -->|implementation| va74ad8(core)
v1bc49d(importer) -->|implementation| v8ebf3d(dependency-model)
```

What you see in the above graph:

* _Module_ `app` has two direct _dependencies_: `exporter` and `importer`, both use the
_configuration_ `api`.
* _Module_ `dependency-plugin` has one direct _dependency_ (`dependency-model`) of
_configuration_ `implementation`.

Features:

* Analyses Gradle projects in both DSLs (Kotlin and Groovy)
* Analyses Gradle projects in both Kotlin and Groovy DSLs
* Summarises the project modules and dependencies
* Generates text-based graphs which are compatible with Mermaid charts
* Filter only relevant modules or configurations
* Include transitive project dependencies

## Usage

Expand All @@ -58,20 +51,23 @@ Filter Options:
-o=<module,...> Module names in origin. Specify multiple comma-separated module names.
-d=<module,...> Module names in destination. Specify multiple comma-separated module names.
-c=<configuration,...> Configurations used in dependencies. Specify multiple comma-separated configuration names.
-t, --transitive If set, also include transitive module dependencies. This applies only if a module filter is active.

Display Options:

Options controlling how to output the analysed data. Display options can not be combined.

--modules Shows all modules of the project applying to the specified filters.
--configurations Displays all configurations applying to the specified filters and sorted by frequency of occurrence.
--chart-mermaid Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria.
--mermaid-graph Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria.
--chart-mermaid Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria. (deprecated)

Options:
-h, --help Show this message and exit

Arguments:
<gradleproject> Path of the Gradle project directory

```

### Quick Start
Expand All @@ -92,57 +88,60 @@ cd dependency-graph-analyser/
4. Publish the Gradle tooling API plugin and its data model to Maven local (available in the
directory `~/.m2/repository/ch/addere/dga/`)

Get an overview of this project by running `dga .``:
Get an overview of this project by running `dga .`:

```
./app/build/install/dga/bin/dga .

Analyse project "dependency-graph-analyser"
6 modules
6 dependencies (2 unique configurations)

5 modules
5 dependency configurations (1 unique dependency configurations)
```

### Create a Mermaid Chart

Use `dga . --chart-mermaid` to generate a Mermaid chart of this project:

```
./app/build/install/dga/bin/dga . --chart-mermaid
./app/build/install/dga/bin/dga . --mermaid-graph

Analyse project "dependency-graph-analyser"
6 modules
6 dependencies (2 unique configurations)
5 modules
5 dependency configurations (1 unique dependency configurations)

graph TD
vd2a57d(app) -->|api| ved7802(exporter)
vd2a57d(app) -->|api| v1bc49d(importer)
vd2a57d(app) -->|implementation| va74ad8(core)
vd2a57d(app) -->|implementation| v1bc49d(importer)
v80f88a(dependency-plugin) -->|implementation| v8ebf3d(dependency-model)
ved7802(exporter) -->|api| vf8b0b9(graph)
v1bc49d(importer) -->|api| v8ebf3d(dependency-model)
v1bc49d(importer) -->|api| vf8b0b9(graph)
v1bc49d(importer) -->|implementation| va74ad8(core)
v1bc49d(importer) -->|implementation| v8ebf3d(dependency-model)

```

#### Filter Modules

Use `dga . -o app,exporter --chart-mermaid` to generate a Mermaid chart of this project only
containing the modules `app` and `exporter` in the origin:
Use `dga . -o app --mermaid-graph` to generate a Mermaid graph chart of this project only
containing the dependencies originating from the module `app`:

```
./app/build/install/dga/bin/dga . -o app,exporter --chart-mermaid
./app/build/install/dga/bin/dga . -o app --mermaid-graph

Analyse project "dependency-graph-analyser"
6 modules
6 dependencies (2 unique configurations)
5 modules
5 dependency configurations (1 unique dependency configurations)

graph TD
vd2a57d(app) -->|api| ved7802(exporter)
vd2a57d(app) -->|api| v1bc49d(importer)
ved7802(exporter) -->|api| vf8b0b9(graph)
Applying filter on data results in:
3 modules
2 dependency configurations (1 unique dependency configurations)

graph TD
vd2a57d(app) -->|implementation| va74ad8(core)
vd2a57d(app) -->|implementation| v1bc49d(importer)

```

- Use `--transitive` to also include transitive dependencies.

## How DGA works

See [HowItWorks.md](HOWITWORKS.md)
Expand Down
8 changes: 5 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ plugins {
id("ch.addere.dga.kotlin-application-conventions")
}

description = "CLI application project"

dependencies {
api(project(":exporter"))
api(project(":importer"))
implementation(project(":core"))
implementation(project(":importer"))

implementation("com.github.ajalt.clikt:clikt:4.0.0")
implementation("com.github.ajalt.clikt:clikt:4.4.0")
implementation("io.insert-koin:koin-core:3.4.2")
}

Expand Down
74 changes: 42 additions & 32 deletions app/src/main/kotlin/ch/addere/dga/app/App.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package ch.addere.dga.app

import ch.addere.dga.app.configuration.OutputOptions
import ch.addere.dga.app.domain.model.CommandConfig
import ch.addere.dga.app.domain.model.FilterConfig
import ch.addere.dga.app.domain.model.OutputConfig
import ch.addere.dga.app.domain.service.DependencyCommand
import ch.addere.dga.app.domain.service.DependencyCommandHandler
import ch.addere.dga.app.infrastructure.factory.coreModule
import ch.addere.dga.app.infrastructure.factory.dgaModule
import ch.addere.dga.app.infrastructure.factory.importerModule
import ch.addere.dga.app.infrastructure.factory.userInputModule
import ch.addere.dga.graph.domain.model.Configuration
import ch.addere.dga.graph.domain.model.Module
import ch.addere.dga.core.domain.model.Configuration
import ch.addere.dga.core.domain.model.Module
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.CliktError
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.help
import com.github.ajalt.clikt.parameters.groups.OptionGroup
import com.github.ajalt.clikt.parameters.groups.default
import com.github.ajalt.clikt.parameters.groups.mutuallyExclusiveOptions
import com.github.ajalt.clikt.parameters.groups.provideDelegate
import com.github.ajalt.clikt.parameters.groups.single
import com.github.ajalt.clikt.parameters.options.convert
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.deprecated
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.help
import com.github.ajalt.clikt.parameters.options.option
Expand All @@ -28,36 +34,53 @@ import org.koin.core.parameter.parametersOf
import java.io.File
import kotlin.system.exitProcess

class Dga : CliktCommand(help = "Analyse the module dependency graph of a Gradle project."),
private class Dga : CliktCommand(help = "Analyse the module dependency graph of a Gradle project."),
KoinComponent {

private val gradleProject: File by argument()
.file()
.help("Path of the Gradle project directory")

private val optionsFilter by OptionsFilter()
private val optionsOutput by OptionsOutput()
private val outputOption: OutputOptions by mutuallyExclusiveOptions(
option("--modules")
.flag()
.convert { OutputOptions.OutputOptionModules }
.help("Shows all modules of the project applying to the specified filters."),
option("--configurations")
.flag()
.convert { OutputOptions.OutputOptionConfigurations }
.help("Displays all configurations applying to the specified filters and sorted by frequency of occurrence."),
option("--mermaid-graph")
.flag()
.convert { OutputOptions.OutputOptionMermaid }
.help("Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria."),
option("--chart-mermaid")
.flag()
.convert { OutputOptions.OutputOptionMermaid }
.help("Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria.")
.deprecated("Use --mermaid-graph instead"),
help = "Options controlling how to output the analysed data. Display options can not be combined.",
name = "Display Options",
).single().default(OutputOptions.OutputOptionOverviewOnly)


override fun run() {
val filterConfig = FilterConfig(
optionsFilter.modules,
optionsFilter.originModules,
optionsFilter.destinationModules,
optionsFilter.configurations
)
val outputConfig = OutputConfig(
optionsOutput.isAllModules,
optionsOutput.isAllConfigurations,
optionsOutput.isChartMermaid
optionsFilter.configurations,
optionsFilter.includeTransitiveModules
)
val argument = CommandConfig(::echo, gradleProject, filterConfig, outputConfig)
val command: DependencyCommand = get { parametersOf(argument) }
val argument = CommandConfig(::echo, gradleProject, filterConfig, outputOption)
val command: DependencyCommandHandler = get { parametersOf(argument) }

command.run()
}
}

class OptionsFilter : OptionGroup(
private class OptionsFilter : OptionGroup(
name = "Filter Options",
help = """
Filter control what to analyse. If several filters are set, dependencies must fulfill all of them.
Expand Down Expand Up @@ -86,25 +109,10 @@ class OptionsFilter : OptionGroup(
val configurations: List<Configuration> by option("-c")
.convert("configuration,...") { Configuration(it) }.split(",").default(emptyList())
.help("Configurations used in dependencies. Specify multiple comma-separated configuration names.")
}

class OptionsOutput : OptionGroup(
name = "Display Options",
help = """
Options controlling how to output the analysed data. Display options can not be combined.
""".trimIndent()
) {
val isAllModules: Boolean by option("--modules")
.flag()
.help("Shows all modules of the project applying to the specified filters.")

val isAllConfigurations: Boolean by option("--configurations")
.flag()
.help("Displays all configurations applying to the specified filters and sorted by frequency of occurrence.")

val isChartMermaid: Boolean by option("--chart-mermaid")
val includeTransitiveModules: Boolean by option("-t", "--transitive")
.flag()
.help("Generate the Mermaid graph chart source for the dependencies fulfilling the filter criteria.")
.help("If set, also include transitive module dependencies. This applies only if a module filter is active.")
}

fun main(args: Array<String>) {
Expand All @@ -113,6 +121,8 @@ fun main(args: Array<String>) {
startKoin {
modules(userInputModule)
modules(dgaModule)
modules(importerModule)
modules(coreModule)
}

dga.parse(args)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ch.addere.dga.app.configuration

sealed class OutputOptions {
data object OutputOptionOverviewOnly : OutputOptions()
data object OutputOptionModules : OutputOptions()
data object OutputOptionConfigurations : OutputOptions()
data object OutputOptionMermaid : OutputOptions()
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package ch.addere.dga.app.domain.model

import ch.addere.dga.app.configuration.OutputOptions
import ch.addere.dga.app.configuration.OutputOptions.OutputOptionOverviewOnly
import java.io.File

data class CommandConfig(
val printer: (String) -> Unit,
val gradleProjectPath: File,
val filterConfig: FilterConfig,
val outputConfig: OutputConfig
)
val outputConfig: OutputOptions
) {
val hasActiveFilter: Boolean =
filterConfig.modules.isNotEmpty() ||
filterConfig.originModules.isNotEmpty() ||
filterConfig.destinationModules.isNotEmpty() ||
filterConfig.configurations.isNotEmpty() ||
filterConfig.includeTransitiveDependencies
val hasActiveOutput: Boolean = outputConfig != OutputOptionOverviewOnly
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ch.addere.dga.app.domain.model

import ch.addere.dga.app.domain.model.writer.Writer


interface Exporter {

fun print(writer: Writer)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package ch.addere.dga.app.domain.model

import ch.addere.dga.graph.domain.model.Configuration
import ch.addere.dga.graph.domain.model.Module
import ch.addere.dga.core.domain.model.Configuration
import ch.addere.dga.core.domain.model.Module

data class FilterConfig(
val modules: List<Module>,
val originModules: List<Module>,
val destinationModules: List<Module>,
val configurations: List<Configuration>
val configurations: List<Configuration>,
val includeTransitiveDependencies: Boolean
)

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ch.addere.dga.exporter.domain.model.exporter.mermaid
package ch.addere.dga.app.domain.model.mermaid

import ch.addere.dga.exporter.domain.model.writer.Writer
import ch.addere.dga.graph.domain.model.Dependency
import ch.addere.dga.app.domain.model.writer.Writer
import ch.addere.dga.core.domain.model.Dependency
import java.util.*

class MermaidFullGraphExporter(private val dependencies: SortedSet<Dependency>) :
Expand Down
Loading
Loading