Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ affectedModuleDetector {
"Run static analysis tool without auto-correction by Impact analysis"
)
]
configurationPredicate = new Predicate<Configuration>() {
boolean test(Configuration configuration) {
return !configuration.name.contains("somethingToExclude")
}
}
}
```

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

By default, the Detector will look for `assembleAndroidDebugTest`, `connectedAndroidDebugTest`, and `testDebug`. Modules can specify a configuration block to specify which variant tests to run:
```groovy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.dropbox.affectedmoduledetector

import com.dropbox.affectedmoduledetector.util.toOsSpecificPath
import org.gradle.api.artifacts.Configuration
import java.io.File
import java.io.Serializable
import java.util.function.Predicate

class AffectedModuleConfiguration : Serializable {

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

/**
* Predicate to determine if a configuration should be considered or ignored. This predicate
* will be called for every configuration defined by each project module. By default,
* all configurations are considered.
*/
var configurationPredicate: Predicate<Configuration> = AlwaysConfigurationPredicate()

/**
* Folder to place the log in
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dropbox.affectedmoduledetector

import org.gradle.api.artifacts.Configuration
import java.util.function.Predicate

/**
* Default implementation of a [Configuration] [Predicate] that always returns true, indicating
* that all configurations should be considered.
*/
internal class AlwaysConfigurationPredicate : Predicate<Configuration> {
override fun test(t: Configuration): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,30 @@ import java.io.Serializable
*/
class DependencyTracker(rootProject: Project, logger: Logger?) : Serializable {

private val configuration: AffectedModuleConfiguration by lazy {
rootProject.extensions.getByType(AffectedModuleConfiguration::class.java)
}

private val dependentList: Map<ProjectPath, Set<ProjectPath>> by lazy {
val result = mutableMapOf<ProjectPath, MutableSet<ProjectPath>>()
rootProject.subprojects.forEach { project ->
logger?.info("checking ${project.path} for dependencies")
project.configurations.forEach { config ->
logger?.info("checking config ${project.path}/$config for dependencies")
config
.dependencies
.filterIsInstance<ProjectDependency>()
.forEach {
logger?.info(
"there is a dependency from ${project.projectPath} to " +
it.path,
)
result.getOrPut(ProjectPath(it.path)) { mutableSetOf() }
.add(project.projectPath)
}
}
project.configurations
.filter(configuration.configurationPredicate::test)
.forEach { config ->
logger?.info("checking config ${project.path}/$config for dependencies")
config
.dependencies
.filterIsInstance<ProjectDependency>()
.forEach {
logger?.info(
"there is a dependency from ${project.projectPath} to " +
it.path,
)
result.getOrPut(ProjectPath(it.path)) { mutableSetOf() }
.add(project.projectPath)
}
}
}
result
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.dropbox.affectedmoduledetector

import com.dropbox.affectedmoduledetector.mocks.MockConfiguration
import com.google.common.truth.Truth.assertThat
import org.gradle.api.artifacts.Configuration
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
Expand All @@ -11,6 +13,7 @@ import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.io.File
import java.util.function.Predicate

@RunWith(JUnit4::class)
class AffectedModuleConfigurationTest {
Expand Down Expand Up @@ -376,4 +379,27 @@ class AffectedModuleConfigurationTest {
// THEN
assertFalse(actual)
}

@Test
fun `GIVEN AffectedModuleConfiguration WHEN configuration predicate is set THEN is configuration predicate`() {
// GIVEN
config.configurationPredicate = Predicate<Configuration> { false }

// WHEN
val actual = config.configurationPredicate.test(MockConfiguration())

// THEN
assertFalse(actual)
}

@Test
fun `GIVEN AffectedModuleConfiguration WHEN configuration predicate is not set THEN is default`() {
// GIVEN default configuration

// WHEN
val actual = config.configurationPredicate.test(MockConfiguration())

// THEN
assertTrue(actual)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.io.File
import java.util.function.Predicate

@RunWith(JUnit4::class)
class AffectedModuleDetectorImplTest {
Expand Down Expand Up @@ -238,6 +239,9 @@ class AffectedModuleDetectorImplTest {
it.baseDir = tmpDir.absolutePath
it.pathsAffectingAllModules = pathsAffectingAllModules
}
listOf(root, root2, root3).forEach { rootProject ->
rootProject.extensions.add(AffectedModuleConfiguration.name, affectedModuleConfiguration)
}
}

@Test
Expand Down Expand Up @@ -1773,6 +1777,59 @@ class AffectedModuleDetectorImplTest {
)
}

@Test
fun `GIVEN upward configuration reference from p2 to p6 WHEN no predicate is supplied THEN p2 is affected`() {
p2.configurations.create("p2-upward-p6") { config ->
config.dependencies.add(p2.dependencies.project(mapOf("path" to p6.path)))
}
val detector = AffectedModuleDetectorImpl(
projectGraph = rootProjectGraph,
dependencyTracker = rootDependencyTracker,
logger = logger.toLogger(),
ignoreUnknownProjects = false,
projectSubset = ProjectSubset.ALL_AFFECTED_PROJECTS,
modules = null,
changedFilesProvider = MockGitClient(
changedFiles = listOf(
convertToFilePath("d1/d3/d6", "foo.java")
),
tmpFolder = tmpFolder.root
).findChangedFiles(root),
gitRoot = tmpFolder.root,
config = affectedModuleConfiguration
)
Truth.assertThat(detector.shouldInclude(p2.projectPath)).isTrue()
Truth.assertThat(detector.shouldInclude(p6.projectPath)).isTrue()
}

@Test
fun `GIVEN upward configuration reference from p2 to p6 WHEN predicate filtered THEN p2 is unaffected`() {
p2.configurations.create("p2-upward-p6") { config ->
config.dependencies.add(p2.dependencies.project(mapOf("path" to p6.path)))
}
affectedModuleConfiguration.configurationPredicate = Predicate { configuration ->
!configuration.name.contains("-upward-")
}
val detector = AffectedModuleDetectorImpl(
projectGraph = rootProjectGraph,
dependencyTracker = rootDependencyTracker,
logger = logger.toLogger(),
ignoreUnknownProjects = false,
projectSubset = ProjectSubset.ALL_AFFECTED_PROJECTS,
modules = null,
changedFilesProvider = MockGitClient(
changedFiles = listOf(
convertToFilePath("d1/d3/d6", "foo.java")
),
tmpFolder = tmpFolder.root
).findChangedFiles(root),
gitRoot = tmpFolder.root,
config = affectedModuleConfiguration
)
Truth.assertThat(detector.shouldInclude(p2.projectPath)).isFalse()
Truth.assertThat(detector.shouldInclude(p6.projectPath)).isTrue()
}

// For both Linux/Windows
fun convertToFilePath(vararg list: String): String {
return list.toList().joinToString(File.separator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.lang.IllegalStateException

@RunWith(JUnit4::class)
class AffectedModuleDetectorPluginTest {
Expand Down
Loading