diff --git a/mozci/console/commands/push.py b/mozci/console/commands/push.py index cb2f3c69..faf3b318 100644 --- a/mozci/console/commands/push.py +++ b/mozci/console/commands/push.py @@ -310,11 +310,6 @@ class ClassifyCommand(BasePushCommand): flag=False, default=3, ), - option( - "disable-build-regressions", - description="If set, skip the analysis of build tasks regressions.", - flag=True, - ), ] def handle(self) -> None: @@ -342,24 +337,6 @@ def handle(self) -> None: raise Exception("Provided --backfill-limit should be an int.") for push in self.pushes: - if self.option("disable-build-regressions"): - self.line("Skipping build regressions analysis") - else: - try: - tasks_to_retrigger = push.check_build_regressions() - if not tasks_to_retrigger: - self.line("No build task detected as potential regression") - else: - self.line( - f"Retriggering {len(tasks_to_retrigger)} build regression that may introduce a build bustage" - ) - for task in tasks_to_retrigger: - task.retrigger(push) - except Exception as e: - self.line( - f" Couldn't run build regressions analysis on push {push.push_uuid}: {e}." - ) - try: classification, regressions, to_retrigger_or_backfill = push.classify( **classify_parameters @@ -454,9 +431,7 @@ def _serialize_regressions(regressions): emails, matrix_room, push, previous, classification, regressions ) - def retrigger_failures( - self, push, groups, count, allowed_patterns, retrigger_limit - ): + def retrigger_failures(self, push, groups, allowed_patterns, retrigger_limit): groups_with_failures = {} for name, failing_tasks in groups.items(): filtered_failing_tasks = [ @@ -501,7 +476,6 @@ def backfill_and_retrigger_failures( self.retrigger_failures( push, to_retrigger_or_backfill.real_retrigger, - classify_parameters.get("consistent_failures_counts", (2, 3))[1], allowed_patterns, retrigger_limit, ) @@ -511,7 +485,15 @@ def backfill_and_retrigger_failures( self.retrigger_failures( push, to_retrigger_or_backfill.intermittent_retrigger, - classify_parameters.get("consistent_failures_counts", (2, 3))[0], + allowed_patterns, + retrigger_limit, + ) + + # Retrigger build failures + self.line("Retriggering failures that may introduce a build bustage") + self.retrigger_failures( + push, + to_retrigger_or_backfill.build_retrigger, allowed_patterns, retrigger_limit, ) diff --git a/mozci/push.py b/mozci/push.py index 3eb8bc70..455908b2 100644 --- a/mozci/push.py +++ b/mozci/push.py @@ -63,6 +63,7 @@ class ToRetriggerOrBackfill: # each item being a single group, with its failing tasks real_retrigger: Dict[str, List[TestTask]] intermittent_retrigger: Dict[str, List[TestTask]] + build_retrigger: Dict[str, List[Task]] backfill: Dict[str, List[TestTask]] @@ -1125,7 +1126,7 @@ def get_likely_regressions( if count == 0 ) - def check_build_regressions(self) -> list[Task]: + def get_build_regressions(self) -> list[Task]: logger.info(f"Fetched {len(self.tasks)} tasks for push {self.id}.") # Try to identify a potential regressions from the failed build @@ -1142,7 +1143,9 @@ def check_build_regressions(self) -> list[Task]: logger.info("No build regression detected.") return [] - new_regressions = sum(past_occurrences == 0 for _, past_occurrences in build_regressions) + new_regressions = sum( + past_occurrences == 0 for _, past_occurrences in build_regressions + ) logger.info( f"Detected {len(build_regressions)} build tasks that may contain a regression " f"({new_regressions} were never seen before)." @@ -1398,6 +1401,9 @@ def _map_failing_tasks(groups): ) failures_to_be_backfilled.reverse() + # Look for build tasks failure + build_regressions = self.get_build_regressions() + # Output real, intermittent and unknown groupfailures # along with their failing configurations + groupfailures to retrigger/backfill return Regressions( @@ -1409,6 +1415,7 @@ def _map_failing_tasks(groups): intermittent_retrigger=_map_failing_tasks( intermittent_failures_to_be_retriggered ), + build_retrigger=_map_failing_tasks(build_regressions), backfill=_map_failing_tasks(failures_to_be_backfilled), ) diff --git a/tests/test_push.py b/tests/test_push.py index cffcd228..9bf7e976 100644 --- a/tests/test_push.py +++ b/tests/test_push.py @@ -1137,6 +1137,7 @@ def mock_return(self, *args, **kwargs): real_retrigger={}, intermittent_retrigger={}, backfill={}, + build_retrigger={}, ) monkeypatch.setattr(Push, "classify_regressions", mock_return) @@ -1149,6 +1150,7 @@ def generate_mocks( get_test_selection_data_value, get_likely_regressions_value, get_possible_regressions_value, + get_build_regressions_value, confirmed_failure_value, cross_config_values, classifications, @@ -1177,6 +1179,13 @@ def mock_return_get_possible_regressions(*args, **kwargs): Push, "get_possible_regressions", mock_return_get_possible_regressions ) + def mock_return_get_build_regressions(*args, **kwargs): + return get_build_regressions_value + + monkeypatch.setattr( + Push, "get_build_regressions", mock_return_get_build_regressions + ) + push.group_summaries = {} for name in classifications.keys(): push.group_summaries[name] = GROUP_SUMMARIES_DEFAULT[name] @@ -1294,6 +1303,7 @@ def test_classify_almost_good_push( test_selection_data, set(), set(), + [], None, are_cross_config, classifications, @@ -1345,6 +1355,7 @@ def test_classify_good_push_only_intermittent_failures(monkeypatch): test_selection_data, likely_regressions, set(), + [], None, are_cross_config, classifications, @@ -1524,6 +1535,7 @@ def test_classify_almost_bad_push( test_selection_data, likely_regressions, set(), + [], None, are_cross_config, classifications, @@ -1581,6 +1593,7 @@ def test_classify_bad_push_some_real_failures(monkeypatch): test_selection_data, likely_regressions, set(), + [], None, are_cross_config, classifications, @@ -1782,6 +1795,7 @@ def test_classify_cases( }, {"group1"} if is_likely_regression else set(), {"group1"} if is_possible_regression else set(), + [], is_confirmed_failure, {"group1": is_cross_config}, {