Skip to content

Commit a7df0f5

Browse files
committed
Address Issue #258: Configuration predicate to control dependency graph creation
Adds a new configuration option to allow the consumer to provision of a `Predicate<Configuration>` instance to customize what `Configuration` instances should be considered when building the dependency graph. # Conflicts: # affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt # affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/DependencyTracker.kt # affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt # affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetectorImplTest.kt
1 parent 199638c commit a7df0f5

File tree

8 files changed

+411
-15
lines changed

8 files changed

+411
-15
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ affectedModuleDetector {
105105
"Run static analysis tool without auto-correction by Impact analysis"
106106
)
107107
]
108+
configurationPredicate = new Predicate<Configuration>() {
109+
boolean test(Configuration configuration) {
110+
return !configuration.name.contains("somethingToExclude")
111+
}
112+
}
108113
}
109114
```
110115

@@ -128,6 +133,7 @@ affectedModuleDetector {
128133
- `includeUncommitted`: If uncommitted files should be considered affected
129134
- `top`: The top of the git log to use. Must be used in combination with configuration `includeUncommitted = false`
130135
- `customTasks`: set of [CustomTask](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt)
136+
- `configurationPredicate`: A predicate to filter configurations that should be considered for the dependency graph. By default, all configurations are considered.
131137

132138
By default, the Detector will look for `assembleAndroidDebugTest`, `connectedAndroidDebugTest`, and `testDebug`. Modules can specify a configuration block to specify which variant tests to run:
133139
```groovy

affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.dropbox.affectedmoduledetector
22

33
import com.dropbox.affectedmoduledetector.util.toOsSpecificPath
4+
import org.gradle.api.artifacts.Configuration
45
import java.io.File
56
import java.io.Serializable
7+
import java.util.function.Predicate
68

