def convert_db_to_json(build_db_data, gatekeeper_config, f):
  """Converts build_db to a format suitable for JSON encoding and writes it."""
  # Remove all but the last finished build.
  for builders in build_db_data.masters.values():
    for builder in builders:
      unfinished = [(k, v) for k, v in builders[builder].iteritems()
                    if not v.finished]

      finished = [(k, v) for k, v in builders[builder].iteritems()
                  if v.finished]

      builders[builder] = dict(unfinished)

      if finished:
        max_finished = max(finished, key=lambda x: x[0])
        builders[builder][max_finished[0]] = max_finished[1]

  build_db = gen_db(masters=build_db_data.masters, aux=build_db_data.aux)

  # Output the gatekeeper sections we're operating with, so a human reading the
  # file can debug issues. This is discarded by the parser in get_build_db.
  used_sections = set([])
  for masters in build_db_data.masters.values():
    for builder in masters.values():
      used_sections |= set(t for b in builder.values() for t in b.triggered)

  for master in gatekeeper_config.values():
    for section in master:
      section_hash = gatekeeper_ng_config.gatekeeper_section_hash(section)
      if section_hash in used_sections:
        build_db.sections[section_hash] = section

  json.dump(build_db.asJson(), f, cls=gatekeeper_ng_config.SetEncoder,
            sort_keys=True)
def check_builds(master_builds, master_jsons, gatekeeper_config):
    """Given a gatekeeper configuration, see which builds have failed."""
    succeeded_builds = []
    failed_builds = []

    # Sort by buildnumber, highest first.
    sorted_builds = sorted(master_builds, key=lambda x: x[3], reverse=True)
    successful_builder_steps = defaultdict(lambda: defaultdict(set))
    current_builds_successful = True

    for build_json, master_url, builder, buildnum in sorted_builds:
        gatekeeper_sections = gatekeeper_config.get(master_url, [])
        for gatekeeper_section in gatekeeper_sections:
            section_hash = gatekeeper_ng_config.gatekeeper_section_hash(
                gatekeeper_section)

            gatekeeper = get_builder_section(gatekeeper_section,
                                             build_json['builderName'])
            if not gatekeeper:
                succeeded_builds.append((master_url, builder, buildnum))
                continue

            steps = build_json['steps']
            excluded_steps = set(gatekeeper.get('excluded_steps', []))
            forgiving_optional = (
                set(gatekeeper.get('forgiving_optional', [])) - excluded_steps)
            closing_optional = ((set(gatekeeper.get('closing_optional', []))
                                 | forgiving_optional) - excluded_steps)
            tree_notify = set(gatekeeper.get('tree_notify', []))
            sheriff_classes = set(gatekeeper.get('sheriff_classes', []))
            status_template = gatekeeper.get(
                'status_template',
                gatekeeper_ng_config.DEFAULTS['status_template'])
            subject_template = gatekeeper.get(
                'subject_template',
                gatekeeper_ng_config.DEFAULTS['subject_template'])
            finished = [s for s in steps if s.get('isFinished')]
            close_tree = gatekeeper.get('close_tree', True)
            respect_build_status = gatekeeper.get('respect_build_status',
                                                  False)

            # We ignore EXCEPTION and RETRY here since those are usually
            # infrastructure-related instead of actual test errors.
            successful_steps = set(
                s['name'] for s in finished
                if s.get('results', [FAILURE])[0] != FAILURE)

            successful_builder_steps[master_url][builder].update(
                successful_steps)

            finished_steps = set(s['name'] for s in finished)

            if '*' in forgiving_optional:
                forgiving_optional = (finished_steps - excluded_steps)
            if '*' in closing_optional:
                closing_optional = (finished_steps - excluded_steps)

            failed_steps = finished_steps - successful_steps
            unsatisfied_steps = failed_steps & closing_optional

            # Build is not yet finished, don't penalize on unstarted/unfinished steps.
            if build_json.get('results', None) is None:
                unsatisfied_steps &= finished_steps

            # If the entire build failed.
            if (not unsatisfied_steps and 'results' in build_json
                    and build_json['results'] == FAILURE
                    and respect_build_status):
                unsatisfied_steps.add('[overall build status]')

            buildbot_url = master_jsons[master_url]['project']['buildbotURL']
            project_name = master_jsons[master_url]['project']['title']

            if unsatisfied_steps:
                failed_builds.append(({
                    'base_url': buildbot_url,
                    'build': build_json,
                    'close_tree': close_tree,
                    'forgiving_steps': forgiving_optional,
                    'project_name': project_name,
                    'sheriff_classes': sheriff_classes,
                    'subject_template': subject_template,
                    'status_template': status_template,
                    'tree_notify': tree_notify,
                    'unsatisfied': unsatisfied_steps,
                }, master_url, builder, buildnum, section_hash))
                # If there is a failing step that a newer builder hasn't succeeded on,
                # don't open the tree.
                still_failing_steps = (
                    unsatisfied_steps -
                    successful_builder_steps[master_url][builder])
                if still_failing_steps:
                    logging.debug('%s failed on %s, not yet resolved.',
                                  ','.join(still_failing_steps),
                                  generate_build_url(failed_builds[-1][0]))
                    current_builds_successful = False
            else:
                succeeded_builds.append((master_url, builder, buildnum))

    return (list(reversed(failed_builds)), list(reversed(succeeded_builds)),
            successful_builder_steps, current_builds_successful)
