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)
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)
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)
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)
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)
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)
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)