79
class AffectedModuleConfiguration : Serializable {
810

@@ -45,6 +47,13 @@ class AffectedModuleConfiguration : Serializable {
4547
*/
4648
var customTasks = emptySet<CustomTask>()
4749

50+
/**
51+
* Predicate to determine if a configuration should be considered or ignored. This predicate
52+
* will be called for every configuration defined by each project module. By default,
53+
* all configurations are considered.
54+
*/
55+
var configurationPredicate: Predicate<Configuration> = AlwaysConfigurationPredicate()
56+
4857
/**
4958
* Folder to place the log in
5059
*/
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.dropbox.affectedmoduledetector
2+
3+
import org.gradle.api.artifacts.Configuration
4+
import java.util.function.Predicate
5+
6+
/**
7+
* Default implementation of a [Configuration] [Predicate] that always returns true, indicating
8+
* that all configurations should be considered.
9+
*/
10+
internal class AlwaysConfigurationPredicate : Predicate<Configuration> {
11+
override fun test(t: Configuration): Boolean {
12+
return true
13+
}
14+
}

affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/DependencyTracker.kt

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,30 @@ import java.io.Serializable
3030
*/
3131
class DependencyTracker(rootProject: Project, logger: Logger?) : Serializable {
3232

33+
private val configuration: AffectedModuleConfiguration by lazy {
34+
rootProject.extensions.getByType(AffectedModuleConfiguration::class.java)
35+
}
36+
3337
private val dependentList: Map<ProjectPath, Set<ProjectPath>> by lazy {
3438
val result = mutableMapOf<ProjectPath, MutableSet<ProjectPath>>()
3539
rootProject.subprojects.forEach { project ->
3640
logger?.info("checking ${project.path} for dependencies")
37-
project.configurations.forEach { config ->
38-
logger?.info("checking config ${project.path}/$config for dependencies")
39-
config
40-
.dependencies
41-
.filterIsInstance<ProjectDependency>()
42-
.forEach {
43-
logger?.info(
44-
"there is a dependency from ${project.projectPath} to " +
45-
it.path,
46-
)
47-
result.getOrPut(ProjectPath(it.path)) { mutableSetOf() }
48-
.add(project.projectPath)
49-
}
50-
}
41+
project.configurations
42+
.filter(configuration.configurationPredicate::test)
43+
.forEach { config ->
44+
logger?.info("checking config ${project.path}/$config for dependencies")
45+
config
46+
.dependencies
47+
.filterIsInstance<ProjectDependency>()
48+
.forEach {
49+
logger?.info(
50+
"there is a dependency from ${project.projectPath} to " +
51+
it.path,
52+
)
53+
result.getOrPut(ProjectPath(it.path)) { mutableSetOf() }
54+
.add(project.projectPath)
55+
}
56+
}
5157
}
5258
result
5359
}

affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.dropbox.affectedmoduledetector
22

3+
import com.dropbox.affectedmoduledetector.mocks.MockConfiguration
34
import com.google.common.truth.Truth.assertThat
5+
import org.gradle.api.artifacts.Configuration
46
import org.junit.Assert.assertFalse
57
import org.junit.Assert.assertTrue
68
import org.junit.Assert.fail
@@ -11,6 +13,7 @@ import org.junit.rules.TemporaryFolder
1113
import org.junit.runner.RunWith
1214
import org.junit.runners.JUnit4
1315
import java.io.File
16+
import java.util.function.Predicate
1417

1518
@RunWith(JUnit4::class)
1619
class AffectedModuleConfigurationTest {
@@ -376,4 +379,27 @@ class AffectedModuleConfigurationTest {
376379
// THEN
377380
assertFalse(actual)
378381
}
382+
383+
@Test
384+
fun `GIVEN AffectedModuleConfiguration WHEN configuration predicate is set THEN is configuration predicate`() {
385+
// GIVEN
386+
config.configurationPredicate = Predicate<Configuration> { false }
387+
388+
// WHEN
389+
val actual = config.configurationPredicate.test(MockConfiguration())
390+
391+
// THEN
392+
assertFalse(actual)
393+
}
394+
395+
@Test
396+
fun `GIVEN AffectedModuleConfiguration WHEN configuration predicate is not set THEN is default`() {
397+
// GIVEN default configuration
398+
399+
// WHEN
400+
val actual = config.configurationPredicate.test(MockConfiguration())
401+
402+
// THEN
403+
assertTrue(actual)
404+
}
379405
}

affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetectorImplTest.kt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.junit.rules.TemporaryFolder
1515
import org.junit.runner.RunWith
1616
import org.junit.runners.JUnit4
1717
import java.io.File
18+
import java.util.function.Predicate
1819

1920
@RunWith(JUnit4::class)
2021
class AffectedModuleDetectorImplTest {
@@ -238,6 +239,9 @@ class AffectedModuleDetectorImplTest {
238239
it.baseDir = tmpDir.absolutePath
239240
it.pathsAffectingAllModules = pathsAffectingAllModules
240241
}
242+
listOf(root, root2, root3).forEach { rootProject ->
243+
rootProject.extensions.add(AffectedModuleConfiguration.name, affectedModuleConfiguration)
244+
}
241245
}
242246

243247
@Test
@@ -1773,6 +1777,59 @@ class AffectedModuleDetectorImplTest {
17731777
)
17741778
}
17751779

1780+
@Test
1781+
fun `GIVEN upward configuration reference from p2 to p6 WHEN no predicate is supplied THEN p2 is affected`() {
1782+
p2.configurations.create("p2-upward-p6") { config ->
1783+
config.dependencies.add(p2.dependencies.project(mapOf("path" to p6.path)))
1784+
}
1785+
val detector = AffectedModuleDetectorImpl(
1786+
projectGraph = rootProjectGraph,
1787+
dependencyTracker = rootDependencyTracker,
1788+
logger = logger.toLogger(),
1789+
ignoreUnknownProjects = false,
1790+
projectSubset = ProjectSubset.ALL_AFFECTED_PROJECTS,
1791+
modules = null,
1792+
changedFilesProvider = MockGitClient(
1793+
changedFiles = listOf(
1794+
convertToFilePath("d1/d3/d6", "foo.java")
1795+
),
1796+
tmpFolder = tmpFolder.root
1797+
).findChangedFiles(root),
1798+
gitRoot = tmpFolder.root,
1799+
config = affectedModuleConfiguration
1800+
)
1801+
Truth.assertThat(detector.shouldInclude(p2.projectPath)).isTrue()
1802+
Truth.assertThat(detector.shouldInclude(p6.projectPath)).isTrue()
1803+
}
1804+
1805+
@Test
1806+
fun `GIVEN upward configuration reference from p2 to p6 WHEN predicate filtered THEN p2 is unaffected`() {
1807+
p2.configurations.create("p2-upward-p6") { config ->
1808+
config.dependencies.add(p2.dependencies.project(mapOf("path" to p6.path)))
1809+
}
1810+
affectedModuleConfiguration.configurationPredicate = Predicate { configuration ->
1811+
!configuration.name.contains("-upward-")
1812+
}
1813+
val detector = AffectedModuleDetectorImpl(
1814+
projectGraph = rootProjectGraph,
1815+
dependencyTracker = rootDependencyTracker,
1816+
logger = logger.toLogger(),
1817+
ignoreUnknownProjects = false,
1818+
projectSubset = ProjectSubset.ALL_AFFECTED_PROJECTS,
1819+
modules = null,
1820+
changedFilesProvider = MockGitClient(
1821+
changedFiles = listOf(
1822+
convertToFilePath("d1/d3/d6", "foo.java")
1823+
),
1824+
tmpFolder = tmpFolder.root
1825+
).findChangedFiles(root),
1826+
gitRoot = tmpFolder.root,
1827+
config = affectedModuleConfiguration
1828+
)
1829+
Truth.assertThat(detector.shouldInclude(p2.projectPath)).isFalse()
1830+
Truth.assertThat(detector.shouldInclude(p6.projectPath)).isTrue()
1831+
}
1832+
17761833
// For both Linux/Windows
17771834
fun convertToFilePath(vararg list: String): String {
17781835
return list.toList().joinToString(File.separator)

affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetectorPluginTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import org.junit.Test
1010
import org.junit.rules.TemporaryFolder
1111
import org.junit.runner.RunWith
1212
import org.junit.runners.JUnit4
13-
import java.lang.IllegalStateException
1413

1514
@RunWith(JUnit4::class)
1615
class AffectedModuleDetectorPluginTest {

0 commit comments

Comments
 (0)