def AnalyzeFlake(self, request): """Analyze a flake on Commit Queue. Currently only supports flaky tests.""" user_email = auth_util.GetUserEmail() is_admin = auth_util.IsCurrentUserAdmin() if not flake_analysis_service.IsAuthorizedUser(user_email, is_admin): raise endpoints.UnauthorizedException( 'No permission to run a new analysis! User is %s' % user_email) def CreateFlakeAnalysisRequest(flake): analysis_request = FlakeAnalysisRequest.Create( flake.name, flake.is_step, flake.bug_id) for step in flake.build_steps: analysis_request.AddBuildStep(step.master_name, step.builder_name, step.build_number, step.step_name, time_util.GetUTCNow()) return analysis_request flake_analysis_request = CreateFlakeAnalysisRequest(request) logging.info('Flake report: %s', flake_analysis_request) try: _AsyncProcessFlakeReport(flake_analysis_request, user_email, is_admin) queued = True except Exception: # Ignore the report when fail to queue it for async processing. queued = False logging.exception('Failed to queue flake report for async processing') return _FlakeAnalysis(queued=queued)
def _Handle(self, handler_func): try: if not self._HasPermission(): template = 'error.html' data = { 'error_message': ('Either not login or no permission. ' 'Please login with your google.com account.'), 'login_url': self.GetLoginUrl(), } return_code = 401 cache_expiry = None else: result = handler_func() or {} template = result.get('template', None) data = result.get('data', {}) return_code = result.get('return_code', 200) cache_expiry = result.get('cache_expiry', None) except Exception as e: logging.exception(e) template = 'error.html' data = { 'error_message': 'An internal error occurred.' } return_code = 500 cache_expiry = None user_email = auth_util.GetUserEmail() if user_email and self.INCLUDE_LOGIN_USER_EMAIL: data['user_email'] = user_email self._SendResponse(template, data, return_code, cache_expiry)
def VerifyToken(handler, *args, **kwargs): user_email = auth_util.GetUserEmail() xsrf_token = str(handler.request.get('xsrf_token')) valid, expired = ValidateAuthToken('site', xsrf_token, user_email, self._action_id) if (not user_email or not valid or expired): return handler.CreateError( 'Invalid XSRF token. Please log in or refresh the page first.', return_code=403) return handler_method(handler, *args, **kwargs)
def AddToken(handler, *args, **kwargs): result = handler_method(handler, *args, **kwargs) user_email = auth_util.GetUserEmail() if not user_email: return result xsrf_token = GenerateAuthToken('site', user_email, self._action_id) result = result or {} result['data'] = result.get('data', {}) result['data']['xsrf_token'] = xsrf_token return result
def HandlePost(self): """Triggers an analysis on demand and redirects to the result page.""" url = self.request.get('url').strip() is_admin = auth_util.IsCurrentUserAdmin() user_email = auth_util.GetUserEmail() if not acl.CanTriggerNewAnalysis(user_email, is_admin): # No permission to schedule a new analysis. return self.CreateRedirect('/waterfall/failure?redirect=1&url=%s' % url) build_info = buildbot.ParseBuildUrl(url) if not build_info: return BaseHandler.CreateError( 'Url "%s" is not pointing to a build.' % url, 404) master_name, builder_name, build_number = build_info analysis = None if not (waterfall_config.MasterIsSupported(master_name) or auth_util.IsCurrentUserAdmin()): # If the build failure was already analyzed, just show it to the user. analysis = WfAnalysis.Get(master_name, builder_name, build_number) if not analysis: return BaseHandler.CreateError( 'Master "%s" is not supported yet.' % master_name, 501) if not analysis: # Only allow admin to force a re-run and set the build_completed. force = is_admin and self.request.get('force') == '1' build = build_util.GetBuildInfo(master_name, builder_name, build_number) if not build: return BaseHandler.CreateError( 'Can\'t get information about build "%s/%s/%s".' % (master_name, builder_name, build_number), 501) if not build.completed and force: return BaseHandler.CreateError( 'Can\'t force a rerun for an incomplete build "%s/%s/%s".' % (master_name, builder_name, build_number), 501) build_failure_analysis_pipelines.ScheduleAnalysisIfNeeded( master_name, builder_name, build_number, build_completed=build.completed, force=force, queue_name=constants.WATERFALL_ANALYSIS_QUEUE) return self.CreateRedirect('/waterfall/failure?redirect=1&url=%s' % url)
def _CreateAndScheduleFlakeAnalysis(request, master_name, builder_name, build_number, step_name, test_name, bug_id, rerun=False): # pylint: disable=unused-argument """Create and schedule a flake analysis. Args: request (FlakeAnalysisRequest): The requested step to analyze, containing all original fields used to create the request, such as the master, builder, etc. on which the the flaky test was originally detected. master_name (string): The name of the master with which to reference the analysis with. builder_name (string): The name of the builder with which to reference the analysis with. build_number (int): The build number with which to reference the analysis with. step_name (string): The name of the step with which to reference the analysis with. test_name (string): The name of the test with which to reference the analysis with. bug_id (int): The bug id. rerun (boolean): Is this analysis a rerun. Returns: (analysis, scheduled) analysis is the new analysis created. scheduled is returned from flake analysis service. """ user_email = auth_util.GetUserEmail() is_admin = auth_util.IsCurrentUserAdmin() scheduled = flake_analysis_service.ScheduleAnalysisForFlake( request, user_email, is_admin, triggering_sources.FINDIT_UI, rerun=rerun) analysis = MasterFlakeAnalysis.GetVersion( master_name, builder_name, build_number, step_name, test_name) return analysis, scheduled
def IsCorpUserOrAdmin(self): """Returns True if the user logged in with corp account or as admin.""" user_email = auth_util.GetUserEmail() return ((user_email and user_email.endswith('@google.com')) or auth_util.IsCurrentUserAdmin())
def testGetUserEmailFromCookie(self, mocked_users): self.assertEqual('email1', auth_util.GetUserEmail()) mocked_users.assert_called_once_with()
def HandleGet(self): key = self.request.get('key') if key: analysis = ndb.Key(urlsafe=key).get() if not analysis: # pragma: no cover return self.CreateError('Analysis of flake is not found', 404) else: build_url = self.request.get('url', '').strip() build_info = buildbot.ParseBuildUrl(build_url) if not build_info: # pragma: no cover return self.CreateError('Unknown build info!', 400) master_name, builder_name, build_number = build_info step_name = self.request.get('step_name', '').strip() test_name = self.request.get('test_name', '').strip() bug_id = self.request.get('bug_id', '').strip() # TODO(lijeffrey): Add support for force flag to trigger a rerun. error = self._ValidateInput(step_name, test_name, bug_id) if error: # pragma: no cover return error build_number = int(build_number) bug_id = int(bug_id) if bug_id else None user_email = auth_util.GetUserEmail() is_admin = auth_util.IsCurrentUserAdmin() request = FlakeAnalysisRequest.Create(test_name, False, bug_id) request.AddBuildStep(master_name, builder_name, build_number, step_name, time_util.GetUTCNow()) scheduled = flake_analysis_service.ScheduleAnalysisForFlake( request, user_email, is_admin, triggering_sources.FINDIT_UI) analysis = MasterFlakeAnalysis.GetVersion(master_name, builder_name, build_number, step_name, test_name) if not analysis: if scheduled is None: # User does not have permission to trigger, nor was any previous # analysis triggered to view. return { 'template': 'error.html', 'data': { 'error_message': ('You could schedule an analysis for flaky test only ' 'after you login with google.com account.'), 'login_url': self.GetLoginUrl(), }, 'return_code': 401, } # Check if a previous request has already covered this analysis so use # the results from that analysis. request = FlakeAnalysisRequest.GetVersion(key=test_name) if not (request and request.analyses): return { 'template': 'error.html', 'data': { 'error_message': ('Flake analysis is not supported for this request. Either' ' the build step may not be supported or the test is not ' 'swarmed.'), }, 'return_code': 400, } analysis = request.FindMatchingAnalysisForConfiguration( master_name, builder_name) if not analysis: # pragma: no cover logging.error('Flake analysis was deleted unexpectedly!') return { 'template': 'error.html', 'data': { 'error_message': 'Flake analysis was deleted unexpectedly!', }, 'return_code': 400 } suspected_flake = _GetSuspectedFlakeInfo(analysis) culprit = _GetCulpritInfo(analysis) build_level_number, revision_level_number = _GetNumbersOfDataPointGroups( analysis.data_points) data = { 'key': analysis.key.urlsafe(), 'master_name': analysis.master_name, 'builder_name': analysis.builder_name, 'build_number': analysis.build_number, 'step_name': analysis.step_name, 'test_name': analysis.test_name, 'pass_rates': [], 'analysis_status': analysis.status_description, 'try_job_status': analysis_status.STATUS_TO_DESCRIPTION.get(analysis.try_job_status), 'last_attempted_swarming_task': _GetLastAttemptedSwarmingTaskDetails(analysis), 'last_attempted_try_job': _GetLastAttemptedTryJobDetails(analysis), 'version_number': analysis.version_number, 'suspected_flake': suspected_flake, 'culprit': culprit, 'request_time': time_util.FormatDatetime(analysis.request_time), 'build_level_number': build_level_number, 'revision_level_number': revision_level_number, 'error': analysis.error_message, 'iterations_to_rerun': analysis.iterations_to_rerun, 'show_input_ui': self._ShowInputUI(analysis) } if (users.is_current_user_admin() and analysis.completed and analysis.triage_history): data['triage_history'] = analysis.GetTriageHistory() data['pending_time'] = time_util.FormatDuration( analysis.request_time, analysis.start_time or time_util.GetUTCNow()) if analysis.status != analysis_status.PENDING: data['duration'] = time_util.FormatDuration( analysis.start_time, analysis.end_time or time_util.GetUTCNow()) data['pass_rates'] = _GetCoordinatesData(analysis) return {'template': 'flake/result.html', 'data': data}