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

Side by Side Diff: appengine/findit/findit_api.py

Issue 2397603002: [Findit] Cloud Endpoints API to receive reports on flakes. (Closed)
Patch Set: 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 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 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 """This module is to provide Findit service APIs through Cloud Endpoints: 5 """This module is to provide Findit service APIs through Cloud Endpoints:
6 6
7 Current APIs include: 7 Current APIs include:
8 1. Analysis of compile/test failures in Chromium waterfalls. 8 1. Analysis of compile/test failures in Chromium waterfalls.
9 Analyzes failures and detects suspected CLs. 9 Analyzes failures and detects suspected CLs.
10 2. Analysis of flakes on Commit Queue.
10 """ 11 """
11 12
12 import json 13 import json
13 import logging 14 import logging
14 15
15 import endpoints 16 import endpoints
16 from google.appengine.api import taskqueue 17 from google.appengine.api import taskqueue
17 from protorpc import messages 18 from protorpc import messages
18 from protorpc import remote 19 from protorpc import remote
19 20
20 from common import appengine_util 21 from common import appengine_util
22 from common import auth_util
21 from common import constants 23 from common import constants
24 from common import time_util
22 from common.waterfall import failure_type 25 from common.waterfall import failure_type
26 from model.flake.flake_analysis_request import FlakeAnalysisRequest
23 from model.wf_analysis import WfAnalysis 27 from model.wf_analysis import WfAnalysis
24 from model.wf_swarming_task import WfSwarmingTask 28 from model.wf_swarming_task import WfSwarmingTask
25 from model.wf_try_job import WfTryJob 29 from model.wf_try_job import WfTryJob
26 from waterfall import buildbot 30 from waterfall import buildbot
27 from waterfall import waterfall_config 31 from waterfall import waterfall_config
32 from waterfall.flake import flake_analysis_service
28 33
29 34
30 # This is used by the underlying ProtoRpc when creating names for the ProtoRPC 35 # This is used by the underlying ProtoRpc when creating names for the ProtoRPC
31 # messages below. This package name will show up as a prefix to the message 36 # messages below. This package name will show up as a prefix to the message
32 # class names in the discovery doc and client libraries. 37 # class names in the discovery doc and client libraries.
33 package = 'FindIt' 38 package = 'FindIt'
34 39
35 40
36 # These subclasses of Message are basically definitions of Protocol RPC 41 # These subclasses of Message are basically definitions of Protocol RPC
37 # messages. https://cloud.google.com/appengine/docs/python/tools/protorpc/ 42 # messages. https://cloud.google.com/appengine/docs/python/tools/protorpc/
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 7, variant=messages.Variant.INT32) 78 7, variant=messages.Variant.INT32)
74 suspected_cls = messages.MessageField(_SuspectedCL, 8, repeated=True) 79 suspected_cls = messages.MessageField(_SuspectedCL, 8, repeated=True)
75 analysis_approach = messages.EnumField(_AnalysisApproach, 9) 80 analysis_approach = messages.EnumField(_AnalysisApproach, 9)
76 81
77 82
78 class _BuildFailureAnalysisResultCollection(messages.Message): 83 class _BuildFailureAnalysisResultCollection(messages.Message):
79 """Represents a response to the client, eg. builder_alerts.""" 84 """Represents a response to the client, eg. builder_alerts."""
80 results = messages.MessageField(_BuildFailureAnalysisResult, 1, repeated=True) 85 results = messages.MessageField(_BuildFailureAnalysisResult, 1, repeated=True)
81 86
82 87
88 class _BuildStep(messages.Message):
89 master_name = messages.StringField(1, required=True)
90 builder_name = messages.StringField(2, required=True)
91 build_number = messages.IntegerField(
92 3, variant=messages.Variant.INT32, required=True)
93 step_name = messages.StringField(4, required=True)
94
95
96 class _Flake(messages.Message):
97 name = messages.StringField(1, required=True)
98 is_step = messages.BooleanField(2, required=False, default=False)
99 bug_id = messages.IntegerField(
100 3, variant=messages.Variant.INT32, required=True)
101 build_steps = messages.MessageField(_BuildStep, 4, repeated=True)
102
103
104 class _Build(messages.Message):
105 master_name = messages.StringField(1, required=True)
106 builder_name = messages.StringField(2, required=True)
107 build_number = messages.IntegerField(
108 3, variant=messages.Variant.INT32, required=True)
109
110
111 class _FlakeAnalysis(messages.Message):
112 analysis_triggered = messages.BooleanField(1, required=True)
113
114
83 def _TriggerNewAnalysesOnDemand(builds): 115 def _TriggerNewAnalysesOnDemand(builds):
84 """Pushes a task to run on the backend to trigger new analyses on demand.""" 116 """Pushes a task to run on the backend to trigger new analyses on demand."""
85 target = appengine_util.GetTargetNameForModule(constants.WATERFALL_BACKEND) 117 target = appengine_util.GetTargetNameForModule(constants.WATERFALL_BACKEND)
86 payload = json.dumps({'builds': builds}) 118 payload = json.dumps({'builds': builds})
87 taskqueue.add( 119 taskqueue.add(
88 url=constants.WATERFALL_TRIGGER_ANALYSIS_URL, payload=payload, 120 url=constants.WATERFALL_TRIGGER_ANALYSIS_URL, payload=payload,
89 target=target, queue_name=constants.WATERFALL_SERIAL_QUEUE) 121 target=target, queue_name=constants.WATERFALL_SERIAL_QUEUE)
90 122
91 123
92 # Create a Cloud Endpoints API. 124 # Create a Cloud Endpoints API.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 logging.info('%d build failure(s), while %d are supported', 275 logging.info('%d build failure(s), while %d are supported',
244 len(request.builds), len(supported_builds)) 276 len(request.builds), len(supported_builds))
245 try: 277 try:
246 _TriggerNewAnalysesOnDemand(supported_builds) 278 _TriggerNewAnalysesOnDemand(supported_builds)
247 except Exception: # pragma: no cover. 279 except Exception: # pragma: no cover.
248 # If we fail to post a task to the task queue, we ignore and wait for next 280 # If we fail to post a task to the task queue, we ignore and wait for next
249 # request. 281 # request.
250 logging.exception('Failed to trigger new analyses on demand.') 282 logging.exception('Failed to trigger new analyses on demand.')
251 283
252 return _BuildFailureAnalysisResultCollection(results=results) 284 return _BuildFailureAnalysisResultCollection(results=results)
285
286 @endpoints.method(_Flake, _FlakeAnalysis, path='flake', name='flake')
287 def AnalyzeFlake(self, request):
288 """Analyze a flake on Commit Queue. Currently only supports flaky tests."""
289 user_email = auth_util.GetUserEmail()
290 is_admin = auth_util.IsCurrentUserAdmin()
291
292 def CreateFlakeAnalysisRequest(flake):
293 analysis_request = FlakeAnalysisRequest.Create(
294 flake.name, flake.is_step, flake.bug_id)
295 for step in flake.build_steps:
296 analysis_request.AddBuildStep(step.master_name, step.builder_name,
297 step.build_number, step.step_name,
298 time_util.GetUTCNow())
299 return analysis_request
300
301 logging.info('Flake: %s', CreateFlakeAnalysisRequest(request))
302 analysis_triggered = flake_analysis_service.ScheduleAnalysisForFlake(
303 CreateFlakeAnalysisRequest(request), user_email, is_admin)
304
305 if analysis_triggered is None:
306 raise endpoints.UnauthorizedException(
307 'No permission for a new analysis! User is %s' % user_email)
308
309 return _FlakeAnalysis(analysis_triggered=analysis_triggered)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698