Beispiel #3
0
def check_builds(master_builds, master_jsons, gatekeeper_config):
  """Given a gatekeeper configuration, see which builds have failed."""
  failed_builds = []
  for build_json, master_url, builder, buildnum in master_builds:
    gatekeeper_sections = gatekeeper_config.get(master_url, [])
    for gatekeeper_section in gatekeeper_sections:
      section_hash = gatekeeper_ng_config.gatekeeper_section_hash(
          gatekeeper_section)

      if build_json['builderName'] in gatekeeper_section:
        gatekeeper = gatekeeper_section[build_json['builderName']]
      elif '*' in gatekeeper_section:
        gatekeeper = gatekeeper_section['*']
      else:
        continue

      # Check if the buildername is in the excluded builder list and disable if
      # so.
      if build_json['builderName'] in gatekeeper.get('excluded_builders', []):
        continue

      steps = build_json['steps']
      excluded_steps = set(gatekeeper.get('excluded_steps', []))
      forgiving = set(gatekeeper.get('forgiving_steps', [])) - excluded_steps
      forgiving_optional = (
          set(gatekeeper.get('forgiving_optional', [])) - excluded_steps)
      closing_steps = (
          set(gatekeeper.get('closing_steps', [])) | forgiving) - excluded_steps
      closing_optional = (
          (set(gatekeeper.get('closing_optional', [])) | forgiving_optional) -
          excluded_steps
      )
      tree_notify = set(gatekeeper.get('tree_notify', []))
      sheriff_classes = set(gatekeeper.get('sheriff_classes', []))
      subject_template = gatekeeper.get('subject_template',
                                        gatekeeper_ng_config.DEFAULTS[
                                            'subject_template'])
      finished = [s for s in steps if s.get('isFinished')]
      close_tree = gatekeeper.get('close_tree', True)
      respect_build_status = gatekeeper.get('respect_build_status', False)

      successful_steps = set(s['name'] for s in finished
                             if (s.get('results', [FAILURE])[0] == SUCCESS or
                                 s.get('results', [FAILURE])[0] == WARNINGS))

      finished_steps = set(s['name'] for s in finished)

      if '*' in forgiving_optional:
        forgiving_optional = (finished_steps - excluded_steps)
      if '*' in closing_optional:
        closing_optional = (finished_steps - excluded_steps)

      unsatisfied_steps = closing_steps - successful_steps
      failed_steps = finished_steps - successful_steps
      failed_optional_steps = failed_steps & closing_optional
      unsatisfied_steps |= failed_optional_steps

      # Build is not yet finished, don't penalize on unstarted/unfinished steps.
      if build_json.get('results', None) is None:
        unsatisfied_steps &= finished_steps

      # If the entire build failed.
      if (not unsatisfied_steps and 'results' in build_json and
          build_json['results'] != SUCCESS and respect_build_status):
        unsatisfied_steps.add('[overall build status]')

      buildbot_url = master_jsons[master_url]['project']['buildbotURL']
      project_name = master_jsons[master_url]['project']['title']

      if unsatisfied_steps:
        failed_builds.append(({'base_url': buildbot_url,
                               'build': build_json,
                               'close_tree': close_tree,
                               'forgiving_steps': (
                                   forgiving | forgiving_optional),
                               'project_name': project_name,
                               'sheriff_classes': sheriff_classes,
                               'subject_template': subject_template,
                               'tree_notify': tree_notify,
                               'unsatisfied': unsatisfied_steps,
                              },
                              master_url,
                              builder,
                              buildnum,
                              section_hash))

  return failed_builds
