diff --git a/contrib/buildbot/server.py b/contrib/buildbot/server.py --- a/contrib/buildbot/server.py +++ b/contrib/buildbot/server.py @@ -261,14 +261,24 @@ config = yaml.safe_load(phab.get_file_content_from_master( "contrib/teamcity/build-configurations.yml")) + # Get the list of changed files + changedFiles = phab.get_revision_changed_files( + revision_id=revision_id) + # Get a list of the builds that should run on diffs - builds = [ - k for k, - v in config.get( - 'builds', - {}).items() if v.get( - 'runOnDiff', - False)] + builds = [] + for build_name, v in config.get('builds', {}).items(): + diffRegex = v.get('runOnDiffRegex', None) + if v.get('runOnDiff', False) or diffRegex is not None: + if diffRegex: + # If the regex matches at least one changed file, add this + # build to the list. + for changedFile in changedFiles: + if re.match(diffRegex, changedFile): + builds.append(build_name) + break + else: + builds.append(build_name) if target_phid in create_server.db['diff_targets']: build_target = create_server.db['diff_targets'][target_phid] diff --git a/contrib/buildbot/test/test_endpoint_buildDiff.py b/contrib/buildbot/test/test_endpoint_buildDiff.py --- a/contrib/buildbot/test/test_endpoint_buildDiff.py +++ b/contrib/buildbot/test/test_endpoint_buildDiff.py @@ -32,29 +32,42 @@ def test_buildDiff(self): data = buildDiffRequestQuery() - def set_build_configuration(builds): + def set_build_configuration(buildConfig): + # add some build configs that we expect to always be skipped + mergedConfig = dict() + mergedConfig.update({ + "build-skip-1": { + "runOnDiff": False, + }, + "build-skip-2": {}, + }) + mergedConfig.update(buildConfig) + config = { - "builds": { - } + "builds": mergedConfig, } - for build in builds: - config["builds"][build.name] = { - "runOnDiff": True - } self.phab.get_file_content_from_master = mock.Mock() self.phab.get_file_content_from_master.return_value = json.dumps( config) - def call_buildDiff(builds): + def call_buildDiff(expectedBuilds): self.teamcity.session.send.side_effect = [ - test.mocks.teamcity.buildInfo(build_id=build.build_id, buildqueue=True) for build in builds + test.mocks.teamcity.buildInfo(build_id=build.build_id, buildqueue=True) for build in expectedBuilds ] + self.phab.differential.getcommitpaths = mock.Mock() + self.phab.differential.getcommitpaths.return_value = { + "0": "dir/subdir/file.h", + "1": "dir/subdir/file.cpp", + "2": "someotherdir/file2.txt", + } + response = self.app.post( '/buildDiff{}'.format(data), headers=self.headers) self.assertEqual(response.status_code, 200) + self.phab.differential.getcommitpaths.assert_called() self.phab.get_file_content_from_master.assert_called() expected_calls = [ @@ -83,7 +96,7 @@ }, }), })) - for build in builds + for build in expectedBuilds ] self.teamcity.session.send.assert_has_calls( expected_calls, any_order=True) @@ -91,19 +104,56 @@ # No diff to run builds = [] - set_build_configuration(builds) + set_build_configuration({}) call_buildDiff(builds) self.teamcity.session.send.assert_not_called() - # Single diff + # Single diff build builds.append(Build(1, BuildStatus.Queued, "build-1")) - set_build_configuration(builds) + set_build_configuration({ + "build-1": { + "runOnDiff": True, + }, + }) call_buildDiff(builds) + # With matching file regex + set_build_configuration({ + "build-1": { + "runOnDiffRegex": "dir/subdir/.*", + }, + }) + call_buildDiff(builds) + + # With non-matching file regex + set_build_configuration({ + "build-1": { + "runOnDiffRegex": "dir/nonmatching/.*", + }, + }) + call_buildDiff([]) + + # Some builds match the file regex + builds.append(Build(1, BuildStatus.Queued, "build-2")) + set_build_configuration({ + "build-1": { + "runOnDiffRegex": "dir/nonmatching/.*", + }, + "build-2": { + "runOnDiffRegex": "someotherdir/file2.txt", + }, + }) + call_buildDiff([builds[1]]) + # Lot of builds builds = [Build(i, BuildStatus.Queued, "build-{}".format(i)) for i in range(10)] - set_build_configuration(builds) + buildConfig = {} + for build in builds: + buildConfig[build.name] = { + "runOnDiff": True, + } + set_build_configuration(buildConfig) call_buildDiff(builds) diff --git a/contrib/teamcity/build-configurations.yml b/contrib/teamcity/build-configurations.yml --- a/contrib/teamcity/build-configurations.yml +++ b/contrib/teamcity/build-configurations.yml @@ -403,6 +403,7 @@ timeout: 1800 check-buildbot: + runOnDiffRegex: contrib/buildbot/ targets: - - check-buildbot timeout: 600