From c7dec20993052b8d2cab11fd3516dcdec43d68ae Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 31 Aug 2025 14:05:47 +0200 Subject: [PATCH 01/11] Generate Mermaid graphs --- .../AndroidApplicationConventionPlugin.kt | 2 + .../kotlin/AndroidLibraryConventionPlugin.kt | 2 + .../kotlin/AndroidTestConventionPlugin.kt | 2 + .../main/kotlin/JvmLibraryConventionPlugin.kt | 2 + .../google/samples/apps/nowinandroid/Graph.kt | 279 ++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 1ab3a2ca0..9cddabaf6 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -19,6 +19,7 @@ import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.gradle.BaseExtension import com.google.samples.apps.nowinandroid.configureBadgingTasks import com.google.samples.apps.nowinandroid.configureGradleManagedDevices +import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configurePrintApksTask import org.gradle.api.Plugin @@ -46,6 +47,7 @@ class AndroidApplicationConventionPlugin : Plugin { configurePrintApksTask(this) configureBadgingTasks(extensions.getByType(), this) } + configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 3fe727410..7524678bc 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -18,6 +18,7 @@ import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.LibraryExtension import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureGradleManagedDevices +import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configurePrintApksTask import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests @@ -58,6 +59,7 @@ class AndroidLibraryConventionPlugin : Plugin { "implementation"(libs.findLibrary("androidx.tracing.ktx").get()) } + configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt index 67933f77d..933327b2d 100644 --- a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -16,6 +16,7 @@ import com.android.build.gradle.TestExtension import com.google.samples.apps.nowinandroid.configureGradleManagedDevices +import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import org.gradle.api.Plugin import org.gradle.api.Project @@ -33,6 +34,7 @@ class AndroidTestConventionPlugin : Plugin { defaultConfig.targetSdk = 35 configureGradleManagedDevices(this) } + configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt index a1477891d..2866de1a2 100644 --- a/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt @@ -14,6 +14,7 @@ * limitations under the License. */ +import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinJvm import com.google.samples.apps.nowinandroid.libs import org.gradle.api.Plugin @@ -31,6 +32,7 @@ class JvmLibraryConventionPlugin : Plugin { dependencies { "testImplementation"(libs.findLibrary("kotlin.test").get()) } + configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt new file mode 100644 index 000000000..41c39c453 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt @@ -0,0 +1,279 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid + +import com.android.utils.associateWithNotNull +import com.google.samples.apps.nowinandroid.PluginType.Unknown +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity.NONE +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.withType +import kotlin.text.RegexOption.DOT_MATCHES_ALL + +/** + * Generates module dependency graphs with `graphDump` task, and update the corresponding `README.md` file with `graphUpdate`. + * + * This is not an optimal implementation and could be improved if needed: + * - [Graph.invoke] is **recursively** searching through dependent projects (although in practice it will never reach a stack overflow). + * - [Graph.invoke] is entirely re-executed for all projects, without re-using intermediate values. + * - [Graph.invoke] is always executed during Gradle's Configuration phase (but takes in general less than 1 ms for a project). + * + * The resulting graphs can be configured with `graph.ignoredProjects` and `graph.supportedConfigurations` properties. + */ +private class Graph( + private val root: Project, + private val dependencies: MutableMap>> = mutableMapOf(), + private val plugins: MutableMap = mutableMapOf(), + private val seen: MutableSet = mutableSetOf(), +) { + + private val ignoredProjects = root.providers.gradleProperty("graph.ignoredProjects") + .map { it.split(",").toSet() } + .orElse(emptySet()) + private val supportedConfigurations = + root.providers.gradleProperty("graph.supportedConfigurations") + .map { it.split(",").toSet() } + .orElse(setOf("api", "implementation", "baselineProfile", "testedApks")) + + operator fun invoke(project: Project = root): Graph { + if (project.path in seen) return this + seen += project.path + plugins.putIfAbsent( + project, + PluginType.entries.firstOrNull { project.pluginManager.hasPlugin(it.id) } ?: Unknown, + ) + dependencies.compute(project) { _, u -> u.orEmpty() } + project.configurations + .matching { it.name in supportedConfigurations.get() } + .associateWithNotNull { it.dependencies.withType().ifEmpty { null } } + .flatMap { (c, value) -> value.map { dep -> c to project.project(dep.path) } } + .filter { (_, p) -> p.path !in ignoredProjects.get() } + .forEach { (configuration: Configuration, projectDependency: Project) -> + dependencies.compute(project) { _, u -> u.orEmpty() + (configuration to projectDependency) } + invoke(projectDependency) + } + return this + } + + fun dependencies(): Map>> = dependencies + .mapKeys { it.key.path } + .mapValues { it.value.mapTo(mutableSetOf()) { (c, p) -> c.name to p.path } } + + fun plugins() = plugins.mapKeys { it.key.path } +} + +/** + * Declaration order is important, as only the first match will be retained. + */ +internal enum class PluginType(val id: String, val ref: String, val style: String) { + AndroidApplication( + id = "com.android.application", + ref = "android-application", + style = "fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff", + ), + AndroidLibrary( + id = "com.android.library", + ref = "android-library", + style = "fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff", + ), + AndroidTest( + id = "com.android.test", + ref = "android-test", + style = "fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff", + ), + Jvm( + id = "org.jetbrains.kotlin.jvm", + ref = "jvm", + style = "fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff", + ), + Unknown( + id = "?", + ref = "unknown", + style = "fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff", + ), +} + +fun Project.configureGraphTasks() { + val dumpTask = tasks.register("graphDump") { + val graph = Graph(this@configureGraphTasks).invoke() + projectPath = this@configureGraphTasks.path + dependencies = graph.dependencies() + plugins = graph.plugins() + output = this@configureGraphTasks.layout.buildDirectory.file("mermaid.txt") + } + tasks.register("graphUpdate") { + projectPath = this@configureGraphTasks.path + input = dumpTask.flatMap { it.output } + output = this@configureGraphTasks.layout.projectDirectory.file("README.md") + } +} + +@CacheableTask +private abstract class GraphDumpTask : DefaultTask() { + + @get:Input + abstract val projectPath: Property + + @get:Input + abstract val dependencies: MapProperty>> + + @get:Input + abstract val plugins: MapProperty + + @get:OutputFile + abstract val output: RegularFileProperty + + override fun getDescription() = "Dumps project dependencies to a mermaid file." + + @TaskAction + operator fun invoke() { + output.get().asFile.writeText(mermaid()) + logger.lifecycle(output.get().asFile.toPath().toUri().toString()) + } + + private fun mermaid() = buildString { + val dependencies: Set = dependencies.get() + .flatMapTo(mutableSetOf()) { (project, entries) -> entries.map { it.toDependency(project) } } + // FrontMatter configuration (not supported yet on GitHub.com) + appendLine( + // language=YAML + """ + --- + config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE + --- + """.trimIndent(), + ) + // Graph declaration + appendLine("graph TB") + // Nodes and subgraphs (limited to a single nested layer) + val (rootProjects, nestedProjects) = dependencies + .map { listOf(it.project, it.dependency) }.flatten().toSet() + .plus(projectPath.get()) // Special case when this specific module has no other dependency + .groupBy { it.substringBeforeLast(":") } + .entries.partition { it.key.isEmpty() } + nestedProjects.sortedByDescending { it.value.size }.forEach { (group, projects) -> + appendLine(" subgraph $group") + appendLine(" direction TB") + projects.sorted().forEach { + appendLine(it.alias(indent = 4, plugins.get().getValue(it))) + } + appendLine(" end") + } + rootProjects.flatMap { it.value }.sortedDescending().forEach { + appendLine(it.alias(indent = 2, plugins.get().getValue(it))) + } + // Links + if (dependencies.isNotEmpty()) appendLine() + dependencies + .sortedWith(compareBy({ it.project }, { it.dependency }, { it.configuration })) + .forEach { appendLine(it.link(indent = 2)) } + // Classes + appendLine() + PluginType.entries.forEach { appendLine(it.classDef()) } + } + + private class Dependency(val project: String, val configuration: String, val dependency: String) + + private fun Pair.toDependency(project: String) = + Dependency(project, configuration = first, dependency = second) + + private fun String.alias(indent: Int, pluginType: PluginType): String = buildString { + append(" ".repeat(indent)) + append(this@alias) + append("[").append(substringAfterLast(":")).append("]:::") + append(pluginType.ref) + } + + private fun Dependency.link(indent: Int) = buildString { + append(" ".repeat(indent)) + append(project).append(" ") + append( + when (configuration) { + "api" -> "--->" + "implementation" -> "-.->" + else -> "-.->|$configuration|" + }, + ) + append(" ").append(dependency) + } + + private fun PluginType.classDef() = "classDef $ref $style;" +} + +@CacheableTask +private abstract class GraphUpdateTask : DefaultTask() { + + @get:Input + abstract val projectPath: Property + + @get:InputFile + @get:PathSensitive(NONE) + abstract val input: RegularFileProperty + + @get:OutputFile + abstract val output: RegularFileProperty + + override fun getDescription() = "Updates Markdown file with the corresponding dependency graph." + + @TaskAction + operator fun invoke() = with(output.get().asFile) { + if (!exists()) { + createNewFile() + writeText( + """ + # `${projectPath.get()}` + + + + """.trimIndent(), + ) + } + val regex = """()(.*?)()""".toRegex(DOT_MATCHES_ALL) + val text = readText().replace(regex) { match -> + val (start, _, end) = match.destructured + val mermaid = input.get().asFile.readText().trimTrailingNewLines() + """ + |$start + |```mermaid + |$mermaid + |``` + |$end + """.trimMargin() + } + writeText(text) + } + + private fun String.trimTrailingNewLines() = lines() + .dropLastWhile(String::isBlank) + .joinToString(System.lineSeparator()) +} From 0156c82090305c2fdf0167f6fcf61a52346ef03c Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 31 Aug 2025 14:08:20 +0200 Subject: [PATCH 02/11] Remove `com.jraska.module.graph.assertion` plugin --- build.gradle.kts | 1 - gradle/libs.versions.toml | 2 -- 2 files changed, 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b7989bab4..c61794f1f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -60,5 +60,4 @@ plugins { alias(libs.plugins.roborazzi) apply false alias(libs.plugins.secrets) apply false alias(libs.plugins.room) apply false - alias(libs.plugins.module.graph) apply true // Plugin applied to allow module graph generation } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 81f12c480..b5cd7df15 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -47,7 +47,6 @@ kotlinxCoroutines = "1.10.1" kotlinxDatetime = "0.6.1" kotlinxSerializationJson = "1.8.0" ksp = "2.1.10-1.0.31" -moduleGraph = "2.7.1" okhttp = "4.12.0" protobuf = "4.29.2" protobufPlugin = "0.9.4" @@ -177,7 +176,6 @@ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -module-graph = { id = "com.jraska.module.graph.assertion", version.ref = "moduleGraph" } protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } room = { id = "androidx.room", version.ref = "room" } From e079e68815b1837a6aed188bc82c3a3bda8f8a00 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 31 Aug 2025 14:14:57 +0200 Subject: [PATCH 03/11] Delete old graphs --- app-nia-catalog/README.md | 3 - app/README.md | 3 - core/analytics/README.md | 3 - core/common/README.md | 3 - core/data-test/README.md | 3 - core/data/README.md | 3 - core/database/README.md | 3 - core/datastore-proto/README.md | 3 - core/datastore-test/README.md | 3 - core/datastore/README.md | 3 - core/designsystem/README.md | 3 - core/domain/README.md | 3 - core/model/README.md | 3 - core/network/README.md | 3 - core/notifications/README.md | 3 - core/screenshot-testing/README.md | 3 - core/testing/README.md | 3 - core/ui/README.md | 3 - docs/images/graphs/dep_graph_app.svg | 305 ------------------ .../graphs/dep_graph_app_nia_catalog.svg | 45 --- .../graphs/dep_graph_core_analytics.svg | 9 - docs/images/graphs/dep_graph_core_common.svg | 9 - docs/images/graphs/dep_graph_core_data.svg | 97 ------ .../graphs/dep_graph_core_data_test.svg | 105 ------ .../images/graphs/dep_graph_core_database.svg | 17 - .../graphs/dep_graph_core_datastore.svg | 33 -- .../graphs/dep_graph_core_datastore_proto.svg | 9 - .../graphs/dep_graph_core_datastore_test.svg | 45 --- .../graphs/dep_graph_core_designsystem.svg | 9 - docs/images/graphs/dep_graph_core_domain.svg | 109 ------- docs/images/graphs/dep_graph_core_model.svg | 9 - docs/images/graphs/dep_graph_core_network.svg | 25 -- .../graphs/dep_graph_core_notifications.svg | 25 -- .../dep_graph_core_screenshot_testing.svg | 17 - docs/images/graphs/dep_graph_core_testing.svg | 121 ------- docs/images/graphs/dep_graph_core_ui.svg | 33 -- .../graphs/dep_graph_feature_bookmarks.svg | 133 -------- .../graphs/dep_graph_feature_foryou.svg | 149 --------- .../graphs/dep_graph_feature_interests.svg | 149 --------- .../graphs/dep_graph_feature_search.svg | 149 --------- .../graphs/dep_graph_feature_settings.svg | 133 -------- .../images/graphs/dep_graph_feature_topic.svg | 133 -------- .../graphs/dep_graph_sync_sync_test.svg | 121 ------- docs/images/graphs/dep_graph_sync_work.svg | 109 ------- feature/bookmarks/README.md | 3 - feature/foryou/README.md | 3 - feature/interests/README.md | 3 - feature/search/README.md | 3 - feature/settings/README.md | 3 - feature/topic/README.md | 3 - generateModuleGraphs.sh | 131 -------- sync/sync-test/README.md | 3 - sync/work/README.md | 3 - 53 files changed, 2307 deletions(-) delete mode 100644 app-nia-catalog/README.md delete mode 100644 app/README.md delete mode 100644 core/analytics/README.md delete mode 100644 core/common/README.md delete mode 100644 core/data-test/README.md delete mode 100644 core/data/README.md delete mode 100644 core/database/README.md delete mode 100644 core/datastore-proto/README.md delete mode 100644 core/datastore-test/README.md delete mode 100644 core/datastore/README.md delete mode 100644 core/designsystem/README.md delete mode 100644 core/domain/README.md delete mode 100644 core/model/README.md delete mode 100644 core/network/README.md delete mode 100644 core/notifications/README.md delete mode 100644 core/screenshot-testing/README.md delete mode 100644 core/testing/README.md delete mode 100644 core/ui/README.md delete mode 100644 docs/images/graphs/dep_graph_app.svg delete mode 100644 docs/images/graphs/dep_graph_app_nia_catalog.svg delete mode 100644 docs/images/graphs/dep_graph_core_analytics.svg delete mode 100644 docs/images/graphs/dep_graph_core_common.svg delete mode 100644 docs/images/graphs/dep_graph_core_data.svg delete mode 100644 docs/images/graphs/dep_graph_core_data_test.svg delete mode 100644 docs/images/graphs/dep_graph_core_database.svg delete mode 100644 docs/images/graphs/dep_graph_core_datastore.svg delete mode 100644 docs/images/graphs/dep_graph_core_datastore_proto.svg delete mode 100644 docs/images/graphs/dep_graph_core_datastore_test.svg delete mode 100644 docs/images/graphs/dep_graph_core_designsystem.svg delete mode 100644 docs/images/graphs/dep_graph_core_domain.svg delete mode 100644 docs/images/graphs/dep_graph_core_model.svg delete mode 100644 docs/images/graphs/dep_graph_core_network.svg delete mode 100644 docs/images/graphs/dep_graph_core_notifications.svg delete mode 100644 docs/images/graphs/dep_graph_core_screenshot_testing.svg delete mode 100644 docs/images/graphs/dep_graph_core_testing.svg delete mode 100644 docs/images/graphs/dep_graph_core_ui.svg delete mode 100644 docs/images/graphs/dep_graph_feature_bookmarks.svg delete mode 100644 docs/images/graphs/dep_graph_feature_foryou.svg delete mode 100644 docs/images/graphs/dep_graph_feature_interests.svg delete mode 100644 docs/images/graphs/dep_graph_feature_search.svg delete mode 100644 docs/images/graphs/dep_graph_feature_settings.svg delete mode 100644 docs/images/graphs/dep_graph_feature_topic.svg delete mode 100644 docs/images/graphs/dep_graph_sync_sync_test.svg delete mode 100644 docs/images/graphs/dep_graph_sync_work.svg delete mode 100644 feature/bookmarks/README.md delete mode 100644 feature/foryou/README.md delete mode 100644 feature/interests/README.md delete mode 100644 feature/search/README.md delete mode 100644 feature/settings/README.md delete mode 100644 feature/topic/README.md delete mode 100755 generateModuleGraphs.sh delete mode 100644 sync/sync-test/README.md delete mode 100644 sync/work/README.md diff --git a/app-nia-catalog/README.md b/app-nia-catalog/README.md deleted file mode 100644 index cf6d05f4f..000000000 --- a/app-nia-catalog/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :app-nia-catalog module -## Dependency graph -![Dependency graph](../docs/images/graphs/dep_graph_app_nia_catalog.svg) diff --git a/app/README.md b/app/README.md deleted file mode 100644 index a3fb4572a..000000000 --- a/app/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :app module -## Dependency graph -![Dependency graph](../docs/images/graphs/dep_graph_app.svg) diff --git a/core/analytics/README.md b/core/analytics/README.md deleted file mode 100644 index d2bcd1ea7..000000000 --- a/core/analytics/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:analytics module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_analytics.svg) diff --git a/core/common/README.md b/core/common/README.md deleted file mode 100644 index 96558bcc6..000000000 --- a/core/common/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:common module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_common.svg) diff --git a/core/data-test/README.md b/core/data-test/README.md deleted file mode 100644 index 977ee10e4..000000000 --- a/core/data-test/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:data-test module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_data_test.svg) diff --git a/core/data/README.md b/core/data/README.md deleted file mode 100644 index 5d30f1638..000000000 --- a/core/data/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:data module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_data.svg) diff --git a/core/database/README.md b/core/database/README.md deleted file mode 100644 index 855eab53e..000000000 --- a/core/database/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:database module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_database.svg) diff --git a/core/datastore-proto/README.md b/core/datastore-proto/README.md deleted file mode 100644 index 19ed58239..000000000 --- a/core/datastore-proto/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:datastore-proto module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_proto.svg) diff --git a/core/datastore-test/README.md b/core/datastore-test/README.md deleted file mode 100644 index 99cf13f1f..000000000 --- a/core/datastore-test/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:datastore-test module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_test.svg) diff --git a/core/datastore/README.md b/core/datastore/README.md deleted file mode 100644 index 4785c5885..000000000 --- a/core/datastore/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:datastore module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore.svg) diff --git a/core/designsystem/README.md b/core/designsystem/README.md deleted file mode 100644 index d1778cb14..000000000 --- a/core/designsystem/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:designsystem module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_designsystem.svg) diff --git a/core/domain/README.md b/core/domain/README.md deleted file mode 100644 index cc6905846..000000000 --- a/core/domain/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:domain module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_domain.svg) diff --git a/core/model/README.md b/core/model/README.md deleted file mode 100644 index efd0eec76..000000000 --- a/core/model/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:model module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_model.svg) diff --git a/core/network/README.md b/core/network/README.md deleted file mode 100644 index 516aa2d38..000000000 --- a/core/network/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:network module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_network.svg) diff --git a/core/notifications/README.md b/core/notifications/README.md deleted file mode 100644 index 8f5607bdf..000000000 --- a/core/notifications/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:notifications module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_notifications.svg) diff --git a/core/screenshot-testing/README.md b/core/screenshot-testing/README.md deleted file mode 100644 index 9bd4f1f9c..000000000 --- a/core/screenshot-testing/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:screenshot-testing module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_screenshot_testing.svg) diff --git a/core/testing/README.md b/core/testing/README.md deleted file mode 100644 index 5a35d379b..000000000 --- a/core/testing/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:testing module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_testing.svg) diff --git a/core/ui/README.md b/core/ui/README.md deleted file mode 100644 index 38e514d01..000000000 --- a/core/ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :core:ui module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_ui.svg) diff --git a/docs/images/graphs/dep_graph_app.svg b/docs/images/graphs/dep_graph_app.svg deleted file mode 100644 index 8e5d9d429..000000000 --- a/docs/images/graphs/dep_graph_app.svg +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - :app - - - - :feature:interests - - - - - - - - :feature:foryou - - - - - - - - :feature:bookmarks - - - - - - - - :feature:topic - - - - - - - - :feature:search - - - - - - - - :feature:settings - - - - - - - - :core:common - - - - - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:analytics - - - - - - - - :sync:work - - - - - - - - - - - - - - - - - - - - :core:domain - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_app_nia_catalog.svg b/docs/images/graphs/dep_graph_app_nia_catalog.svg deleted file mode 100644 index 151ee63ad..000000000 --- a/docs/images/graphs/dep_graph_app_nia_catalog.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - :app-nia-catalog - - - - :core:designsystem - - - - - - - - :core:ui - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_analytics.svg b/docs/images/graphs/dep_graph_core_analytics.svg deleted file mode 100644 index 45f1c1eb0..000000000 --- a/docs/images/graphs/dep_graph_core_analytics.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:analytics - - - diff --git a/docs/images/graphs/dep_graph_core_common.svg b/docs/images/graphs/dep_graph_core_common.svg deleted file mode 100644 index 91033eaa0..000000000 --- a/docs/images/graphs/dep_graph_core_common.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:common - - - diff --git a/docs/images/graphs/dep_graph_core_data.svg b/docs/images/graphs/dep_graph_core_data.svg deleted file mode 100644 index ab91bafb2..000000000 --- a/docs/images/graphs/dep_graph_core_data.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - :core:data - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_data_test.svg b/docs/images/graphs/dep_graph_core_data_test.svg deleted file mode 100644 index b9736c859..000000000 --- a/docs/images/graphs/dep_graph_core_data_test.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - :core:data-test - - - - :core:data - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_database.svg b/docs/images/graphs/dep_graph_core_database.svg deleted file mode 100644 index e82d46436..000000000 --- a/docs/images/graphs/dep_graph_core_database.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - :core:database - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_datastore.svg b/docs/images/graphs/dep_graph_core_datastore.svg deleted file mode 100644 index f7502e55b..000000000 --- a/docs/images/graphs/dep_graph_core_datastore.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - :core:datastore - - - - :core:datastore-proto - - - - - - - - :core:model - - - - - - - - :core:common - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_datastore_proto.svg b/docs/images/graphs/dep_graph_core_datastore_proto.svg deleted file mode 100644 index 7fcfb8358..000000000 --- a/docs/images/graphs/dep_graph_core_datastore_proto.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:datastore-proto - - - diff --git a/docs/images/graphs/dep_graph_core_datastore_test.svg b/docs/images/graphs/dep_graph_core_datastore_test.svg deleted file mode 100644 index 37521a05f..000000000 --- a/docs/images/graphs/dep_graph_core_datastore_test.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - :core:datastore-test - - - - :core:common - - - - - - - - :core:datastore - - - - - - - - - - - - :core:datastore-proto - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_designsystem.svg b/docs/images/graphs/dep_graph_core_designsystem.svg deleted file mode 100644 index 737140876..000000000 --- a/docs/images/graphs/dep_graph_core_designsystem.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:designsystem - - - diff --git a/docs/images/graphs/dep_graph_core_domain.svg b/docs/images/graphs/dep_graph_core_domain.svg deleted file mode 100644 index fe3740d2f..000000000 --- a/docs/images/graphs/dep_graph_core_domain.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - :core:domain - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_model.svg b/docs/images/graphs/dep_graph_core_model.svg deleted file mode 100644 index 125684a08..000000000 --- a/docs/images/graphs/dep_graph_core_model.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:model - - - diff --git a/docs/images/graphs/dep_graph_core_network.svg b/docs/images/graphs/dep_graph_core_network.svg deleted file mode 100644 index 3022a86ee..000000000 --- a/docs/images/graphs/dep_graph_core_network.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - :core:network - - - - :core:common - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_notifications.svg b/docs/images/graphs/dep_graph_core_notifications.svg deleted file mode 100644 index d96d28769..000000000 --- a/docs/images/graphs/dep_graph_core_notifications.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - :core:notifications - - - - :core:model - - - - - - - - :core:common - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_screenshot_testing.svg b/docs/images/graphs/dep_graph_core_screenshot_testing.svg deleted file mode 100644 index a7d58b0ea..000000000 --- a/docs/images/graphs/dep_graph_core_screenshot_testing.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - :core:screenshot-testing - - - - :core:designsystem - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_testing.svg b/docs/images/graphs/dep_graph_core_testing.svg deleted file mode 100644 index d441858e5..000000000 --- a/docs/images/graphs/dep_graph_core_testing.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - :core:testing - - - - :core:analytics - - - - - - - - :core:common - - - - - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_ui.svg b/docs/images/graphs/dep_graph_core_ui.svg deleted file mode 100644 index 2cd972357..000000000 --- a/docs/images/graphs/dep_graph_core_ui.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - :core:ui - - - - :core:analytics - - - - - - - - :core:designsystem - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_bookmarks.svg b/docs/images/graphs/dep_graph_feature_bookmarks.svg deleted file mode 100644 index 0391eb39c..000000000 --- a/docs/images/graphs/dep_graph_feature_bookmarks.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:bookmarks - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_foryou.svg b/docs/images/graphs/dep_graph_feature_foryou.svg deleted file mode 100644 index 63a154a87..000000000 --- a/docs/images/graphs/dep_graph_feature_foryou.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:foryou - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_interests.svg b/docs/images/graphs/dep_graph_feature_interests.svg deleted file mode 100644 index 2de1fc61f..000000000 --- a/docs/images/graphs/dep_graph_feature_interests.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:interests - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_search.svg b/docs/images/graphs/dep_graph_feature_search.svg deleted file mode 100644 index 7f8f29777..000000000 --- a/docs/images/graphs/dep_graph_feature_search.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:search - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_settings.svg b/docs/images/graphs/dep_graph_feature_settings.svg deleted file mode 100644 index 3f0d35df2..000000000 --- a/docs/images/graphs/dep_graph_feature_settings.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:settings - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_topic.svg b/docs/images/graphs/dep_graph_feature_topic.svg deleted file mode 100644 index b7c7dd26c..000000000 --- a/docs/images/graphs/dep_graph_feature_topic.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:topic - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_sync_sync_test.svg b/docs/images/graphs/dep_graph_sync_sync_test.svg deleted file mode 100644 index 7a083ba54..000000000 --- a/docs/images/graphs/dep_graph_sync_sync_test.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - :sync:sync-test - - - - :core:data - - - - - - - - :sync:work - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_sync_work.svg b/docs/images/graphs/dep_graph_sync_work.svg deleted file mode 100644 index c649f2397..000000000 --- a/docs/images/graphs/dep_graph_sync_work.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - :sync:work - - - - :core:analytics - - - - - - - - :core:data - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/feature/bookmarks/README.md b/feature/bookmarks/README.md deleted file mode 100644 index 54cbf91d0..000000000 --- a/feature/bookmarks/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:bookmarks module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_bookmarks.svg) diff --git a/feature/foryou/README.md b/feature/foryou/README.md deleted file mode 100644 index 0f08cb827..000000000 --- a/feature/foryou/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:foryou module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_foryou.svg) diff --git a/feature/interests/README.md b/feature/interests/README.md deleted file mode 100644 index 90a4fbc9c..000000000 --- a/feature/interests/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:interests module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_interests.svg) diff --git a/feature/search/README.md b/feature/search/README.md deleted file mode 100644 index e205970f0..000000000 --- a/feature/search/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:search module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_search.svg) diff --git a/feature/settings/README.md b/feature/settings/README.md deleted file mode 100644 index 7a4df04fe..000000000 --- a/feature/settings/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:settings module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_settings.svg) diff --git a/feature/topic/README.md b/feature/topic/README.md deleted file mode 100644 index 84588929c..000000000 --- a/feature/topic/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# :feature:topic module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_topic.svg) diff --git a/generateModuleGraphs.sh b/generateModuleGraphs.sh deleted file mode 100755 index 5307d2932..000000000 --- a/generateModuleGraphs.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/bash -# -# Copyright 2024 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# -# Script to generate dependency graphs for each of the modules. The --exclude-module parameter can -# be used to exclude modules which are not part of the root dependency graph (and which, if included -# would cause the script to fail. -# -# Usage: generateModuleGraphs.sh --exclude-module :benchmarks --exclude-module :lint --exclude-module :ui-test-hilt-manifest - -# Check if the dot command is available -if ! command -v dot &> /dev/null -then - echo "The 'dot' command is not found. This is required to generate SVGs from the Graphviz files." - echo "Installation instructions:" - echo " - On macOS: You can install Graphviz using Homebrew with the command: 'brew install graphviz'" - echo " - On Ubuntu: You can install Graphviz using APT with the command: 'sudo apt install graphviz'" - echo " - Others: Visit https://graphviz.org/download/" - exit 1 -fi - -# Check if the svgo command is available -if ! command -v svgo &> /dev/null -then - echo "The 'svgo' command is not found. This is required to cleanup and compress SVGs." - echo "Installation instructions available at https://github.com/svg/svgo." - exit 1 -fi - -# Check for a version of grep which supports Perl regex. -# On MacOS the OS installed grep doesn't support Perl regex so check for the existence of the -# GNU version instead which is prefixed with 'g' to distinguish it from the OS installed version. - if grep -P "" /dev/null > /dev/null 2>&1; then - GREP_COMMAND=grep -elif command -v ggrep &> /dev/null; then - GREP_COMMAND=ggrep -else - echo "You don't have a version of 'grep' installed which supports Perl regular expressions." - echo "On MacOS you can install one using Homebrew with the command: 'brew install grep'" - exit 1 -fi - -# Initialize an array to store excluded modules -excluded_modules=() - -# Parse command-line arguments for excluded modules -while [[ $# -gt 0 ]]; do - case "$1" in - --exclude-module) - excluded_modules+=("$2") - shift # Past argument - shift # Past value - ;; - *) - echo "Unknown parameter passed: $1" - exit 1 - ;; - esac -done - -# Get the module paths -module_paths=$(${GREP_COMMAND} -oP 'include\("\K[^"]+' settings.gradle.kts) - -# Ensure the output directory exists -mkdir -p docs/images/graphs/ - -# Function to check and create a README.md for modules which don't have one. -check_and_create_readme() { - local module_path="$1" - local file_name="$2" - - local readme_path="${module_path:1}" # Remove leading colon - readme_path=${readme_path//:/\/} # Replace colons with slashes - readme_path="${readme_path}/README.md" #Append the filename - - # Check if README.md exists and create it if not - if [[ ! -f "$readme_path" ]]; then - echo "Creating README.md for ${module_path}" - - # Determine the depth of the module based on the number of colons - local depth=$(awk -F: '{print NF-1}' <<< "${module_path}") - - # Construct the relative image path with the correct number of "../" - local relative_image_path="../" - for ((i=1; i<$depth; i++)); do - relative_image_path+="../" - done - relative_image_path+="docs/images/graphs/${file_name}.svg" - - echo "# ${module_path} module" > "$readme_path" - echo "## Dependency graph" >> "$readme_path" - echo "![Dependency graph](${relative_image_path})" >> "$readme_path" - fi -} - -# Loop through each module path -echo "$module_paths" | while read -r module_path; do - # Check if the module is in the excluded list - if [[ ! " ${excluded_modules[@]} " =~ " ${module_path} " ]]; then - # Derive the filename from the module path - file_name="dep_graph${module_path//:/_}" # Replace colons with underscores - file_name="${file_name//-/_}" # Replace dashes with underscores - - check_and_create_readme "$module_path" "$file_name" - - # Generate the .gv file in a temporary location - # Date: Sun, 31 Aug 2025 14:23:23 +0200 Subject: [PATCH 04/11] graphUpdate --- app-nia-catalog/README.md | 33 +++++++++ app/README.md | 109 ++++++++++++++++++++++++++++++ benchmarks/README.md | 109 ++++++++++++++++++++++++++++++ core/analytics/README.md | 23 +++++++ core/common/README.md | 23 +++++++ core/data-test/README.md | 48 +++++++++++++ core/data/README.md | 46 +++++++++++++ core/database/README.md | 26 +++++++ core/datastore-proto/README.md | 23 +++++++ core/datastore-test/README.md | 33 +++++++++ core/datastore/README.md | 30 ++++++++ core/designsystem/README.md | 23 +++++++ core/domain/README.md | 49 ++++++++++++++ core/model/README.md | 23 +++++++ core/network/README.md | 28 ++++++++ core/notifications/README.md | 28 ++++++++ core/screenshot-testing/README.md | 26 +++++++ core/testing/README.md | 52 ++++++++++++++ core/ui/README.md | 30 ++++++++ feature/bookmarks/README.md | 58 ++++++++++++++++ feature/foryou/README.md | 63 +++++++++++++++++ feature/interests/README.md | 62 +++++++++++++++++ feature/search/README.md | 62 +++++++++++++++++ feature/settings/README.md | 58 ++++++++++++++++ feature/topic/README.md | 58 ++++++++++++++++ sync/sync-test/README.md | 56 +++++++++++++++ sync/work/README.md | 53 +++++++++++++++ ui-test-hilt-manifest/README.md | 20 ++++++ 28 files changed, 1252 insertions(+) create mode 100644 app-nia-catalog/README.md create mode 100644 app/README.md create mode 100644 benchmarks/README.md create mode 100644 core/analytics/README.md create mode 100644 core/common/README.md create mode 100644 core/data-test/README.md create mode 100644 core/data/README.md create mode 100644 core/database/README.md create mode 100644 core/datastore-proto/README.md create mode 100644 core/datastore-test/README.md create mode 100644 core/datastore/README.md create mode 100644 core/designsystem/README.md create mode 100644 core/domain/README.md create mode 100644 core/model/README.md create mode 100644 core/network/README.md create mode 100644 core/notifications/README.md create mode 100644 core/screenshot-testing/README.md create mode 100644 core/testing/README.md create mode 100644 core/ui/README.md create mode 100644 feature/bookmarks/README.md create mode 100644 feature/foryou/README.md create mode 100644 feature/interests/README.md create mode 100644 feature/search/README.md create mode 100644 feature/settings/README.md create mode 100644 feature/topic/README.md create mode 100644 sync/sync-test/README.md create mode 100644 sync/work/README.md create mode 100644 ui-test-hilt-manifest/README.md diff --git a/app-nia-catalog/README.md b/app-nia-catalog/README.md new file mode 100644 index 000000000..a0b2bb6f6 --- /dev/null +++ b/app-nia-catalog/README.md @@ -0,0 +1,33 @@ +# `:app-nia-catalog` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm + :core:ui[ui]:::android-library + end + :app-nia-catalog[app-nia-catalog]:::android-application + + :app-nia-catalog -.-> :core:designsystem + :app-nia-catalog -.-> :core:ui + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/app/README.md b/app/README.md new file mode 100644 index 000000000..020aecd28 --- /dev/null +++ b/app/README.md @@ -0,0 +1,109 @@ +# `:app` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-library + :feature:foryou[foryou]:::android-library + :feature:interests[interests]:::android-library + :feature:search[search]:::android-library + :feature:settings[settings]:::android-library + :feature:topic[topic]:::android-library + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + :benchmarks[benchmarks]:::android-test + :app[app]:::android-application + + :app -.->|baselineProfile| :benchmarks + :app -.-> :core:analytics + :app -.-> :core:common + :app -.-> :core:data + :app -.-> :core:designsystem + :app -.-> :core:model + :app -.-> :core:ui + :app -.-> :feature:bookmarks + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:search + :app -.-> :feature:settings + :app -.-> :feature:topic + :app -.-> :sync:work + :benchmarks -.->|testedApks| :app + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000..6e91ce55d --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,109 @@ +# `:benchmarks` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-library + :feature:foryou[foryou]:::android-library + :feature:interests[interests]:::android-library + :feature:search[search]:::android-library + :feature:settings[settings]:::android-library + :feature:topic[topic]:::android-library + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + :benchmarks[benchmarks]:::android-test + :app[app]:::android-application + + :app -.->|baselineProfile| :benchmarks + :app -.-> :core:analytics + :app -.-> :core:common + :app -.-> :core:data + :app -.-> :core:designsystem + :app -.-> :core:model + :app -.-> :core:ui + :app -.-> :feature:bookmarks + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:search + :app -.-> :feature:settings + :app -.-> :feature:topic + :app -.-> :sync:work + :benchmarks -.->|testedApks| :app + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/analytics/README.md b/core/analytics/README.md new file mode 100644 index 000000000..7248d2078 --- /dev/null +++ b/core/analytics/README.md @@ -0,0 +1,23 @@ +# `:core:analytics` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + end + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/common/README.md b/core/common/README.md new file mode 100644 index 000000000..fbb05367d --- /dev/null +++ b/core/common/README.md @@ -0,0 +1,23 @@ +# `:core:common` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm + end + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/data-test/README.md b/core/data-test/README.md new file mode 100644 index 000000000..a47212933 --- /dev/null +++ b/core/data-test/README.md @@ -0,0 +1,48 @@ +# `:core:data-test` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:data-test[data-test]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:data-test ---> :core:data + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/data/README.md b/core/data/README.md new file mode 100644 index 000000000..fdf93793d --- /dev/null +++ b/core/data/README.md @@ -0,0 +1,46 @@ +# `:core:data` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/database/README.md b/core/database/README.md new file mode 100644 index 000000000..cc3c5dd0d --- /dev/null +++ b/core/database/README.md @@ -0,0 +1,26 @@ +# `:core:database` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:database[database]:::android-library + :core:model[model]:::jvm + end + + :core:database ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/datastore-proto/README.md b/core/datastore-proto/README.md new file mode 100644 index 000000000..313935d82 --- /dev/null +++ b/core/datastore-proto/README.md @@ -0,0 +1,23 @@ +# `:core:datastore-proto` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:datastore-proto[datastore-proto]:::android-library + end + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/datastore-test/README.md b/core/datastore-test/README.md new file mode 100644 index 000000000..453e7fe13 --- /dev/null +++ b/core/datastore-test/README.md @@ -0,0 +1,33 @@ +# `:core:datastore-test` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:datastore-test[datastore-test]:::android-library + :core:model[model]:::jvm + end + + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:datastore-test -.-> :core:common + :core:datastore-test -.-> :core:datastore + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/datastore/README.md b/core/datastore/README.md new file mode 100644 index 000000000..32c1a2bdf --- /dev/null +++ b/core/datastore/README.md @@ -0,0 +1,30 @@ +# `:core:datastore` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + end + + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/designsystem/README.md b/core/designsystem/README.md new file mode 100644 index 000000000..f5fdc599d --- /dev/null +++ b/core/designsystem/README.md @@ -0,0 +1,23 @@ +# `:core:designsystem` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:designsystem[designsystem]:::android-library + end + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/domain/README.md b/core/domain/README.md new file mode 100644 index 000000000..cacdc2467 --- /dev/null +++ b/core/domain/README.md @@ -0,0 +1,49 @@ +# `:core:domain` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/model/README.md b/core/model/README.md new file mode 100644 index 000000000..11db83b5a --- /dev/null +++ b/core/model/README.md @@ -0,0 +1,23 @@ +# `:core:model` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:model[model]:::jvm + end + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/network/README.md b/core/network/README.md new file mode 100644 index 000000000..807907b8d --- /dev/null +++ b/core/network/README.md @@ -0,0 +1,28 @@ +# `:core:network` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm + :core:model[model]:::jvm + :core:network[network]:::android-library + end + + :core:network ---> :core:common + :core:network ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/notifications/README.md b/core/notifications/README.md new file mode 100644 index 000000000..7328236c8 --- /dev/null +++ b/core/notifications/README.md @@ -0,0 +1,28 @@ +# `:core:notifications` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm + :core:model[model]:::jvm + :core:notifications[notifications]:::android-library + end + + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/screenshot-testing/README.md b/core/screenshot-testing/README.md new file mode 100644 index 000000000..1e5c91e89 --- /dev/null +++ b/core/screenshot-testing/README.md @@ -0,0 +1,26 @@ +# `:core:screenshot-testing` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:designsystem[designsystem]:::android-library + :core:screenshot-testing[screenshot-testing]:::android-library + end + + :core:screenshot-testing -.-> :core:designsystem + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/testing/README.md b/core/testing/README.md new file mode 100644 index 000000000..9eb74ed24 --- /dev/null +++ b/core/testing/README.md @@ -0,0 +1,52 @@ +# `:core:testing` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:testing[testing]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:testing ---> :core:analytics + :core:testing ---> :core:common + :core:testing ---> :core:data + :core:testing ---> :core:model + :core:testing ---> :core:notifications + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/core/ui/README.md b/core/ui/README.md new file mode 100644 index 000000000..2e1d324af --- /dev/null +++ b/core/ui/README.md @@ -0,0 +1,30 @@ +# `:core:ui` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm + :core:ui[ui]:::android-library + end + + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/bookmarks/README.md b/feature/bookmarks/README.md new file mode 100644 index 000000000..667d1e277 --- /dev/null +++ b/feature/bookmarks/README.md @@ -0,0 +1,58 @@ +# `:feature:bookmarks` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/foryou/README.md b/feature/foryou/README.md new file mode 100644 index 000000000..a0846e6af --- /dev/null +++ b/feature/foryou/README.md @@ -0,0 +1,63 @@ +# `:feature:foryou` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:foryou[foryou]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/interests/README.md b/feature/interests/README.md new file mode 100644 index 000000000..143ce58bb --- /dev/null +++ b/feature/interests/README.md @@ -0,0 +1,62 @@ +# `:feature:interests` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:interests[interests]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/search/README.md b/feature/search/README.md new file mode 100644 index 000000000..9deedad41 --- /dev/null +++ b/feature/search/README.md @@ -0,0 +1,62 @@ +# `:feature:search` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:search[search]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:domain ---> :core:data + :core:domain ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/settings/README.md b/feature/settings/README.md new file mode 100644 index 000000000..c0c78931b --- /dev/null +++ b/feature/settings/README.md @@ -0,0 +1,58 @@ +# `:feature:settings` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:settings[settings]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/feature/topic/README.md b/feature/topic/README.md new file mode 100644 index 000000000..e10b7b4a1 --- /dev/null +++ b/feature/topic/README.md @@ -0,0 +1,58 @@ +# `:feature:topic` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:topic[topic]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :core:ui ---> :core:analytics + :core:ui ---> :core:designsystem + :core:ui ---> :core:model + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/sync/sync-test/README.md b/sync/sync-test/README.md new file mode 100644 index 000000000..29da495ae --- /dev/null +++ b/sync/sync-test/README.md @@ -0,0 +1,56 @@ +# `:sync:sync-test` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + subgraph :sync + direction TB + :sync:sync-test[sync-test]:::android-library + :sync:work[work]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :sync:sync-test -.-> :core:data + :sync:sync-test -.-> :sync:work + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/sync/work/README.md b/sync/work/README.md new file mode 100644 index 000000000..246742bbb --- /dev/null +++ b/sync/work/README.md @@ -0,0 +1,53 @@ +# `:sync:work` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + + :core:data -.-> :core:analytics + :core:data ---> :core:common + :core:data ---> :core:database + :core:data ---> :core:datastore + :core:data ---> :core:network + :core:data -.-> :core:notifications + :core:database ---> :core:model + :core:datastore -.-> :core:common + :core:datastore ---> :core:datastore-proto + :core:datastore ---> :core:model + :core:network ---> :core:common + :core:network ---> :core:model + :core:notifications -.-> :core:common + :core:notifications ---> :core:model + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + diff --git a/ui-test-hilt-manifest/README.md b/ui-test-hilt-manifest/README.md new file mode 100644 index 000000000..92f93ca64 --- /dev/null +++ b/ui-test-hilt-manifest/README.md @@ -0,0 +1,20 @@ +# `:ui-test-hilt-manifest` + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + :ui-test-hilt-manifest[ui-test-hilt-manifest]:::android-library + +classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; +classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; +classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +``` + From 5e34fb49c04717265d5351035fcc87f6bba6ed18 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Wed, 3 Sep 2025 22:15:26 +0200 Subject: [PATCH 05/11] Create `RootPlugin` to `configureGraphTasks()` on `subprojects` --- build-logic/convention/build.gradle.kts | 4 +++ .../AndroidApplicationConventionPlugin.kt | 2 -- .../kotlin/AndroidLibraryConventionPlugin.kt | 2 -- .../kotlin/AndroidTestConventionPlugin.kt | 2 -- .../main/kotlin/JvmLibraryConventionPlugin.kt | 2 -- .../convention/src/main/kotlin/RootPlugin.kt | 26 +++++++++++++++++++ .../google/samples/apps/nowinandroid/Graph.kt | 2 +- build.gradle.kts | 1 + gradle/libs.versions.toml | 1 + 9 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 build-logic/convention/src/main/kotlin/RootPlugin.kt diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 958ae82f5..166b54907 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -114,5 +114,9 @@ gradlePlugin { id = libs.plugins.nowinandroid.jvm.library.get().pluginId implementationClass = "JvmLibraryConventionPlugin" } + register("root") { + id = libs.plugins.nowinandroid.root.get().pluginId + implementationClass = "RootPlugin" + } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 4fa7a7afa..f45d664b7 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -18,7 +18,6 @@ import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.google.samples.apps.nowinandroid.configureBadgingTasks import com.google.samples.apps.nowinandroid.configureGradleManagedDevices -import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configurePrintApksTask import org.gradle.api.Plugin @@ -46,7 +45,6 @@ class AndroidApplicationConventionPlugin : Plugin { configurePrintApksTask(this) configureBadgingTasks(extensions.getByType(), this) } - configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index c4f464101..0f6fde884 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -18,7 +18,6 @@ import com.android.build.api.dsl.LibraryExtension import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureGradleManagedDevices -import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configurePrintApksTask import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests @@ -60,7 +59,6 @@ class AndroidLibraryConventionPlugin : Plugin { "implementation"(libs.findLibrary("androidx.tracing.ktx").get()) } - configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt index 9221cbf08..49c2eecec 100644 --- a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -16,7 +16,6 @@ import com.android.build.api.dsl.TestExtension import com.google.samples.apps.nowinandroid.configureGradleManagedDevices -import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinAndroid import org.gradle.api.Plugin import org.gradle.api.Project @@ -34,7 +33,6 @@ class AndroidTestConventionPlugin : Plugin { defaultConfig.targetSdk = 35 configureGradleManagedDevices(this) } - configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt index 2866de1a2..a1477891d 100644 --- a/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/JvmLibraryConventionPlugin.kt @@ -14,7 +14,6 @@ * limitations under the License. */ -import com.google.samples.apps.nowinandroid.configureGraphTasks import com.google.samples.apps.nowinandroid.configureKotlinJvm import com.google.samples.apps.nowinandroid.libs import org.gradle.api.Plugin @@ -32,7 +31,6 @@ class JvmLibraryConventionPlugin : Plugin { dependencies { "testImplementation"(libs.findLibrary("kotlin.test").get()) } - configureGraphTasks() } } } diff --git a/build-logic/convention/src/main/kotlin/RootPlugin.kt b/build-logic/convention/src/main/kotlin/RootPlugin.kt new file mode 100644 index 000000000..b704adf76 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/RootPlugin.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.google.samples.apps.nowinandroid.configureGraphTasks +import org.gradle.api.Plugin +import org.gradle.api.Project + +class RootPlugin : Plugin { + override fun apply(target: Project) { + require(target.path == ":") + target.subprojects { configureGraphTasks() } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt index 41c39c453..c9a71dde2 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt @@ -120,7 +120,7 @@ internal enum class PluginType(val id: String, val ref: String, val style: Strin ), } -fun Project.configureGraphTasks() { +internal fun Project.configureGraphTasks() { val dumpTask = tasks.register("graphDump") { val graph = Graph(this@configureGraphTasks).invoke() projectPath = this@configureGraphTasks.path diff --git a/build.gradle.kts b/build.gradle.kts index 0981b8920..594f7f92e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,4 +38,5 @@ plugins { alias(libs.plugins.roborazzi) apply false alias(libs.plugins.google.osslicenses) apply false alias(libs.plugins.room) apply false + alias(libs.plugins.nowinandroid.root) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6f75a2aca..22692120d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -194,3 +194,4 @@ nowinandroid-android-room = { id = "nowinandroid.android.room" } nowinandroid-android-test = { id = "nowinandroid.android.test" } nowinandroid-hilt = { id = "nowinandroid.hilt" } nowinandroid-jvm-library = { id = "nowinandroid.jvm.library" } +nowinandroid-root = { id = "nowinandroid.root" } From 175164f76f3a48d2cb758cd1a1cbafdc572253bd Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Wed, 3 Sep 2025 22:51:13 +0200 Subject: [PATCH 06/11] Detect changes when rendering graphs and auto-commit --- .github/workflows/Build.yaml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a4a49b8ee..1e67aefbb 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -77,6 +77,35 @@ jobs: disable_globbing: true commit_message: "🤖 Updates baselines for Dependency Guard" + - name: Update Graphs + run: ./gradlew updateGraph + + - name: Check Graphs + id: graphs_verify + run: git add -- '**/README.md' && git diff --cached --quiet --exit-code -- '**/README.md' + + - name: Prevent updating graphs if this is a fork + id: checkfork_graphs + continue-on-error: false + if: steps.graphs_verify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository + run: | + echo "::error::Check Graphs failed, please update graphs with: ./gradlew updateGraph" && exit 1 + + # Runs if previous job failed + - name: Generate new Dependency Guard baselines if verification failed and it's a PR + id: dependencyguard_baseline + if: steps.dependencyguard_verify.outcome == 'failure' && github.event_name == 'pull_request' + run: | + ./gradlew dependencyGuardBaseline + + - name: Push new graphs if available + if: steps.graphs_verify.outcome == 'failure' && github.event_name == 'pull_request' + uses: stefanzweifel/git-auto-commit-action@v5 + with: + file_pattern: '**/README.md' + disable_globbing: true + commit_message: "🤖 Updates graphs" + - name: Run all local screenshot tests (Roborazzi) id: screenshotsverify continue-on-error: true From 1c61be7b7b607a07828baa8b9d1e621f1a2b9cbc Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 14 Sep 2025 15:41:13 +0200 Subject: [PATCH 07/11] Update color mapping | Type | Plugin ID | Color | |-------------|------------------------------------|------------------------| | Application | `nowinandroid.android.application` | `#CAFFBF` PastelGreen | | Feature | `nowinandroid.android.feature` | `#FFD6A5` PastelOrange | | Library | `nowinandroid.android.library` | `#9BF6FF` PastelBlue | | Test | `nowinandroid.android.test` | `#A0C4FF` PastelMauve | | JVM | `nowinandroid.jvm.library` | `#BDB2FF` PastelPurple | | Unknown | `?` | `#FFADAD` PastelRed | --- app-nia-catalog/README.md | 15 +++++---- app/README.md | 29 +++++++++-------- benchmarks/README.md | 29 +++++++++-------- .../google/samples/apps/nowinandroid/Graph.kt | 32 ++++++++++++------- core/analytics/README.md | 13 +++++--- core/common/README.md | 15 +++++---- core/data-test/README.md | 17 ++++++---- core/data/README.md | 17 ++++++---- core/database/README.md | 15 +++++---- core/datastore-proto/README.md | 13 +++++--- core/datastore-test/README.md | 17 ++++++---- core/datastore/README.md | 17 ++++++---- core/designsystem/README.md | 13 +++++--- core/domain/README.md | 17 ++++++---- core/model/README.md | 15 +++++---- core/network/README.md | 17 ++++++---- core/notifications/README.md | 17 ++++++---- core/screenshot-testing/README.md | 13 +++++--- core/testing/README.md | 17 ++++++---- core/ui/README.md | 15 +++++---- feature/bookmarks/README.md | 19 ++++++----- feature/foryou/README.md | 19 ++++++----- feature/interests/README.md | 19 ++++++----- feature/search/README.md | 19 ++++++----- feature/settings/README.md | 19 ++++++----- feature/topic/README.md | 19 ++++++----- lint/README.md | 23 +++++++++++++ sync/sync-test/README.md | 17 ++++++---- sync/work/README.md | 17 ++++++---- ui-test-hilt-manifest/README.md | 13 +++++--- 30 files changed, 326 insertions(+), 211 deletions(-) create mode 100644 lint/README.md diff --git a/app-nia-catalog/README.md b/app-nia-catalog/README.md index a0b2bb6f6..1b71784e8 100644 --- a/app-nia-catalog/README.md +++ b/app-nia-catalog/README.md @@ -1,5 +1,7 @@ # `:app-nia-catalog` +## Module dependency graph + ```mermaid --- @@ -13,7 +15,7 @@ graph TB direction TB :core:analytics[analytics]:::android-library :core:designsystem[designsystem]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:ui[ui]:::android-library end :app-nia-catalog[app-nia-catalog]:::android-application @@ -24,10 +26,11 @@ graph TB :core:ui ---> :core:designsystem :core:ui ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/app/README.md b/app/README.md index 020aecd28..0a75a68d0 100644 --- a/app/README.md +++ b/app/README.md @@ -1,5 +1,7 @@ # `:app` +## Module dependency graph + ```mermaid --- @@ -12,26 +14,26 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:bookmarks[bookmarks]:::android-library - :feature:foryou[foryou]:::android-library - :feature:interests[interests]:::android-library - :feature:search[search]:::android-library - :feature:settings[settings]:::android-library - :feature:topic[topic]:::android-library + :feature:bookmarks[bookmarks]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:search[search]:::android-feature + :feature:settings[settings]:::android-feature + :feature:topic[topic]:::android-feature end subgraph :sync direction TB @@ -100,10 +102,11 @@ graph TB :sync:work -.-> :core:data :sync:work -.-> :core:notifications -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/benchmarks/README.md b/benchmarks/README.md index 6e91ce55d..26f4e4f1a 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -1,5 +1,7 @@ # `:benchmarks` +## Module dependency graph + ```mermaid --- @@ -12,26 +14,26 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:bookmarks[bookmarks]:::android-library - :feature:foryou[foryou]:::android-library - :feature:interests[interests]:::android-library - :feature:search[search]:::android-library - :feature:settings[settings]:::android-library - :feature:topic[topic]:::android-library + :feature:bookmarks[bookmarks]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:search[search]:::android-feature + :feature:settings[settings]:::android-feature + :feature:topic[topic]:::android-feature end subgraph :sync direction TB @@ -100,10 +102,11 @@ graph TB :sync:work -.-> :core:data :sync:work -.-> :core:notifications -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt index c9a71dde2..85d5b956d 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt @@ -94,33 +94,39 @@ private class Graph( */ internal enum class PluginType(val id: String, val ref: String, val style: String) { AndroidApplication( - id = "com.android.application", + id = "nowinandroid.android.application", ref = "android-application", - style = "fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff", + style = "fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000", + ), + AndroidFeature( + id = "nowinandroid.android.feature", + ref = "android-feature", + style = "fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000", ), AndroidLibrary( - id = "com.android.library", + id = "nowinandroid.android.library", ref = "android-library", - style = "fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff", + style = "fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000", ), AndroidTest( - id = "com.android.test", + id = "nowinandroid.android.test", ref = "android-test", - style = "fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff", + style = "fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000", ), Jvm( - id = "org.jetbrains.kotlin.jvm", - ref = "jvm", - style = "fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff", + id = "nowinandroid.jvm.library", + ref = "jvm-library", + style = "fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000", ), Unknown( id = "?", ref = "unknown", - style = "fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff", + style = "fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000", ), } internal fun Project.configureGraphTasks() { + if (!buildFile.exists()) return // Ignore root modules without build file val dumpTask = tasks.register("graphDump") { val graph = Graph(this@configureGraphTasks).invoke() projectPath = this@configureGraphTasks.path @@ -252,9 +258,11 @@ private abstract class GraphUpdateTask : DefaultTask() { writeText( """ # `${projectPath.get()}` - + + ## Module dependency graph + - + """.trimIndent(), ) } diff --git a/core/analytics/README.md b/core/analytics/README.md index 7248d2078..0441403b1 100644 --- a/core/analytics/README.md +++ b/core/analytics/README.md @@ -1,5 +1,7 @@ # `:core:analytics` +## Module dependency graph + ```mermaid --- @@ -14,10 +16,11 @@ graph TB :core:analytics[analytics]:::android-library end -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/common/README.md b/core/common/README.md index fbb05367d..e385e9b2d 100644 --- a/core/common/README.md +++ b/core/common/README.md @@ -1,5 +1,7 @@ # `:core:common` +## Module dependency graph + ```mermaid --- @@ -11,13 +13,14 @@ config: graph TB subgraph :core direction TB - :core:common[common]:::jvm + :core:common[common]:::jvm-library end -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/data-test/README.md b/core/data-test/README.md index a47212933..ac7fdce83 100644 --- a/core/data-test/README.md +++ b/core/data-test/README.md @@ -1,5 +1,7 @@ # `:core:data-test` +## Module dependency graph + ```mermaid --- @@ -12,13 +14,13 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:data-test[data-test]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library end @@ -39,10 +41,11 @@ graph TB :core:notifications -.-> :core:common :core:notifications ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/data/README.md b/core/data/README.md index fdf93793d..57a101df5 100644 --- a/core/data/README.md +++ b/core/data/README.md @@ -1,5 +1,7 @@ # `:core:data` +## Module dependency graph + ```mermaid --- @@ -12,12 +14,12 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library end @@ -37,10 +39,11 @@ graph TB :core:notifications -.-> :core:common :core:notifications ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/database/README.md b/core/database/README.md index cc3c5dd0d..98d5907f5 100644 --- a/core/database/README.md +++ b/core/database/README.md @@ -1,5 +1,7 @@ # `:core:database` +## Module dependency graph + ```mermaid --- @@ -12,15 +14,16 @@ graph TB subgraph :core direction TB :core:database[database]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library end :core:database ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/datastore-proto/README.md b/core/datastore-proto/README.md index 313935d82..b3985d45b 100644 --- a/core/datastore-proto/README.md +++ b/core/datastore-proto/README.md @@ -1,5 +1,7 @@ # `:core:datastore-proto` +## Module dependency graph + ```mermaid --- @@ -14,10 +16,11 @@ graph TB :core:datastore-proto[datastore-proto]:::android-library end -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/datastore-test/README.md b/core/datastore-test/README.md index 453e7fe13..988172cff 100644 --- a/core/datastore-test/README.md +++ b/core/datastore-test/README.md @@ -1,5 +1,7 @@ # `:core:datastore-test` +## Module dependency graph + ```mermaid --- @@ -11,11 +13,11 @@ config: graph TB subgraph :core direction TB - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:datastore-test[datastore-test]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library end :core:datastore -.-> :core:common @@ -24,10 +26,11 @@ graph TB :core:datastore-test -.-> :core:common :core:datastore-test -.-> :core:datastore -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/datastore/README.md b/core/datastore/README.md index 32c1a2bdf..710567e73 100644 --- a/core/datastore/README.md +++ b/core/datastore/README.md @@ -1,5 +1,7 @@ # `:core:datastore` +## Module dependency graph + ```mermaid --- @@ -11,20 +13,21 @@ config: graph TB subgraph :core direction TB - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library end :core:datastore -.-> :core:common :core:datastore ---> :core:datastore-proto :core:datastore ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/designsystem/README.md b/core/designsystem/README.md index f5fdc599d..eeedb3093 100644 --- a/core/designsystem/README.md +++ b/core/designsystem/README.md @@ -1,5 +1,7 @@ # `:core:designsystem` +## Module dependency graph + ```mermaid --- @@ -14,10 +16,11 @@ graph TB :core:designsystem[designsystem]:::android-library end -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/domain/README.md b/core/domain/README.md index cacdc2467..c92d4e18d 100644 --- a/core/domain/README.md +++ b/core/domain/README.md @@ -1,5 +1,7 @@ # `:core:domain` +## Module dependency graph + ```mermaid --- @@ -12,13 +14,13 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library end @@ -40,10 +42,11 @@ graph TB :core:notifications -.-> :core:common :core:notifications ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/model/README.md b/core/model/README.md index 11db83b5a..175ecdd3a 100644 --- a/core/model/README.md +++ b/core/model/README.md @@ -1,5 +1,7 @@ # `:core:model` +## Module dependency graph + ```mermaid --- @@ -11,13 +13,14 @@ config: graph TB subgraph :core direction TB - :core:model[model]:::jvm + :core:model[model]:::jvm-library end -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/network/README.md b/core/network/README.md index 807907b8d..3fcd8d9a4 100644 --- a/core/network/README.md +++ b/core/network/README.md @@ -1,5 +1,7 @@ # `:core:network` +## Module dependency graph + ```mermaid --- @@ -11,18 +13,19 @@ config: graph TB subgraph :core direction TB - :core:common[common]:::jvm - :core:model[model]:::jvm + :core:common[common]:::jvm-library + :core:model[model]:::jvm-library :core:network[network]:::android-library end :core:network ---> :core:common :core:network ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/notifications/README.md b/core/notifications/README.md index 7328236c8..1c73d0b2b 100644 --- a/core/notifications/README.md +++ b/core/notifications/README.md @@ -1,5 +1,7 @@ # `:core:notifications` +## Module dependency graph + ```mermaid --- @@ -11,18 +13,19 @@ config: graph TB subgraph :core direction TB - :core:common[common]:::jvm - :core:model[model]:::jvm + :core:common[common]:::jvm-library + :core:model[model]:::jvm-library :core:notifications[notifications]:::android-library end :core:notifications -.-> :core:common :core:notifications ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/screenshot-testing/README.md b/core/screenshot-testing/README.md index 1e5c91e89..d8e942128 100644 --- a/core/screenshot-testing/README.md +++ b/core/screenshot-testing/README.md @@ -1,5 +1,7 @@ # `:core:screenshot-testing` +## Module dependency graph + ```mermaid --- @@ -17,10 +19,11 @@ graph TB :core:screenshot-testing -.-> :core:designsystem -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/testing/README.md b/core/testing/README.md index 9eb74ed24..6dd50a19d 100644 --- a/core/testing/README.md +++ b/core/testing/README.md @@ -1,5 +1,7 @@ # `:core:testing` +## Module dependency graph + ```mermaid --- @@ -12,12 +14,12 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:testing[testing]:::android-library @@ -43,10 +45,11 @@ graph TB :core:testing ---> :core:model :core:testing ---> :core:notifications -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/core/ui/README.md b/core/ui/README.md index 2e1d324af..f1a48f7c4 100644 --- a/core/ui/README.md +++ b/core/ui/README.md @@ -1,5 +1,7 @@ # `:core:ui` +## Module dependency graph + ```mermaid --- @@ -13,7 +15,7 @@ graph TB direction TB :core:analytics[analytics]:::android-library :core:designsystem[designsystem]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:ui[ui]:::android-library end @@ -21,10 +23,11 @@ graph TB :core:ui ---> :core:designsystem :core:ui ---> :core:model -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/bookmarks/README.md b/feature/bookmarks/README.md index 667d1e277..c105a914e 100644 --- a/feature/bookmarks/README.md +++ b/feature/bookmarks/README.md @@ -1,5 +1,7 @@ # `:feature:bookmarks` +## Module dependency graph + ```mermaid --- @@ -12,20 +14,20 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:bookmarks[bookmarks]:::android-library + :feature:bookmarks[bookmarks]:::android-feature end :core:data -.-> :core:analytics @@ -49,10 +51,11 @@ graph TB :feature:bookmarks -.-> :core:designsystem :feature:bookmarks -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/foryou/README.md b/feature/foryou/README.md index a0846e6af..bd4517694 100644 --- a/feature/foryou/README.md +++ b/feature/foryou/README.md @@ -1,5 +1,7 @@ # `:feature:foryou` +## Module dependency graph + ```mermaid --- @@ -12,21 +14,21 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:foryou[foryou]:::android-library + :feature:foryou[foryou]:::android-feature end :core:data -.-> :core:analytics @@ -54,10 +56,11 @@ graph TB :feature:foryou -.-> :core:notifications :feature:foryou -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/interests/README.md b/feature/interests/README.md index 143ce58bb..423dd2da3 100644 --- a/feature/interests/README.md +++ b/feature/interests/README.md @@ -1,5 +1,7 @@ # `:feature:interests` +## Module dependency graph + ```mermaid --- @@ -12,21 +14,21 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:interests[interests]:::android-library + :feature:interests[interests]:::android-feature end :core:data -.-> :core:analytics @@ -53,10 +55,11 @@ graph TB :feature:interests -.-> :core:domain :feature:interests -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/search/README.md b/feature/search/README.md index 9deedad41..ffaa130f9 100644 --- a/feature/search/README.md +++ b/feature/search/README.md @@ -1,5 +1,7 @@ # `:feature:search` +## Module dependency graph + ```mermaid --- @@ -12,21 +14,21 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library :core:domain[domain]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:search[search]:::android-library + :feature:search[search]:::android-feature end :core:data -.-> :core:analytics @@ -53,10 +55,11 @@ graph TB :feature:search -.-> :core:domain :feature:search -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/settings/README.md b/feature/settings/README.md index c0c78931b..6440cc4c9 100644 --- a/feature/settings/README.md +++ b/feature/settings/README.md @@ -1,5 +1,7 @@ # `:feature:settings` +## Module dependency graph + ```mermaid --- @@ -12,20 +14,20 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:settings[settings]:::android-library + :feature:settings[settings]:::android-feature end :core:data -.-> :core:analytics @@ -49,10 +51,11 @@ graph TB :feature:settings -.-> :core:designsystem :feature:settings -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/feature/topic/README.md b/feature/topic/README.md index e10b7b4a1..df25443b3 100644 --- a/feature/topic/README.md +++ b/feature/topic/README.md @@ -1,5 +1,7 @@ # `:feature:topic` +## Module dependency graph + ```mermaid --- @@ -12,20 +14,20 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library :core:designsystem[designsystem]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB - :feature:topic[topic]:::android-library + :feature:topic[topic]:::android-feature end :core:data -.-> :core:analytics @@ -49,10 +51,11 @@ graph TB :feature:topic -.-> :core:designsystem :feature:topic -.-> :core:ui -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/lint/README.md b/lint/README.md new file mode 100644 index 000000000..4529d5b07 --- /dev/null +++ b/lint/README.md @@ -0,0 +1,23 @@ +# `:lint` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + :lint[lint]:::unknown + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + diff --git a/sync/sync-test/README.md b/sync/sync-test/README.md index 29da495ae..0a4feaa46 100644 --- a/sync/sync-test/README.md +++ b/sync/sync-test/README.md @@ -1,5 +1,7 @@ # `:sync:sync-test` +## Module dependency graph + ```mermaid --- @@ -12,12 +14,12 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library end @@ -47,10 +49,11 @@ graph TB :sync:work -.-> :core:data :sync:work -.-> :core:notifications -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/sync/work/README.md b/sync/work/README.md index 246742bbb..e39919a7e 100644 --- a/sync/work/README.md +++ b/sync/work/README.md @@ -1,5 +1,7 @@ # `:sync:work` +## Module dependency graph + ```mermaid --- @@ -12,12 +14,12 @@ graph TB subgraph :core direction TB :core:analytics[analytics]:::android-library - :core:common[common]:::jvm + :core:common[common]:::jvm-library :core:data[data]:::android-library :core:database[database]:::android-library :core:datastore[datastore]:::android-library :core:datastore-proto[datastore-proto]:::android-library - :core:model[model]:::jvm + :core:model[model]:::jvm-library :core:network[network]:::android-library :core:notifications[notifications]:::android-library end @@ -44,10 +46,11 @@ graph TB :sync:work -.-> :core:data :sync:work -.-> :core:notifications -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` diff --git a/ui-test-hilt-manifest/README.md b/ui-test-hilt-manifest/README.md index 92f93ca64..2b33713b1 100644 --- a/ui-test-hilt-manifest/README.md +++ b/ui-test-hilt-manifest/README.md @@ -1,5 +1,7 @@ # `:ui-test-hilt-manifest` +## Module dependency graph + ```mermaid --- @@ -11,10 +13,11 @@ config: graph TB :ui-test-hilt-manifest[ui-test-hilt-manifest]:::android-library -classDef android-application fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-library fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef android-test fill:#3BD482,stroke:#fff,stroke-width:2px,color:#fff; -classDef jvm fill:#7F52FF,stroke:#fff,stroke-width:2px,color:#fff; -classDef unknown fill:#FF0000,stroke:#fff,stroke-width:2px,color:#fff; +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; ``` From 0a352c2b357055e4b8b95feaacf6daac844530b1 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 14 Sep 2025 15:42:33 +0200 Subject: [PATCH 08/11] Replace old diagram with new mermaid graph in ModularizationLearningJourney --- docs/ModularizationLearningJourney.md | 52 +++++++++++++++++++- docs/images/modularization-graph.drawio.png | Bin 97387 -> 0 bytes 2 files changed, 51 insertions(+), 1 deletion(-) delete mode 100644 docs/images/modularization-graph.drawio.png diff --git a/docs/ModularizationLearningJourney.md b/docs/ModularizationLearningJourney.md index a9766c68d..14c19e12e 100644 --- a/docs/ModularizationLearningJourney.md +++ b/docs/ModularizationLearningJourney.md @@ -85,7 +85,57 @@ how you can organize your project. In general, you should strive for low couplin ## Types of modules in Now in Android -![Diagram showing types of modules and their dependencies in Now in Android](images/modularization-graph.drawio.png "Diagram showing types of modules and their dependencies in Now in Android") +```mermaid +graph TB + subgraph :core + direction TB + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:topic[topic]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:foo[...]:::android-feature + + end + :app[app]:::android-application + + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:topic + :core:data ---> :core:database + :core:data ---> :core:network + :core:database ---> :core:model + :core:network ---> :core:model + :core:ui ---> :core:model + :feature:topic -.-> :core:data + :feature:topic -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application:::android-application -. implementation .-> feature:::android-feature + library:::android-library -- api --> jvm:::jvm-library + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +``` + +
**Top tip**: A module graph (shown above) can be useful during modularization planning for visualizing dependencies between modules. diff --git a/docs/images/modularization-graph.drawio.png b/docs/images/modularization-graph.drawio.png deleted file mode 100644 index fb5bc375be84a5860a2a1891652ba11bf0fdfe5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97387 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 Date: Sun, 14 Sep 2025 15:42:49 +0200 Subject: [PATCH 09/11] Document `graphUpdate` task --- docs/ModularizationLearningJourney.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/ModularizationLearningJourney.md b/docs/ModularizationLearningJourney.md index 14c19e12e..5cda61b69 100644 --- a/docs/ModularizationLearningJourney.md +++ b/docs/ModularizationLearningJourney.md @@ -283,6 +283,9 @@ Using the above modularization strategy, the Now in Android app has the followin +Each module has its own `README.md` file containing a module graph (e.g. [`:app` module graph](../app/README.md#module-dependency-graph)). +When modules dependencies change, module graphs are automatically updated by the [Build.yaml](../.github/workflows/Build.yaml) workflow. +You can also manually update the graphs by running the `graphUpdate` task. ## Modularization in Now in Android From 29e3dae0621aaf7a6e6928b7516d88a25259ceb6 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 14 Sep 2025 15:52:06 +0200 Subject: [PATCH 10/11] Fix workflow --- .github/workflows/Build.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 1e67aefbb..4f0ee9fe8 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -91,13 +91,6 @@ jobs: run: | echo "::error::Check Graphs failed, please update graphs with: ./gradlew updateGraph" && exit 1 - # Runs if previous job failed - - name: Generate new Dependency Guard baselines if verification failed and it's a PR - id: dependencyguard_baseline - if: steps.dependencyguard_verify.outcome == 'failure' && github.event_name == 'pull_request' - run: | - ./gradlew dependencyGuardBaseline - - name: Push new graphs if available if: steps.graphs_verify.outcome == 'failure' && github.event_name == 'pull_request' uses: stefanzweifel/git-auto-commit-action@v5 From c21ce2dcbe12eee346be2d39511aaf840a09741e Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sun, 14 Sep 2025 15:59:45 +0200 Subject: [PATCH 11/11] Fix graphUpdate naming in workflow --- .github/workflows/Build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 4f0ee9fe8..2a52855b8 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -78,7 +78,7 @@ jobs: commit_message: "🤖 Updates baselines for Dependency Guard" - name: Update Graphs - run: ./gradlew updateGraph + run: ./gradlew graphUpdate - name: Check Graphs id: graphs_verify @@ -89,7 +89,7 @@ jobs: continue-on-error: false if: steps.graphs_verify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository run: | - echo "::error::Check Graphs failed, please update graphs with: ./gradlew updateGraph" && exit 1 + echo "::error::Check Graphs failed, please update graphs with: ./gradlew graphUpdate" && exit 1 - name: Push new graphs if available if: steps.graphs_verify.outcome == 'failure' && github.event_name == 'pull_request'