Exemplo n.º 1
0
def summarize_patch(codereview_hostname, issue, patch, now):
  attempts = [
    summarize_attempt(raw_attempt, now)
    for raw_attempt in get_raw_attempts(codereview_hostname, issue, patch)
  ]
  attempts.reverse()
  return {
    'success': any(attempt['success'] for attempt in attempts),
    'begin': maybe_min(attempt['begin'] for attempt in attempts),
    'end': maybe_max(attempt['end'] for attempt in attempts),
    'durations': {
      field: sum(attempt['durations'][field] for attempt in attempts)
      for field in blank_durations_summary()
    },
    'job_counts': {
      state: sum(len(attempt['jobs'][state]) for attempt in attempts)
      for state in JOB_STATE.itervalues()
    },
    'flaky_jobs': get_flaky_jobs(attempts),
    'attempt_count': len(attempts),
    'attempt_fail_count': sum(
        1
        for attempt in attempts
        if attempt['success'] == False),
    'attempts': attempts,
  }
Exemplo n.º 2
0
def blank_attempt_summary():  # pragma: no cover
    return {
        "success": None,
        "fail_reason": None,
        "begin": None,
        "end": None,
        "durations": blank_durations_summary(),
        "jobs": {state: [] for state in JOB_STATE.itervalues()},
    }
Exemplo n.º 3
0
def blank_attempt_summary():
  return {
    'success': None,
    'fail_reason': None,
    'begin': None,
    'end': None,
    'durations': blank_durations_summary(),
    'jobs': {state: [] for state in JOB_STATE.itervalues()},
  }
Exemplo n.º 4
0
 def summarize_jobs(self, attempt_ended, last_timestamp):
   summaries = {state: [] for state in JOB_STATE.itervalues()}
   for builds in self.jobs.itervalues():
     for jobs in builds.itervalues():
       for job in jobs.itervalues():
         if job['end'] == None:  # pragma: no cover
           if attempt_ended:
             job['end'] = last_timestamp
           job['duration'] = last_timestamp - job['begin']
         summaries[job['state']].append(job)
   for jobs in summaries.itervalues():
     jobs.sort(key=lambda x: x['begin'], reverse=True)
   return summaries
Exemplo n.º 5
0
 def summarize_jobs(self, attempt_ended, last_timestamp):
     summaries = {state: [] for state in JOB_STATE.itervalues()}
     for builds in self.jobs.itervalues():
         for jobs in builds.itervalues():
             for job in jobs.itervalues():
                 if job["end"] == None:
                     if attempt_ended:
                         job["end"] = last_timestamp
                     job["duration"] = last_timestamp - job["begin"]
                 summaries[job["state"]].append(job)
     for jobs in summaries.itervalues():
         jobs.sort(cmp=lambda x, y: cmp(y["begin"], x["begin"]))
     return summaries
Exemplo n.º 6
0
 def summarize_jobs(self, attempt_ended, last_timestamp):
     summaries = {state: [] for state in JOB_STATE.itervalues()}
     for builds in self.jobs.itervalues():
         for jobs in builds.itervalues():
             for job in jobs.itervalues():
                 if job['end'] == None:
                     if attempt_ended:
                         job['end'] = last_timestamp
                     job['duration'] = last_timestamp - job['begin']
                 summaries[job['state']].append(job)
     for jobs in summaries.itervalues():
         jobs.sort(cmp=lambda x, y: cmp(y['begin'], x['begin']))
     return summaries
Exemplo n.º 7
0
 def update_jobs(self, record):
   job_states = record.fields.get('jobs', {})
   for cq_job_state, jobs in job_states.iteritems():
     job_state = JOB_STATE.get(cq_job_state)
     if not job_state:  # pragma: no cover
       logging.warning('Unknown job state: %s', cq_job_state)
       continue
     for job_info in jobs:
       build_number = job_info.get('buildnumber')
       if not build_number:  # pragma: no cover
         # NOTE: this is outdated assumption. In LUCI world, many try builds
         # don't have buildnumber ever. It apperas this app assumes buildnumber
         # to exist, but since this is deprecated, this is a NOTE, not a FIXME.
         continue
       master = job_info.get('master')
       builder = job_info.get('builder')
       self.jobs.setdefault(master, {})
       self.jobs[master].setdefault(builder, {})
       job_info = job_info or {}
       timestamp = parse_rietveld_timestamp(
           job_info.get('created_ts') or job_info.get('timestamp'))
       # Ignore jobs from past attempts.
       if (not timestamp or  # pragma: no branch
           timestamp < self.cutoff_timestamp):
         continue
       job = self.jobs[master][builder].setdefault(build_number, {})
       if len(job) == 0:
         job.update(blank_job_summary())
         job.update({
           'begin': timestamp,
           'master': master,
           'builder': builder,
           'slave': job_info.get('slave'),
           'build_number': build_number,
         })
       if job_state != 'running':
         job['end'] = timestamp
         job['duration'] = timestamp - job['begin']
       job['state'] = job_state
       job['retry'] = any(
           same_builder(job, test_job) and
           job['build_number'] != test_job['build_number'] and
           test_job['begin'] < job['begin']
           for test_job in self.jobs[master][builder].itervalues())
       # The build URL is sometimes missing so ensure we set it
       # if it was not already set.
       job['url'] = job['url'] or job_info.get('url')
