Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging | 5 import logging |
| 6 | 6 |
| 7 from common import appengine_util | 7 from common import appengine_util |
| 8 from common import constants | 8 from common import constants |
| 9 from common import time_util | 9 from common import time_util |
| 10 from model import analysis_status | 10 from model import analysis_status |
| 11 from model.flake.master_flake_analysis import MasterFlakeAnalysis | 11 from model.flake.master_flake_analysis import MasterFlakeAnalysis |
| 12 from waterfall import waterfall_config | 12 from waterfall import waterfall_config |
| 13 from waterfall.flake import triggering_sources | |
| 13 from waterfall.flake.recursive_flake_pipeline import RecursiveFlakePipeline | 14 from waterfall.flake.recursive_flake_pipeline import RecursiveFlakePipeline |
| 14 | 15 |
| 15 | 16 |
| 16 def _NeedANewAnalysis( | 17 def _NeedANewAnalysis( |
| 17 master_name, builder_name, build_number, step_name, test_name, | 18 master_name, builder_name, build_number, step_name, test_name, |
| 18 algorithm_parameters, allow_new_analysis=False, force=False): | 19 algorithm_parameters, allow_new_analysis=False, force=False, |
| 20 user_email='', triggering_source=triggering_sources.FINDIT): | |
| 19 """Checks status of analysis for the test and decides if a new one is needed. | 21 """Checks status of analysis for the test and decides if a new one is needed. |
| 20 | 22 |
| 21 A MasterFlakeAnalysis entity for the given parameters will be created if none | 23 A MasterFlakeAnalysis entity for the given parameters will be created if none |
| 22 exists. When a new analysis is needed, this function will create and | 24 exists. When a new analysis is needed, this function will create and |
| 23 save a MasterFlakeAnalysis entity to the datastore. | 25 save a MasterFlakeAnalysis entity to the datastore. |
| 24 | 26 |
| 25 Args: | 27 Args: |
| 26 master_name (str): The master name on Waterfall. | 28 master_name (str): The master name on Waterfall. |
| 27 builder_name (str): The builder name on Waterfall. | 29 builder_name (str): The builder name on Waterfall. |
| 28 build_number (int): The build number on Waterfall. | 30 build_number (int): The build number on Waterfall. |
| 29 step_name (str): The step in which the flaky test is found. | 31 step_name (str): The step in which the flaky test is found. |
| 30 test_name (str): The flaky test to be analyzed. | 32 test_name (str): The flaky test to be analyzed. |
| 31 allow_new_analysis (bool): Indicate whether a new analysis is allowed. | 33 allow_new_analysis (bool): Indicate whether a new analysis is allowed. |
| 32 force (bool): Indicate whether to force a rerun of current analysis. | 34 force (bool): Indicate whether to force a rerun of current analysis. |
| 35 user_email (str): The user triggering this analysis. | |
| 36 triggering_source (int): The source from which this analysis was triggered. | |
| 33 | 37 |
| 34 Returns: | 38 Returns: |
| 35 (need_new_analysis, analysis) | 39 (need_new_analysis, analysis) |
| 36 need_new_analysis (bool): True if an analysis is needed, otherwise False. | 40 need_new_analysis (bool): True if an analysis is needed, otherwise False. |
| 37 analysis (MasterFlakeAnalysis): The MasterFlakeAnalysis entity. | 41 analysis (MasterFlakeAnalysis): The MasterFlakeAnalysis entity. |
| 38 """ | 42 """ |
| 39 analysis = MasterFlakeAnalysis.GetVersion( | 43 analysis = MasterFlakeAnalysis.GetVersion( |
| 40 master_name, builder_name, build_number, step_name, test_name) | 44 master_name, builder_name, build_number, step_name, test_name) |
| 41 | 45 |
| 42 if not analysis: | 46 if not analysis: |
| 43 if not allow_new_analysis: | 47 if not allow_new_analysis: |
| 44 return False, None | 48 return False, None |
| 45 analysis = MasterFlakeAnalysis.Create( | 49 analysis = MasterFlakeAnalysis.Create( |
| 46 master_name, builder_name, build_number, step_name, test_name) | 50 master_name, builder_name, build_number, step_name, test_name) |
| 47 analysis.request_time = time_util.GetUTCNow() | 51 analysis.request_time = time_util.GetUTCNow() |
| 48 analysis.status = analysis_status.PENDING | 52 analysis.status = analysis_status.PENDING |
| 49 analysis.algorithm_parameters = algorithm_parameters | 53 analysis.algorithm_parameters = algorithm_parameters |
| 50 analysis.version = appengine_util.GetCurrentVersion() | 54 analysis.version = appengine_util.GetCurrentVersion() |
| 55 analysis.triggering_user_email = user_email | |
| 56 analysis.triggering_source = triggering_source | |
| 51 _, saved = analysis.Save() | 57 _, saved = analysis.Save() |
| 52 return saved, analysis | 58 return saved, analysis |
| 53 elif (analysis.status == analysis_status.PENDING or | 59 elif (analysis.status == analysis_status.PENDING or |
| 54 analysis.status == analysis_status.RUNNING): | 60 analysis.status == analysis_status.RUNNING): |
| 55 return False, analysis | 61 return False, analysis |
| 56 elif allow_new_analysis and force and analysis.status in ( | 62 elif allow_new_analysis and force and analysis.status in ( |
| 57 analysis_status.ERROR, analysis_status.COMPLETED): | 63 analysis_status.ERROR, analysis_status.COMPLETED): |
| 58 analysis.Reset() | 64 analysis.Reset() |
| 59 analysis.request_time = time_util.GetUTCNow() | 65 analysis.request_time = time_util.GetUTCNow() |
| 60 analysis.status = analysis_status.PENDING | 66 analysis.status = analysis_status.PENDING |
| 61 analysis.algorithm_parameters = algorithm_parameters | 67 analysis.algorithm_parameters = algorithm_parameters |
| 62 analysis.version = appengine_util.GetCurrentVersion() | 68 analysis.version = appengine_util.GetCurrentVersion() |
| 69 analysis.triggering_user_email = user_email | |
| 70 analysis.triggering_source = triggering_source | |
| 63 _, saved = analysis.Save() | 71 _, saved = analysis.Save() |
| 64 return saved, analysis | 72 return saved, analysis |
| 65 else: | 73 else: |
| 66 return False, analysis | 74 return False, analysis |
| 67 | 75 |
| 68 | 76 |
| 69 def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, step_name, | 77 def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, step_name, |
| 70 test_name, allow_new_analysis=False, force=False, | 78 test_name, allow_new_analysis=False, force=False, |
| 71 manually_triggered=False, | 79 user_email='', |
| 80 triggering_source=triggering_sources.FINDIT, | |
| 72 queue_name=constants.DEFAULT_QUEUE): | 81 queue_name=constants.DEFAULT_QUEUE): |
| 73 """Schedules an analysis if needed and returns the MasterFlakeAnalysis. | 82 """Schedules an analysis if needed and returns the MasterFlakeAnalysis. |
| 74 | 83 |
| 75 When the build failure was already analyzed and a new analysis is scheduled, | 84 When the build failure was already analyzed and a new analysis is scheduled, |
| 76 the returned WfAnalysis will still have the result of last completed analysis. | 85 the returned WfAnalysis will still have the result of last completed analysis. |
| 77 | 86 |
| 78 Args: | 87 Args: |
| 79 master_name (str): The master name of the failed test | 88 master_name (str): The master name of the failed test |
| 80 builder_name (str): The builder name of the failed test | 89 builder_name (str): The builder name of the failed test |
| 81 build_number (int): The build number of the failed test | 90 build_number (int): The build number of the failed test |
| 82 step_name (str): The name of the test suite | 91 step_name (str): The name of the test suite |
| 83 test_name (str): The single test we are checking | 92 test_name (str): The single test we are checking |
| 84 allow_new_analysis (bool): Indicate whether a new analysis is allowed. | 93 allow_new_analysis (bool): Indicate whether a new analysis is allowed. |
| 85 force (bool): Indicate whether to force a rerun of current analysis. | 94 force (bool): Indicate whether to force a rerun of current analysis. |
| 86 manually_triggered (bool): True if the analysis is from manual request, like | 95 user_email (str): The email of the user requesting the analysis. |
| 87 by a Chromium sheriff. | 96 triggering_source (int): From where this analysis was triggered, such as |
| 97 through Findit itself or through Findit API. | |
| 88 queue_name (str): The App Engine queue to run the analysis. | 98 queue_name (str): The App Engine queue to run the analysis. |
| 89 | 99 |
| 90 Returns: | 100 Returns: |
| 91 A MasterFlakeAnalysis instance. | 101 A MasterFlakeAnalysis instance. |
| 92 None if no analysis was scheduled and the user has no permission to. | 102 None if no analysis was scheduled and the user has no permission to. |
| 93 """ | 103 """ |
| 94 algorithm_parameters = waterfall_config.GetCheckFlakeSettings() | 104 algorithm_parameters = waterfall_config.GetCheckFlakeSettings() |
| 95 | 105 |
| 96 need_new_analysis, analysis = _NeedANewAnalysis( | 106 need_new_analysis, analysis = _NeedANewAnalysis( |
| 97 master_name, builder_name, build_number, step_name, test_name, | 107 master_name, builder_name, build_number, step_name, test_name, |
| 98 algorithm_parameters, allow_new_analysis, force) | 108 algorithm_parameters, allow_new_analysis, force, |
| 109 user_email, triggering_source) | |
| 99 | 110 |
| 100 if need_new_analysis: | 111 if need_new_analysis: |
| 101 # _NeedANewAnalysis just created master_flake_analysis. Use the latest | 112 # _NeedANewAnalysis just created master_flake_analysis. Use the latest |
| 102 # version number and pass that along to the other pipelines for updating | 113 # version number and pass that along to the other pipelines for updating |
| 103 # results and data. | 114 # results and data. |
| 104 logging.info( | 115 logging.info( |
| 105 'A new master flake analysis was successfully saved for %s/%s/%s/%s/%s ' | 116 'A new master flake analysis was successfully saved for %s/%s/%s/%s/%s ' |
| 106 'and will be captured in version %s', master_name, builder_name, | 117 'and will be captured in version %s', master_name, builder_name, |
| 107 build_number, step_name, test_name, analysis.version_number) | 118 build_number, step_name, test_name, analysis.version_number) |
| 108 | 119 |
| 109 max_build_numbers_to_look_back = algorithm_parameters.get( | 120 max_build_numbers_to_look_back = algorithm_parameters.get( |
| 110 'max_build_numbers_to_look_back') | 121 'max_build_numbers_to_look_back') |
| 111 flakiness_algorithm_results_dict = { | 122 flakiness_algorithm_results_dict = { |
| 112 'flakes_in_a_row': 0, | 123 'flakes_in_a_row': 0, |
| 113 'stable_in_a_row': 0, | 124 'stable_in_a_row': 0, |
| 114 'stabled_out': False, | 125 'stabled_out': False, |
| 115 'flaked_out': False, | 126 'flaked_out': False, |
| 116 'last_build_number': max( | 127 'last_build_number': max( |
| 117 0, build_number - max_build_numbers_to_look_back), | 128 0, build_number - max_build_numbers_to_look_back), |
| 118 'lower_boundary': None, | 129 'lower_boundary': None, |
| 119 'upper_boundary': None, | 130 'upper_boundary': None, |
| 120 'lower_boundary_result': None, | 131 'lower_boundary_result': None, |
| 121 'sequential_run_index': 0 | 132 'sequential_run_index': 0 |
| 122 } | 133 } |
| 123 | 134 |
| 135 manually_triggered = user_email.endswith('@google.com') | |
|
stgao
2016/10/13 06:14:38
Not sure if it is a good idea to add this logic de
lijeffrey
2016/10/14 23:45:21
Done. Changed it back to accept manually_triggered
| |
| 136 | |
| 124 pipeline_job = RecursiveFlakePipeline( | 137 pipeline_job = RecursiveFlakePipeline( |
| 125 master_name, builder_name, build_number, step_name, test_name, | 138 master_name, builder_name, build_number, step_name, test_name, |
| 126 analysis.version_number, master_build_number=build_number, | 139 analysis.version_number, master_build_number=build_number, |
| 127 flakiness_algorithm_results_dict=flakiness_algorithm_results_dict, | 140 flakiness_algorithm_results_dict=flakiness_algorithm_results_dict, |
| 128 manually_triggered=manually_triggered) | 141 manually_triggered=manually_triggered) |
| 129 pipeline_job.target = appengine_util.GetTargetNameForModule( | 142 pipeline_job.target = appengine_util.GetTargetNameForModule( |
| 130 constants.WATERFALL_BACKEND) | 143 constants.WATERFALL_BACKEND) |
| 131 pipeline_job.StartOffPSTPeakHours(queue_name=queue_name) | 144 pipeline_job.StartOffPSTPeakHours(queue_name=queue_name) |
| 132 | 145 |
| 133 return analysis | 146 return analysis |
| OLD | NEW |