def build_finished_handler(build_id, **kwargs):
    build = Build.query.get(build_id)
    if build is None:
        return

    if build.tags and 'arc test' in build.tags:
        # 'arc test' builds have an associated Phabricator diff, but
        # aren't necessarily for the diff under review, so we don't
        # want to notify with them.
        return

    options = get_options(build.project_id)
    if options.get('phabricator.notify', '0') != '1':
        return

    target = build.target
    is_diff_build = target and target.startswith(u'D')
    is_commit_build = (build.source is not None and build.source.is_commit() and
                       build.tags and 'commit' in build.tags)

    phab = PhabricatorClient()

    if options.get('phabricator.coverage', '0') == '1' and (is_diff_build or is_commit_build):
        coverage = merged_coverage_data(get_coverage_by_build_id(build_id))
        if coverage:
            if is_diff_build:
                logger.info("Posting coverage to %s", target)
                post_diff_coverage(target[1:], coverage, phab)
            elif is_commit_build:
                # commits update diffs in phabricator, so post the coverage there too
                revision_id = parse_revision_id(build.message)
                if revision_id:
                    post_diff_coverage(revision_id, coverage, phab)

                callsign, branch, commit = commit_details(build.source)
                if callsign and commit:
                    logger.info("Posting coverage to %s, %s, %s", callsign, branch, commit)
                    post_commit_coverage(callsign, branch, commit, coverage, phab)

    if not is_diff_build:
        # Not a diff build
        return

    builds = list(
        Build.query.filter(Build.collection_id == build.collection_id))

    # Exit if there are no builds for the given build_id, or any build hasn't
    # finished.
    if not builds or any(map(lambda b: b.status != Status.finished, builds)):
        return

    # if comment has already been posted for this set of builds, don't do anything
    if _comment_posted_for_collection_of_build(build):
        return

    context = build_context_lib.get_collection_context(builds)

    message = '\n\n'.join([_get_message_for_build_context(x) for x in context['builds']])

    post_comment(target, message, phab)
Esempio n. 2
0
    def get(self, build_id):
        build = Build.query.get(build_id)
        if build is None:
            return '', 404

        args = self.parser.parse_args()

        results = get_coverage_by_build_id(build.id)

        if args.diff:
            diff = build.source.generate_diff()
            if not diff:
                return self.respond({})

            diff_parser = DiffParser(diff)
            lines_by_file = diff_parser.get_lines_by_file()

            results = [r for r in results if r.filename in lines_by_file]

            coverage_data = merged_coverage_data(results)

            coverage_stats = {}
            for filename in lines_by_file:
                if filename in coverage_data and filename in lines_by_file:
                    stats = get_coverage_stats(lines_by_file[filename], coverage_data[filename])
                    coverage_stats[filename] = {
                        'linesCovered': stats.lines_covered,
                        'linesUncovered': stats.lines_uncovered,
                        'diffLinesCovered': stats.diff_lines_covered,
                        'diffLinesUncovered': stats.diff_lines_uncovered,
                    }

        else:
            # NOTE: Without a diff, the stats may be off if there are
            # multiple job steps.  (Each job step can potentially
            # return a separate FileCoverage row for the same file.)
            # For each file, we return the best metrics using
            # min()/max(); if you want more correct metrics, pass
            # diff=1.
            coverage_stats = {}
            for r in results:
                if r.filename not in coverage_stats:
                    coverage_stats[r.filename] = {
                        'linesCovered': r.lines_covered,
                        'linesUncovered': r.lines_uncovered,
                        'diffLinesCovered': r.diff_lines_covered,
                        'diffLinesUncovered': r.diff_lines_uncovered,
                    }
                else:
                    # Combine metrics using max() for [diff] lines
                    # covered, min() for [diff] lines uncovered.
                    stats = coverage_stats[r.filename]
                    coverage_stats[r.filename] = {
                        'linesCovered': max(stats['linesCovered'], r.lines_covered),
                        'linesUncovered': min(stats['linesUncovered'], r.lines_uncovered),
                        'diffLinesCovered': max(stats['diffLinesCovered'], r.diff_lines_covered),
                        'diffLinesUncovered': min(stats['diffLinesUncovered'], r.diff_lines_uncovered),
                    }

        return self.respond(coverage_stats)
    def get(self, source_id):
        source = Source.query.filter(
            Source.id == source_id,
        ).first()
        if source is None:
            return error("Source not found", http_code=404)

        args = self.get_parser.parse_args()

        context = self.serialize(source)

        diff = source.generate_diff()

        if diff:
            files = self._get_files_from_raw_diff(diff)

            if args.coverage:
                coverage = merged_coverage_data(c for c in get_coverage_by_source_id(source_id)
                                                if c.filename in files)

                coverage_for_added_lines = self._filter_coverage_for_added_lines(diff, coverage)

            tails_info = dict(source.data)
        else:
            coverage = None
            coverage_for_added_lines = None
            tails_info = None

        context['diff'] = diff
        if args.coverage:
            context['coverage'] = coverage
            context['coverageForAddedLines'] = coverage_for_added_lines
        context['tailsInfo'] = tails_info

        return self.respond(context)
