Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: appengine/findit/waterfall/flake/flake_analysis_service.py

Issue 2396283002: [Findit] Hook up analysis for CQ flakes. (Closed)
Patch Set: Fix nit. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 6
6 def ScheduleAnalysisForFlake( 7 from common import constants
7 _request, _user_email, _is_admin): # pragma: no cover. 8 from model.flake.flake_analysis_request import FlakeAnalysisRequest
9 from waterfall.flake import initialize_flake_pipeline
10 from waterfall.flake import step_mapper
11
12
13 def _CheckFlakeSwarmedAndSupported(request):
14 """Checks if the flake is Swarmed and supported in any build step.
15
16 Args:
17 request (FlakeAnalysisRequest): The request to analyze a flake.
18
19 Returns:
20 (swarmed, supported, build_step)
21 swarmed(bool): True if any step is Swarmed.
22 supported(bool): True if any step is supported (Swarmed Gtest).
23 build_step(BuildStep): The representative step that is Swarmed Gtest.
24 """
25 build_step = None
26 swarmed = False
27 supported = False
28 for step in request.build_steps:
29 swarmed = swarmed or step.swarmed
30 supported = supported or step.supported
31 if step.supported:
32 build_step = step
33 break
34 return swarmed, supported, build_step
35
36
37 def _NeedNewAnalysis(request):
chanli 2016/10/07 21:40:37 Nit: This kind of name indicates a True/False retu
stgao 2016/10/07 23:07:06 Renamed to CheckForNewAnalyais. Hope it is better,
38 """Checks if a new analysis is needed for the requested flake.
39
40 Args:
41 request (FlakeAnalysisRequest): The request to analyze a flake.
42
43 Returns:
44 (version_number, build_step)
45 version_number(int): The version of the FlakeAnalysisRequest if a new
46 analysis is needed; otherwise 0.
lijeffrey 2016/10/07 20:45:07 nit: space before (. Same with build_step
stgao 2016/10/07 23:07:05 Done.
47 build_step(BuildStep): a BuildStep instance if a new analysis is needed;
48 otherwise None.
49 """
50 previous_request = FlakeAnalysisRequest.GetVersion(key=request.name)
51 if not previous_request or (previous_request.bug_id and request.bug_id and
52 previous_request.bug_id != request.bug_id):
53 # If no existing analysis or last analysis was for a different bug, randomly
54 # pick one configuration for a new analysis.
55 if previous_request:
56 # Make a copy to preserve the version number of previous analysis and
57 # prevent concurrent analyses of the same flake.
58 previous_request.CopyFrom(request)
59 request = previous_request
60
61 swarmed, supported, supported_build_step = _CheckFlakeSwarmedAndSupported(
62 request)
63 request.swarmed = swarmed
64 request.supported = supported
65
66 if supported_build_step and not request.is_step:
67 supported_build_step.analyzed = True # This step will be analyzed.
chanli 2016/10/07 21:40:37 Based on flake_analysis_request.py, analyzed 'Indi
stgao 2016/10/07 23:07:06 Good point. Renamed to "scheduled".
68 # For unsupported or step-level flakes, still save them for monitoring.
lijeffrey 2016/10/07 20:45:07 nit: add 1 empty line before the comment
stgao 2016/10/07 23:07:06 Done.
69 _, saved = request.Save(retry_on_conflict=False) # Create a new version.
70
71 if not saved or not supported_build_step or request.is_step:
72 # No new analysis if:
73 # 1. Another analysis was just triggered.
74 # 2. No representative step is Swarmed Gtest.
75 # 3. The flake is a step-level one.
76 return 0, None
77
78 return request.version_number, supported_build_step
79 else:
80 # If no bug is attached to the existing analysis or the new request, or both
81 # are attached to the same bug, start a new analysis with a different
82 # configuration. For a configuration that was analyzed 7 days ago, reset it
83 # to use the new reported step of the same configuration.
84 # TODO: move this setting to config.
85 seconds_n_days = 7 * 24 * 60 * 60 # 7 days.
86 candidate_supported_steps = []
87 need_updating = False
88 for step in request.build_steps:
lijeffrey 2016/10/07 20:45:07 is it possible to move this for loop to a separate
stgao 2016/10/07 23:07:06 I just moved the else branch to another function.
89 existing_step = None
90 for s in previous_request.build_steps:
91 if (step.master_name == s.master_name and
92 step.builder_name == s.builder_name):
93 existing_step = s
94 break
95
96 if existing_step:
97 # If last reported flake at the existing step was too long ago, drop it
98 # so that the new one is recorded.
99 time_diff = step.reported_time - existing_step.reported_time
100 if time_diff.total_seconds() > seconds_n_days:
101 previous_request.build_steps.remove(existing_step)
102 existing_step = None
103
104 if not existing_step:
105 need_updating = True
106 previous_request.build_steps.append(step)
107 if step.supported:
108 candidate_supported_steps.append(step)
109
110 if not candidate_supported_steps:
111 # Find some existing configuration that is not analyzed yet.
112 for s in previous_request.build_steps:
113 if not s.analyzed and s.supported:
114 candidate_supported_steps.append(s)
115
116 supported_build_step = None
117 if candidate_supported_steps:
118 supported_build_step = candidate_supported_steps[0]
119 previous_request.swarmed = (previous_request.swarmed or
120 supported_build_step.swarmed)
121 previous_request.supported = True
122 need_updating = True
123
124 if supported_build_step and not previous_request.is_step:
125 supported_build_step.analyzed = True # This will be analyzed.
126
127 if not previous_request.bug_id: # No bug was attached before.
128 previous_request.bug_id = request.bug_id
129 need_updating = True
130
131 if need_updating:
132 # TODO: update in a transaction.
133 previous_request.put()
134
135 if not supported_build_step or previous_request.is_step:
136 # No new analysis if:
137 # 1. All analyzed steps are fresh enough and cover all the steps in the
138 # request.
139 # 2. No representative step is Swarmed Gtest.
140 # 3. The flake is a step-level one.
141 return 0, None
142
143 return previous_request.version_number, supported_build_step
chanli 2016/10/07 21:40:37 Just to be clear: If there is not previous analysi
stgao 2016/10/07 23:07:06 Assume only one bug is files for the same flake. A
144
145
146 def ScheduleAnalysisForFlake(request, user_email, is_admin):
8 """Schedules an analysis on the flake in the given request if needed. 147 """Schedules an analysis on the flake in the given request if needed.
9 148
10 Args: 149 Args:
11 request (FlakeAnalysisRequest): The request to analyze a flake. 150 request (FlakeAnalysisRequest): The request to analyze a flake.
12 user_email (str): The email of the requester. 151 user_email (str): The email of the requester.
13 is_admin (bool): Whether the requester is an admin. 152 is_admin (bool): Whether the requester is an admin.
14 153
15 Returns: 154 Returns:
16 An instance of MasterFlakeAnalysis if an analysis was scheduled; otherwise 155 An instance of MasterFlakeAnalysis if an analysis was scheduled; otherwise
17 None if no analysis was scheduled before and the user has no permission to. 156 None if no analysis was scheduled before and the user has no permission to.
18 """ 157 """
19 # TODO (stgao): hook up with analysis. 158 assert len(request.build_steps) > 0, 'At least 1 build step is needed!'
159
160 # TODO (stgao): maybe move this to config.
161 whitelisted_accounts = [
chanli 2016/10/07 21:40:36 Move this to constant for now?
stgao 2016/10/07 23:07:06 Done.
162 'chromium-try-flakes@appspot.gserviceaccount.com',
lijeffrey 2016/10/07 21:22:47 does findit-for-me@appspot.gserviceaccount.com cou
stgao 2016/10/07 23:07:06 No. Admin means admin of the project.
163 ]
164
165 # Check whether the requester is authorized for access.
166 if not user_email or not (
lijeffrey 2016/10/07 20:45:07 nit: I think this should be a separate function _I
stgao 2016/10/07 23:07:06 Done.
167 user_email.endswith('@google.com') or
168 user_email in whitelisted_accounts or is_admin):
169 return None
170 request.user_emails = [user_email]
171
172 manually_triggered = user_email.endswith('@google.com')
173
174 for build_step in request.build_steps:
175 step_mapper.FindMatchingWaterfallStep(build_step)
176
177 version_number, build_step = _NeedNewAnalysis(request)
178 if version_number and build_step:
179 # A new analysis is needed.
180 logging.info('A new analysis is needed for: %s', build_step)
181 analysis = initialize_flake_pipeline.ScheduleAnalysisIfNeeded(
182 build_step.wf_master_name, build_step.wf_builder_name,
183 build_step.wf_build_number, build_step.wf_step_name,
184 request.name, allow_new_analysis=True,
185 manually_triggered=manually_triggered,
186 queue_name=constants.WATERFALL_ANALYSIS_QUEUE)
187 if analysis:
188 # TODO: put this in a transaction.
189 request = FlakeAnalysisRequest.GetVersion(
190 key=request.name, version=version_number)
191 request.analyses.append(analysis.key)
192 request.put()
193 logging.info('A new analysis was triggered successfully: %s',
194 analysis.key)
195 return True
chanli 2016/10/07 21:40:37 Shouldn't return an instance of MasterFlakeAnalysi
stgao 2016/10/07 23:07:06 Updated docstring.
196 else:
197 logging.info('But no new analysis was not triggered!')
198 else:
199 logging.info('No new analysis is needed: %s', request)
200
20 return False 201 return False
chanli 2016/10/07 21:40:37 Return None?
stgao 2016/10/07 23:07:06 Acknowledged.
OLDNEW
« no previous file with comments | « appengine/findit/model/flake/test/flake_analysis_request_test.py ('k') | appengine/findit/waterfall/flake/step_mapper.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698