From 60d9580a4ae6496b6e499b024a550527b0cf83db Mon Sep 17 00:00:00 2001 From: tinder-ravitejabonagiri Date: Mon, 12 May 2025 10:05:14 -0700 Subject: [PATCH 1/4] Pass parentBranch as optional param in AffectedModuleDetectorConfig --- README.md | 88 ++----------------- .../AffectedModuleConfiguration.kt | 2 + .../AffectedModuleDetector.kt | 3 +- .../affectedmoduledetector/GitClient.kt | 2 +- .../commitshaproviders/CommitShaProvider.kt | 3 +- .../commitshaproviders/ForkCommit.kt | 4 +- .../AffectedModuleConfigurationTest.kt | 16 ++++ .../commitshaproviders/ForkCommitTest.kt | 13 +++ 8 files changed, 43 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 5d245fd..8bae12d 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,9 @@ affectedModuleDetector { buildAllWhenNoProjectsChanged = true // default is true includeUncommitted = true top = "HEAD" + specifiedBranch = "main" + specifiedRawCommitSha = "abc123" + parentBranch = "main" // Optional: specify parent branch for ForkCommit comparison customTasks = [ new AffectedModuleConfiguration.CustomTask( "runDetektByImpact", @@ -114,6 +117,7 @@ affectedModuleDetector { - `logFolder`: A folder to output the log file in - `specifiedBranch`: A branch to specify changes against. Must be used in combination with configuration `compareFrom = "SpecifiedBranchCommit"` - `specifiedRawCommitSha`: A raw commit SHA to specify changes against. Must be used in combination with configuration `compareFrom = "SpecifiedRawCommitSha"` + - `parentBranch`: A branch to specify as the parent branch for ForkCommit comparison. If not provided, ForkCommit will try to detect it automatically. - `ignoredFiles`: A set of files that will be filtered out of the list of changed files retrieved by git. - `buildAllWhenNoProjectsChanged`: If true, the plugin will build all projects when no projects are considered affected. - `compareFrom`: A commit to compare the branch changes against. Can be either: @@ -180,86 +184,4 @@ only executes the given task on a subset of projects. To run all the projects affected by a change, run one of the tasks while enabling the module detector. -``` -./gradlew runAffectedUnitTests -Paffected_module_detector.enable -``` - -#### Running All Changed Projects - -To run all the projects that changed, run one of the tasks (while enabling the module detector) and with `-Paffected_module_detector.changedProjects` - -``` -./gradlew runAffectedUnitTests -Paffected_module_detector.enable -Paffected_module_detector.changedProjects -``` - -#### Running All Dependent Projects - -To run all the dependent projects of projects that changed, run one of the tasks (while enabling the module detector) and with `-Paffected_module_detector.dependentProjects` - -``` -./gradlew runAffectedUnitTests -Paffected_module_detector.enable -Paffected_module_detector.dependentProjects -``` - -## Using the Sample project - -To run this on the sample app: - -1. Publish the plugin to local maven: -``` -./gradlew :affectedmoduledetector:publishToMavenLocal -``` - -2. Try running the following commands: -``` -cd sample - ./gradlew runAffectedUnitTests -Paffected_module_detector.enable -``` - -You should see zero tests run. Make a change within one of the modules and commit it. Rerunning the command should execute tests in that module and its dependent modules. - -## Custom tasks - -If you want to add a custom gradle command to execute with impact analysis -you must declare [AffectedModuleConfiguration.CustomTask](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt) -which is implementing the [AffectedModuleTaskType](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleTaskType.kt) interface in the `build.gradle` configuration of your project: - -```groovy -// ... - -affectedModuleDetector { - // ... - customTasks = [ - new AffectedModuleConfiguration.CustomTask( - "runDetektByImpact", - "detekt", - "Run static analysis tool without auto-correction by Impact analysis" - ) - ] - // ... -} -``` - -**NOTE:** Please, test all your custom commands. -If your custom task doesn't work correctly after testing, it might be that your task is quite complex -and to work correctly it must use more gradle api's. -Hence, you must create `buildSrc` module and write a custom plugin manually like [AffectedModuleDetectorPlugin](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetectorPlugin.kt) - -## Notes - -Special thanks to the AndroidX team for originally developing this project at https://android.googlesource.com/platform/frameworks/support/+/androidx-main/buildSrc/src/main/kotlin/androidx/build/dependencyTracker - -## License - - Copyright (c) 2021 Dropbox, Inc. - - 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 - - http://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. +``` \ No newline at end of file diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt index 7150166..9496830 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt @@ -84,6 +84,8 @@ class AffectedModuleConfiguration : Serializable { var specifiedRawCommitSha: String? = null + var parentBranch: String? = null + var compareFrom: String = "PreviousCommit" set(value) { val commitShaProviders = listOf( diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt index c00ca92..bc681f8 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetector.kt @@ -207,7 +207,8 @@ abstract class AffectedModuleDetector(protected val logger: Logger?) { specifiedBranch = config.specifiedBranch, specifiedSha = config.specifiedRawCommitSha, top = config.top, - includeUncommitted = config.includeUncommitted + includeUncommitted = config.includeUncommitted, + parentBranch = config.parentBranch ), ignoredFiles = config.ignoredFiles ) diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/GitClient.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/GitClient.kt index 5b3e836..c549bbf 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/GitClient.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/GitClient.kt @@ -232,7 +232,7 @@ internal abstract class GitChangedFilesSource : val specifiedSha = parameters.commitShaProvider.specifiedSha val type = when (parameters.commitShaProvider.type) { "PreviousCommit" -> PreviousCommit() - "ForkCommit" -> ForkCommit() + "ForkCommit" -> ForkCommit(parameters.commitShaProvider.parentBranch) "SpecifiedBranchCommit" -> { requireNotNull(specifiedBranch) { "Specified branch must be defined" diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/CommitShaProvider.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/CommitShaProvider.kt index 99e0ff9..242a762 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/CommitShaProvider.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/CommitShaProvider.kt @@ -13,5 +13,6 @@ data class CommitShaProviderConfiguration( val specifiedBranch: String? = null, val specifiedSha: String? = null, val top: Sha, - val includeUncommitted: Boolean + val includeUncommitted: Boolean, + val parentBranch: String? = null ) : Serializable diff --git a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommit.kt b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommit.kt index 8e632c0..89c805f 100644 --- a/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommit.kt +++ b/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommit.kt @@ -3,11 +3,11 @@ package com.dropbox.affectedmoduledetector.commitshaproviders import com.dropbox.affectedmoduledetector.GitClient import com.dropbox.affectedmoduledetector.Sha -class ForkCommit : CommitShaProvider { +class ForkCommit(private val providedParentBranch: String? = null) : CommitShaProvider { override fun get(commandRunner: GitClient.CommandRunner): Sha { val currentBranch = commandRunner.executeAndParseFirst(CURRENT_BRANCH_CMD) - val parentBranch = commandRunner.executeAndParse(SHOW_ALL_BRANCHES_CMD) + val parentBranch = providedParentBranch ?: commandRunner.executeAndParse(SHOW_ALL_BRANCHES_CMD) .firstOrNull { !it.contains(currentBranch) && it.contains("*") } ?.substringAfter("[") ?.substringBefore("]") diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt index ad006a7..a115f8f 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfigurationTest.kt @@ -376,4 +376,20 @@ class AffectedModuleConfigurationTest { // THEN assertFalse(actual) } + + @Test + fun `GIVEN AffectedModuleConfiguration WHEN parentBranch is set THEN value is returned`() { + val parentBranch = "main" + + config.parentBranch = parentBranch + + val actual = config.parentBranch + assertThat(actual).isEqualTo(parentBranch) + } + + @Test + fun `GIVEN AffectedModuleConfiguration WHEN parentBranch is not set THEN null is returned`() { + val actual = config.parentBranch + assertThat(actual).isNull() + } } diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt index cd4ab38..f1cfff3 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt @@ -75,4 +75,17 @@ class ForkCommitTest { assertThat(actual).isEqualTo("commit-sha") } + + @Test + fun givenProvidedParentBranch_whenGetCommitSha_thenUseProvidedBranch() { + val providedParentBranch = "main" + val forkCommitWithParent = ForkCommit(providedParentBranch) + + commandRunner.addReply(ForkCommit.CURRENT_BRANCH_CMD, "feature") + commandRunner.addReply("git merge-base feature main", "commit-sha") + + val actual = forkCommitWithParent.get(commandRunner) + + assertThat(actual).isEqualTo("commit-sha") + } } From 4924d6f3a74451501a9c78c3554fc2557d822b7e Mon Sep 17 00:00:00 2001 From: tinder-ravitejabonagiri Date: Mon, 12 May 2025 10:26:30 -0700 Subject: [PATCH 2/4] Fix unit tests --- .../commitshaproviders/ForkCommitTest.kt | 10 +++++----- .../affectedmoduledetector/mocks/MockCommandRunner.kt | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt index f1cfff3..865f3c2 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/commitshaproviders/ForkCommitTest.kt @@ -77,15 +77,15 @@ class ForkCommitTest { } @Test - fun givenProvidedParentBranch_whenGetCommitSha_thenUseProvidedBranch() { - val providedParentBranch = "main" + fun givenProvidedParentBranch_whenGetCommitSha_thenVerifyExactCommand() { + val providedParentBranch = "abc" val forkCommitWithParent = ForkCommit(providedParentBranch) commandRunner.addReply(ForkCommit.CURRENT_BRANCH_CMD, "feature") - commandRunner.addReply("git merge-base feature main", "commit-sha") + commandRunner.addReply("git merge-base feature abc", "commit-sha") - val actual = forkCommitWithParent.get(commandRunner) + forkCommitWithParent.get(commandRunner) - assertThat(actual).isEqualTo("commit-sha") + assertThat(commandRunner.executedCommands).contains("git merge-base feature abc") } } diff --git a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt index 49d5f41..c8dcfe5 100644 --- a/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt +++ b/affectedmoduledetector/src/test/kotlin/com/dropbox/affectedmoduledetector/mocks/MockCommandRunner.kt @@ -5,6 +5,8 @@ import com.dropbox.affectedmoduledetector.GitClient internal class MockCommandRunner(private val logger: FileLogger) : GitClient.CommandRunner { private val replies = mutableMapOf>() + private val _executedCommands = mutableListOf() + val executedCommands: List get() = _executedCommands fun addReply(command: String, response: String) { logger.info("add reply. cmd: $command response: $response") @@ -12,6 +14,7 @@ internal class MockCommandRunner(private val logger: FileLogger) : GitClient.Com } override fun execute(command: String): String { + _executedCommands.add(command) return replies.getOrDefault(command, emptyList()) .joinToString(System.lineSeparator()).also { logger.info("cmd: $command response: $it") @@ -19,12 +22,14 @@ internal class MockCommandRunner(private val logger: FileLogger) : GitClient.Com } override fun executeAndParse(command: String): List { + _executedCommands.add(command) return replies.getOrDefault(command, emptyList()).also { logger.info("cmd: $command response: $it") } } override fun executeAndParseFirst(command: String): String { + _executedCommands.add(command) return replies.getOrDefault(command, emptyList()).first().also { logger.info("cmd: $command response: $it") } From 8e0538c726c69be782f53a194aa95ec931cb688c Mon Sep 17 00:00:00 2001 From: tinder-ravitejabonagiri Date: Mon, 12 May 2025 10:27:48 -0700 Subject: [PATCH 3/4] Fix README --- README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bae12d..52d99ab 100644 --- a/README.md +++ b/README.md @@ -184,4 +184,85 @@ only executes the given task on a subset of projects. To run all the projects affected by a change, run one of the tasks while enabling the module detector. -``` \ No newline at end of file +``` +./gradlew runAffectedUnitTests -Paffected_module_detector.enable +``` + +#### Running All Changed Projects + +To run all the projects that changed, run one of the tasks (while enabling the module detector) and with `-Paffected_module_detector.changedProjects` + +``` +./gradlew runAffectedUnitTests -Paffected_module_detector.enable -Paffected_module_detector.changedProjects +``` + +#### Running All Dependent Projects + +To run all the dependent projects of projects that changed, run one of the tasks (while enabling the module detector) and with `-Paffected_module_detector.dependentProjects` + +``` +./gradlew runAffectedUnitTests -Paffected_module_detector.enable -Paffected_module_detector.dependentProjects +``` + +## Using the Sample project + +To run this on the sample app: + +1. Publish the plugin to local maven: +``` +./gradlew :affectedmoduledetector:publishToMavenLocal +``` + +2. Try running the following commands: +``` +cd sample + ./gradlew runAffectedUnitTests -Paffected_module_detector.enable +``` + +You should see zero tests run. Make a change within one of the modules and commit it. Rerunning the command should execute tests in that module and its dependent modules. + +## Custom tasks + +If you want to add a custom gradle command to execute with impact analysis +you must declare [AffectedModuleConfiguration.CustomTask](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleConfiguration.kt) +which is implementing the [AffectedModuleTaskType](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleTaskType.kt) interface in the `build.gradle` configuration of your project: + +```groovy +// ... +affectedModuleDetector { + // ... + customTasks = [ + new AffectedModuleConfiguration.CustomTask( + "runDetektByImpact", + "detekt", + "Run static analysis tool without auto-correction by Impact analysis" + ) + ] + // ... +} +``` + +**NOTE:** Please, test all your custom commands. +If your custom task doesn't work correctly after testing, it might be that your task is quite complex +and to work correctly it must use more gradle api's. +Hence, you must create `buildSrc` module and write a custom plugin manually like [AffectedModuleDetectorPlugin](https://github.com/dropbox/AffectedModuleDetector/blob/main/affectedmoduledetector/src/main/kotlin/com/dropbox/affectedmoduledetector/AffectedModuleDetectorPlugin.kt) + +## Notes + +Special thanks to the AndroidX team for originally developing this project at https://android.googlesource.com/platform/frameworks/support/+/androidx-main/buildSrc/src/main/kotlin/androidx/build/dependencyTracker + +## License + + Copyright (c) 2021 Dropbox, Inc. + + 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 + + http://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. \ No newline at end of file From 07be63750fe6a05f5876e41900c2325bba9990ce Mon Sep 17 00:00:00 2001 From: tinder-ravitejabonagiri Date: Mon, 12 May 2025 10:28:28 -0700 Subject: [PATCH 4/4] Add new line in README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 52d99ab..0cf2a4e 100644 --- a/README.md +++ b/README.md @@ -265,4 +265,5 @@ Special thanks to the AndroidX team for originally developing this project at ht 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. \ No newline at end of file + limitations under the License. + \ No newline at end of file