Esempio n. 4
0
    def get(self, build_id):
        build = Build.query.get(build_id)
        if build is None:
            return '', 404

        coverage = merged_coverage_data(get_coverage_by_build_id(build.id))

        return self.respond(coverage)
Esempio n. 5
0
    def get(self, project_id, source_id):
        project = Project.get(project_id)
        if not project:
            return '', 404

        repo = project.repository
        source = Source.query.filter(
            Source.id == source_id,
            Source.repository_id == repo.id,
        ).first()
        if source is None:
            return '', 404

        context = self.serialize(source)

        diff = source.generate_diff()

        if diff:
            files = self._get_files_from_raw_diff(diff)

            coverage = merged_coverage_data(
                c for c in get_coverage_by_source_id(source_id)
                if c.filename in files)

            coverage_for_added_lines = self._filter_coverage_for_added_lines(
                diff, coverage)

            tails_info = dict(source.data)
        else:
            coverage = None
            coverage_for_added_lines = None
            tails_info = None

        context['diff'] = diff
        context['coverage'] = coverage
        context['coverageForAddedLines'] = coverage_for_added_lines
        context['tailsInfo'] = tails_info

        return self.respond(context)
    def get(self, project_id, source_id):
        project = Project.get(project_id)
        if not project:
            return '', 404

        repo = project.repository
        source = Source.query.filter(
            Source.id == source_id,
            Source.repository_id == repo.id,
        ).first()
        if source is None:
            return '', 404

        context = self.serialize(source)

        diff = source.generate_diff()

        if diff:
            files = self._get_files_from_raw_diff(diff)

            coverage = merged_coverage_data(c for c in get_coverage_by_source_id(source_id)
                                            if c.filename in files)

            coverage_for_added_lines = self._filter_coverage_for_added_lines(diff, coverage)

            tails_info = dict(source.data)
        else:
            coverage = None
            coverage_for_added_lines = None
            tails_info = None

        context['diff'] = diff
        context['coverage'] = coverage
        context['coverageForAddedLines'] = coverage_for_added_lines
        context['tailsInfo'] = tails_info

        return self.respond(context)
Esempio n. 7
0
def build_finished_handler(build_id, **kwargs):
    build = Build.query.get(build_id)
    if build is None:
        return

    if build.tags and 'arc test' in build.tags:
        # 'arc test' builds have an associated Phabricator diff, but
        # aren't necessarily for the diff under review, so we don't
        # want to notify with them.
        return

    options = get_options(build.project_id)
    if options.get('phabricator.notify', '0') != '1':
        return

    target = build.target
    is_diff_build = target and target.startswith(u'D')
    is_commit_build = (build.source is not None and build.source.is_commit()
                       and build.tags and 'commit' in build.tags)

    phab = PhabricatorClient()

    if options.get('phabricator.coverage',
                   '0') == '1' and (is_diff_build or is_commit_build):
        coverage = merged_coverage_data(get_coverage_by_build_id(build_id))
        if coverage:
            if is_diff_build:
                logger.info("Posting coverage to %s", target)
                post_diff_coverage(target[1:], coverage, phab)
            elif is_commit_build:
                # commits update diffs in phabricator, so post the coverage there too
                revision_id = parse_revision_id(build.message)
                if revision_id:
                    post_diff_coverage(revision_id, coverage, phab)

                callsign, branch, commit = commit_details(build.source)
                if callsign and commit:
                    logger.info("Posting coverage to %s, %s, %s", callsign,
                                branch, commit)
                    post_commit_coverage(callsign, branch, commit, coverage,
                                         phab)

    if not is_diff_build:
        # Not a diff build
        return

    builds = list(
        Build.query.filter(Build.collection_id == build.collection_id))

    # Exit if there are no builds for the given build_id, or any build hasn't
    # finished.
    if not builds or any(map(lambda b: b.status != Status.finished, builds)):
        return

    # if comment has already been posted for this set of builds, don't do anything
    if _comment_posted_for_collection_of_build(build):
        return

    context = build_context_lib.get_collection_context(builds)

    message = '\n\n'.join(
        [_get_message_for_build_context(x) for x in context['builds']])

    post_comment(target, message, phab)