Beispiel #4
0
def check_builds(master_builds, master_jsons, gatekeeper_config):
    """Given a gatekeeper configuration, see which builds have failed."""
    failed_builds = []
    for build_json, master_url, builder, buildnum in master_builds:
        gatekeeper_sections = gatekeeper_config.get(master_url, [])
        for gatekeeper_section in gatekeeper_sections:
            section_hash = gatekeeper_ng_config.gatekeeper_section_hash(
                gatekeeper_section)

            if build_json['builderName'] in gatekeeper_section:
                gatekeeper = gatekeeper_section[build_json['builderName']]
            elif '*' in gatekeeper_section:
                gatekeeper = gatekeeper_section['*']
            else:
                continue

            # Check if the buildername is in the excluded builder list and disable if
            # so.
            if build_json['builderName'] in gatekeeper.get(
                    'excluded_builders', []):
                continue

            steps = build_json['steps']
            excluded_steps = set(gatekeeper.get('excluded_steps', []))
            forgiving = set(gatekeeper.get('forgiving_steps',
                                           [])) - excluded_steps
            forgiving_optional = (
                set(gatekeeper.get('forgiving_optional', [])) - excluded_steps)
            closing_steps = (set(gatekeeper.get('closing_steps', []))
                             | forgiving) - excluded_steps
            closing_optional = ((set(gatekeeper.get('closing_optional', []))
                                 | forgiving_optional) - excluded_steps)
            tree_notify = set(gatekeeper.get('tree_notify', []))
            sheriff_classes = set(gatekeeper.get('sheriff_classes', []))
            subject_template = gatekeeper.get(
                'subject_template',
                gatekeeper_ng_config.DEFAULTS['subject_template'])
            finished = [s for s in steps if s.get('isFinished')]
            close_tree = gatekeeper.get('close_tree', True)
            respect_build_status = gatekeeper.get('respect_build_status',
                                                  False)

            successful_steps = set(
                s['name'] for s in finished
                if (s.get('results', [FAILURE])[0] == SUCCESS
                    or s.get('results', [FAILURE])[0] == WARNINGS))

            finished_steps = set(s['name'] for s in finished)

            if '*' in forgiving_optional:
                forgiving_optional = (finished_steps - excluded_steps)
            if '*' in closing_optional:
                closing_optional = (finished_steps - excluded_steps)

            unsatisfied_steps = closing_steps - successful_steps
            failed_steps = finished_steps - successful_steps
            failed_optional_steps = failed_steps & closing_optional
            unsatisfied_steps |= failed_optional_steps

            # Build is not yet finished, don't penalize on unstarted/unfinished steps.
            if build_json.get('results', None) is None:
                unsatisfied_steps &= finished_steps

            # If the entire build failed.
            if (not unsatisfied_steps and 'results' in build_json
                    and build_json['results'] != SUCCESS
                    and respect_build_status):
                unsatisfied_steps.add('[overall build status]')

            buildbot_url = master_jsons[master_url]['project']['buildbotURL']
            project_name = master_jsons[master_url]['project']['title']

            if unsatisfied_steps:
                failed_builds.append(({
                    'base_url':
                    buildbot_url,
                    'build':
                    build_json,
                    'close_tree':
                    close_tree,
                    'forgiving_steps': (forgiving | forgiving_optional),
                    'project_name':
                    project_name,
                    'sheriff_classes':
                    sheriff_classes,
                    'subject_template':
                    subject_template,
                    'tree_notify':
                    tree_notify,
                    'unsatisfied':
                    unsatisfied_steps,
                }, master_url, builder, buildnum, section_hash))

    return failed_builds
