Beispiel #1
0
  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)
Beispiel #2
0
  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)
Beispiel #3
0
 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)
Beispiel #4
0
 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
Beispiel #5
0
    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)
Beispiel #6
0
  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
Beispiel #7
0
 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())
Beispiel #8
0
 def testGetUserEmailFromCookie(self, mocked_users):
   self.assertEqual('email1', auth_util.GetUserEmail())
   mocked_users.assert_called_once_with()
Beispiel #9
0
    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}