Esempio n. 8
0
    def get(self, build_id):
        build = Build.query.get(build_id)
        if build is None:
            return '', 404

        args = self.parser.parse_args()

        results = get_coverage_by_build_id(build.id)

        if args.diff:
            diff = build.source.generate_diff()
            if not diff:
                return self.respond({})

            diff_parser = DiffParser(diff)
            lines_by_file = diff_parser.get_lines_by_file()

            results = [r for r in results if r.filename in lines_by_file]

            coverage_data = merged_coverage_data(results)

            coverage_stats = {}
            for filename in lines_by_file:
                if filename in coverage_data and filename in lines_by_file:
                    stats = get_coverage_stats(lines_by_file[filename],
                                               coverage_data[filename])
                    coverage_stats[filename] = {
                        'linesCovered': stats.lines_covered,
                        'linesUncovered': stats.lines_uncovered,
                        'diffLinesCovered': stats.diff_lines_covered,
                        'diffLinesUncovered': stats.diff_lines_uncovered,
                    }

        else:
            # NOTE: Without a diff, the stats may be off if there are
            # multiple job steps.  (Each job step can potentially
            # return a separate FileCoverage row for the same file.)
            # For each file, we return the best metrics using
            # min()/max(); if you want more correct metrics, pass
            # diff=1.
            coverage_stats = {}
            for r in results:
                if r.filename not in coverage_stats:
                    coverage_stats[r.filename] = {
                        'linesCovered': r.lines_covered,
                        'linesUncovered': r.lines_uncovered,
                        'diffLinesCovered': r.diff_lines_covered,
                        'diffLinesUncovered': r.diff_lines_uncovered,
                    }
                else:
                    # Combine metrics using max() for [diff] lines
                    # covered, min() for [diff] lines uncovered.
                    stats = coverage_stats[r.filename]
                    coverage_stats[r.filename] = {
                        'linesCovered':
                        max(stats['linesCovered'], r.lines_covered),
                        'linesUncovered':
                        min(stats['linesUncovered'], r.lines_uncovered),
                        'diffLinesCovered':
                        max(stats['diffLinesCovered'], r.diff_lines_covered),
                        'diffLinesUncovered':
                        min(stats['diffLinesUncovered'],
                            r.diff_lines_uncovered),
                    }

        return self.respond(coverage_stats)