Exemplo n.º 8
0
 def update_jobs(self, record):
     job_states = record.fields.get("jobs", {})
     for cq_job_state, jobs in job_states.iteritems():
         job_state = JOB_STATE.get(cq_job_state)
         if not job_state:
             logging.warning("Unknown job state: %s", cq_job_state)
             continue
         for job_info in jobs:
             master = job_info.get("master")
             builder = job_info.get("builder")
             self.jobs.setdefault(master, {})
             self.jobs[master].setdefault(builder, {})
             job_info = job_info or {}
             timestamp = self.rietveld_timestamp(job_info.get("timestamp"))
             # Ignore jobs from past attempts.
             if not timestamp or timestamp < self.cutoff_timestamp:
                 continue
             build_number = job_info.get("buildnumber")
             if not build_number:
                 logging.warning("No build number for %s %s at %s." % (master, builder, timestamp))
                 continue
             job = self.jobs[master][builder].setdefault(build_number, {})
             if len(job) == 0:
                 job.update(blank_job_summary())
                 job.update(
                     {
                         "begin": timestamp,
                         "master": master,
                         "builder": builder,
                         "slave": job_info.get("slave"),
                         "build_number": build_number,
                     }
                 )
             if job_state != "running":
                 job["end"] = timestamp
                 job["duration"] = timestamp - job["begin"]
             job["state"] = job_state
             job["retry"] = any(
                 same_builder(job, test_job)
                 and job["build_number"] != test_job["build_number"]
                 and test_job["begin"] < job["begin"]
                 for test_job in self.jobs[master][builder].itervalues()
             )
             # The build URL is sometimes missing so ensure we set it
             # if it was not already set.
             job["url"] = job["url"] or job_info.get("url")
Exemplo n.º 9
0
 def update_jobs(self, record):
     job_states = record.fields.get('jobs', {})
     for cq_job_state, jobs in job_states.iteritems():
         job_state = JOB_STATE.get(cq_job_state)
         if not job_state:  # pragma: no cover
             logging.warning('Unknown job state: %s', cq_job_state)
             continue
         for job_info in jobs:
             build_number = job_info.get('buildnumber')
             if not build_number:  # pragma: no cover
                 # Early exit: CQ is now scheduling with buildbucket,
                 # which means first events won't have a buildnumber, just build_id.
                 continue
             master = job_info.get('master')
             builder = job_info.get('builder')
             self.jobs.setdefault(master, {})
             self.jobs[master].setdefault(builder, {})
             job_info = job_info or {}
             timestamp = parse_rietveld_timestamp(
                 job_info.get('created_ts') or job_info.get('timestamp'))
             # Ignore jobs from past attempts.
             if (not timestamp or  # pragma: no branch
                     timestamp < self.cutoff_timestamp):
                 continue
             job = self.jobs[master][builder].setdefault(build_number, {})
             if len(job) == 0:
                 job.update(blank_job_summary())
                 job.update({
                     'begin': timestamp,
                     'master': master,
                     'builder': builder,
                     'slave': job_info.get('slave'),
                     'build_number': build_number,
                 })
             if job_state != 'running':
                 job['end'] = timestamp
                 job['duration'] = timestamp - job['begin']
             job['state'] = job_state
             job['retry'] = any(
                 same_builder(job, test_job)
                 and job['build_number'] != test_job['build_number']
                 and test_job['begin'] < job['begin']
                 for test_job in self.jobs[master][builder].itervalues())
             # The build URL is sometimes missing so ensure we set it
             # if it was not already set.
             job['url'] = job['url'] or job_info.get('url')
Exemplo n.º 10
0
 def update_jobs(self, record):
     job_states = record.fields.get('jobs', {})
     for cq_job_state, jobs in job_states.iteritems():
         job_state = JOB_STATE.get(cq_job_state)
         if not job_state:
             logging.warning('Unknown job state: %s', cq_job_state)
             continue
         for job_info in jobs:
             master = job_info.get('master')
             builder = job_info.get('builder')
             self.jobs.setdefault(master, {})
             self.jobs[master].setdefault(builder, {})
             job_info = job_info or {}
             timestamp = self.rietveld_timestamp(job_info.get('timestamp'))
             # Ignore jobs from past attempts.
             if not timestamp or timestamp < self.cutoff_timestamp:
                 continue
             build_number = job_info.get('buildnumber')
             if not build_number:
                 logging.warning('No build number for %s %s at %s.' %
                                 (master, builder, timestamp))
                 continue
             job = self.jobs[master][builder].setdefault(build_number, {})
             if len(job) == 0:
                 job.update(blank_job_summary())
                 job.update({
                     'begin': timestamp,
                     'master': master,
                     'builder': builder,
                     'slave': job_info.get('slave'),
                     'build_number': build_number,
                 })
             if job_state != 'running':
                 job['end'] = timestamp
                 job['duration'] = timestamp - job['begin']
             job['state'] = job_state
             job['retry'] = any(
                 same_builder(job, test_job)
                 and job['build_number'] != test_job['build_number']
                 and test_job['begin'] < job['begin']
                 for test_job in self.jobs[master][builder].itervalues())
             # The build URL is sometimes missing so ensure we set it
             # if it was not already set.
             job['url'] = job['url'] or job_info.get('url')