def check_builds(master_builds, master_jsons, gatekeeper_config):
  """Given a gatekeeper configuration, see which builds have failed."""
  succeeded_builds = []
  failed_builds = []

  # Sort by buildnumber, highest first.
  sorted_builds = sorted(master_builds, key=lambda x: x[3], reverse=True)
  successful_builder_steps = defaultdict(lambda: defaultdict(set))
  current_builds_successful = True

  for build_json, master_url, builder, buildnum in sorted_builds:
    gatekeeper_sections = gatekeeper_config.get(master_url, [])
    for gatekeeper_section in gatekeeper_sections:
      section_hash = gatekeeper_ng_config.gatekeeper_section_hash(
          gatekeeper_section)

      gatekeeper = get_builder_section(
          gatekeeper_section, build_json['builderName'])
      if not gatekeeper:
        succeeded_builds.append((master_url, builder, buildnum))
        continue

      steps = build_json['steps']
      excluded_steps = set(gatekeeper.get('excluded_steps', []))
      forgiving = set(gatekeeper.get('forgiving_steps', [])) - excluded_steps
      forgiving_optional = (
          set(gatekeeper.get('forgiving_optional', [])) - excluded_steps)
      closing_steps = (
          set(gatekeeper.get('closing_steps', [])) | forgiving) - excluded_steps
      closing_optional = (
          (set(gatekeeper.get('closing_optional', [])) | forgiving_optional) -
          excluded_steps
      )
      tree_notify = set(gatekeeper.get('tree_notify', []))
      sheriff_classes = set(gatekeeper.get('sheriff_classes', []))
      status_template = gatekeeper.get(
          'status_template', gatekeeper_ng_config.DEFAULTS['status_template'])
      subject_template = gatekeeper.get(
          'subject_template', gatekeeper_ng_config.DEFAULTS[
             'subject_template'])
      finished = [s for s in steps if s.get('isFinished')]
      close_tree = gatekeeper.get('close_tree', True)
      respect_build_status = gatekeeper.get('respect_build_status', False)

      # We ignore EXCEPTION and RETRY here since those are usually
      # infrastructure-related instead of actual test errors.
      successful_steps = set(s['name'] for s in finished
                             if s.get('results', [FAILURE])[0] != FAILURE)

      successful_builder_steps[master_url][builder].update(successful_steps)

      finished_steps = set(s['name'] for s in finished)

      if '*' in forgiving_optional:
        forgiving_optional = (finished_steps - excluded_steps)
      if '*' in closing_optional:
        closing_optional = (finished_steps - excluded_steps)

      unsatisfied_steps = closing_steps - successful_steps
      failed_steps = finished_steps - successful_steps
      failed_optional_steps = failed_steps & closing_optional
      unsatisfied_steps |= failed_optional_steps

      # Build is not yet finished, don't penalize on unstarted/unfinished steps.
      if build_json.get('results', None) is None:
        unsatisfied_steps &= finished_steps

      # If the entire build failed.
      if (not unsatisfied_steps and 'results' in build_json and
          build_json['results'] == FAILURE and respect_build_status):
        unsatisfied_steps.add('[overall build status]')

      buildbot_url = master_jsons[master_url]['project']['buildbotURL']
      project_name = master_jsons[master_url]['project']['title']

      if unsatisfied_steps:
        failed_builds.append(({'base_url': buildbot_url,
                               'build': build_json,
                               'close_tree': close_tree,
                               'forgiving_steps': (
                                   forgiving | forgiving_optional),
                               'project_name': project_name,
                               'sheriff_classes': sheriff_classes,
                               'subject_template': subject_template,
                               'status_template': status_template,
                               'tree_notify': tree_notify,
                               'unsatisfied': unsatisfied_steps,
                              },
                              master_url,
                              builder,
                              buildnum,
                              section_hash))
        # If there is a failing step that a newer builder hasn't succeeded on,
        # don't open the tree.
        still_failing_steps = (
            unsatisfied_steps - successful_builder_steps[master_url][builder])
        if still_failing_steps and close_tree:
          logging.debug('%s failed on %s, not yet resolved.',
              ','.join(still_failing_steps),
              generate_build_url(failed_builds[-1][0]))
          current_builds_successful = False
      else:
        succeeded_builds.append((master_url, builder, buildnum))

  return (list(reversed(failed_builds)), list(reversed(succeeded_builds)),
      successful_builder_steps, current_builds_successful)