Esempio n. 9
0
def build_finished_handler(build_id, **kwargs):
    build = Build.query.get(build_id)
    if build is None:
        return

    if build_type.is_arc_test_build(build):
        # 'arc test' builds have an associated Phabricator diff, but
        # aren't necessarily for the diff under review, so we don't
        # want to notify with them.
        return

    options = get_options(build.project_id)
    if options.get('phabricator.notify', '0') != '1':
        return

    target = build.target
    is_diff_build = build_type.is_phabricator_diff_build(build)
    is_commit_build = build_type.is_initial_commit_build(build)

    phab = PhabricatorClient()

    if options.get('phabricator.coverage', '0') == '1' and (is_diff_build or is_commit_build):
        coverage = merged_coverage_data(get_coverage_by_build_id(build_id))
        if coverage:
            if is_diff_build:
                logger.info("Posting coverage to %s", target)
                post_diff_coverage(target[1:], coverage, phab)
            elif is_commit_build:
                # commits update diffs in phabricator, so post the coverage there too
                revision_id = parse_revision_id(build.message)
                if revision_id:
                    post_diff_coverage(revision_id, coverage, phab)

                callsign, branch, commit = commit_details(build.source)
                if callsign and commit:
                    logger.info("Posting coverage to %s, %s, %s", callsign, branch, commit)
                    post_commit_coverage(callsign, branch, commit, coverage, phab)

    if not is_diff_build:
        # Not a diff build
        return

    builds = list(
        Build.query.filter(Build.collection_id == build.collection_id))

    # Filter collection of builds down to only consider/report builds for
    # projects with phabricator.notify set.
    options = ProjectOptionsHelper.get_options([b.project for b in builds], ['phabricator.notify'])
    builds = [b for b in builds if options[b.project.id].get('phabricator.notify', '0') == '1']

    # Exit if there are no builds for the given build_id, or any build hasn't
    # finished.
    if not builds or any(map(lambda b: b.status != Status.finished, builds)):
        return

    # if comment has already been posted for this set of builds, don't do anything
    if _comment_posted_for_collection_of_build(build):
        return

    context = build_context_lib.get_collection_context(builds)

    good_builds = [b for b in context.builds if b['build'].result == Result.passed]
    bad_builds = [b for b in context.builds if b['build'].result != Result.passed]

    message = ""
    if bad_builds:
        message += '(IMPORTANT) Failing builds!\n\n'
        message += '\n'.join([_get_message_for_build_context(x) for x in bad_builds])
    if good_builds:
        if bad_builds:
            message += '\n\n'
        message += '(NOTE) Passing builds:\n\n'
        message += '\n'.join([_get_message_for_build_context(x) for x in good_builds])

    post_comment(target, message, phab)
Esempio n. 10
0
def build_finished_handler(build_id, **kwargs):
    build = Build.query.get(build_id)
    if build is None:
        return

    if build_type.is_arc_test_build(build):
        # 'arc test' builds have an associated Phabricator diff, but
        # aren't necessarily for the diff under review, so we don't
        # want to notify with them.
        return

    options = get_options(build.project_id)
    if options.get('phabricator.notify', '0') != '1':
        return

    target = build.target
    is_diff_build = build_type.is_phabricator_diff_build(build)
    is_commit_build = build_type.is_initial_commit_build(build)

    phab = PhabricatorClient()

    if options.get('phabricator.coverage',
                   '0') == '1' and (is_diff_build or is_commit_build):
        coverage = merged_coverage_data(get_coverage_by_build_id(build_id))
        if coverage:
            if is_diff_build:
                logger.info("Posting coverage to %s", target)
                post_diff_coverage(target[1:], coverage, phab)
            elif is_commit_build:
                # commits update diffs in phabricator, so post the coverage there too
                revision_id = parse_revision_id(build.message)
                if revision_id:
                    post_diff_coverage(revision_id, coverage, phab)

                callsign, branch, commit = commit_details(build.source)
                if callsign and commit:
                    logger.info("Posting coverage to %s, %s, %s", callsign,
                                branch, commit)
                    post_commit_coverage(callsign, branch, commit, coverage,
                                         phab)

    if not is_diff_build:
        # Not a diff build
        return

    builds = list(
        Build.query.filter(Build.collection_id == build.collection_id))

    # Filter collection of builds down to only consider/report builds for
    # projects with phabricator.notify set.
    options = ProjectOptionsHelper.get_options([b.project for b in builds],
                                               ['phabricator.notify'])
    builds = [
        b for b in builds
        if options[b.project.id].get('phabricator.notify', '0') == '1'
    ]

    # Exit if there are no builds for the given build_id, or any build hasn't
    # finished.
    if not builds or any(map(lambda b: b.status != Status.finished, builds)):
        return

    # if comment has already been posted for this set of builds, don't do anything
    if _comment_posted_for_collection_of_build(build):
        return

    context = build_context_lib.get_collection_context(builds)

    good_builds = [
        b for b in context.builds if b['build'].result == Result.passed
    ]
    bad_builds = [
        b for b in context.builds if b['build'].result != Result.passed
    ]

    message = ""
    if bad_builds:
        message += '(IMPORTANT) Failing builds!\n\n'
        message += '\n'.join(
            [_get_message_for_build_context(x) for x in bad_builds])
    if good_builds:
        if bad_builds:
            message += '\n\n'
        message += '(NOTE) Passing builds:\n\n'
        message += '\n'.join(
            [_get_message_for_build_context(x) for x in good_builds])

    post_comment(target, message, phab)