Exemplo n.º 11
0
def summarize_patch(issue, patch, now):  # pragma: no cover
    attempts = [summarize_attempt(raw_attempt, now) for raw_attempt in get_raw_attempts(issue, patch)][::-1]
    return {
        "success": any(attempt["success"] for attempt in attempts),
        "begin": maybe_min(attempt["begin"] for attempt in attempts),
        "end": maybe_max(attempt["end"] for attempt in attempts),
        "durations": {
            field: sum(attempt["durations"][field] for attempt in attempts) for field in blank_durations_summary()
        },
        "job_counts": {
            state: sum(len(attempt["jobs"][state]) for attempt in attempts) for state in JOB_STATE.itervalues()
        },
        "flaky_jobs": get_flaky_jobs(attempts),
        "attempt_count": len(attempts),
        "attempt_fail_count": sum(1 for attempt in attempts if attempt["success"] == False),
        "attempts": attempts,
    }
Exemplo n.º 12
0
def record_to_events(record, attempt_number): # pragma: no cover
  """Given a single CQ record, creates a generator for Trace Viewer events.

  A single record in CQ can correspond to any number of events, depending on
  the action performed in the record. The conversion from each action to
  Trace Viewer event is listed below.

  patch_start: single 'B' event representing the start of the attempt.
  patch_ready_to_commit: single 'B' event representing start of commit attempt
  patch_committed: single 'E' event representing successful commit
  patch_failed: single 'E' event representing completed patch attempt
  patch_stop: single 'E' event representing the end of the attempt.
  verifier_trigger: multiple 'B' events, one for each builder triggered.
  verifier_jobs_update: multiple 'E' events, one for each builder success
    or failure.
  """
  action = record.fields.get('action')
  attempt_string = 'Attempt %d' % attempt_number
  timestamp = record.fields.get('timestamp')
  if action == 'verifier_trigger':
    masters = record.fields.get('trybots', {})
    for master in masters:
      for builder in masters[master]:
        yield TraceViewerEvent(builder, master, 'B', timestamp, attempt_string,
                               builder, 'cq_build_running')
  elif action == 'verifier_jobs_update':
    job_states = record.fields.get('jobs', {})
    # CQ splits jobs into lists based on their state.
    for cq_job_state, jobs in job_states.iteritems():
      # Jobs can be in many different states, JOB_STATE maps them to
      # 'running' or not.
      job_state = JOB_STATE.get(cq_job_state)

      if not job_state:
        continue
      elif job_state == 'running':
        for job_info in jobs:
          master = job_info['master']
          builder = job_info['builder']
          args = {'build_url': job_info.get('url')}
          yield MetaEvent(builder, master, args)
      else:
        for job_info in jobs:
          master = job_info['master']
          builder = job_info['builder']
          timestamp = rietveld_timestamp(job_info['timestamp'])
          cname = 'cq_build_' + job_state
          args = {
            'build_url': job_info.get('url'),
          }
          yield TraceViewerEvent(builder, master, 'E', timestamp, 
                                 attempt_string, builder, cname, args)
  elif action == 'patch_start':
    yield TraceViewerEvent(attempt_string, 'Patch Progress', 'B',
                           timestamp, attempt_string,
                           'Patch Progress', 'cq_build_attempt_running')
  elif action == 'patch_ready_to_commit':
    yield TraceViewerEvent('Patch Committing', 'Patch Progress', 'B',
                           timestamp, attempt_string,
                           'Patch Progress', 'cq_build_attempt_running')
  elif action == 'patch_committed':
    yield TraceViewerEvent('Patch Committing', 'Patch Progress', 'E',
                             timestamp, attempt_string,
                             'Patch Progress', 'cq_build_attempt_passed')
  elif action == 'patch_stop':
    cname = 'cq_build_attempt_'
    if 'successfully committed' in record.fields['message']:
      cname += 'passed'
    else:
      cname += 'failed'
    yield TraceViewerEvent(attempt_string, 'Patch Progress', 'E',
                           timestamp, attempt_string, 'Patch Progress',
                           cname, {'action': action})