def get(self): """ Gets the list of open tasks associated with quarantined tests. We find them based on the fact that they're always created by the same bot/user. """ try: quarantine_user = current_app.config['QUARANTINE_PHID'] if not quarantine_user: return self.respond({'fetched_data_from_phabricator': False}) request = PhabricatorClient() request.connect() task_info = request.call('maniphest.query', {'authorPHIDs': [quarantine_user]}) # we need to get the names of the task owners too user_info = {} owner_phids = [ t['ownerPHID'] for t in task_info.values() if t.get('ownerPHID') ] if owner_phids: user_info = request.call('phid.query', {'phids': owner_phids}) return self.respond({ 'fetched_data_from_phabricator': True, 'tasks': task_info, 'users': user_info }) except requests.exceptions.ConnectionError: return 'Unable to connect to Phabricator', 503
def get(self, author_id): if author_id == 'me' and not get_current_user(): return error('Must be logged in to ask about yourself', http_code=401) authors = Author.find(author_id, get_current_user()) if not authors: return self.respond([]) try: author_email = authors[0].email request = PhabricatorClient() request.connect() user_info = request.call('user.query', {'emails': [author_email]}) if not user_info: return 'phabricator: %s not found' % author_email, 404 author_phid = user_info[0]["phid"] diff_info = request.call('differential.query', { 'authors': [author_phid], 'status': "status-open" }) diff_info.sort(key=lambda k: -1 * int(k['dateModified'])) except requests.exceptions.ConnectionError: return 'Unable to connect to Phabricator', 503 if not diff_info: # No diffs, no point in trying to find builds. return self.respond([]) rows = list( db.session.query(PhabricatorDiff, Build).join( Build, Build.source_id == PhabricatorDiff.source_id).filter( PhabricatorDiff.revision_id.in_( [d['id'] for d in diff_info]))) serialized_builds = zip(self.serialize([row.Build for row in rows]), [row.PhabricatorDiff for row in rows]) builds_map = defaultdict(list) for build, phabricator_diff in serialized_builds: builds_map[str(phabricator_diff.revision_id)].append(build) for d in diff_info: d['builds'] = builds_map[str(d['id'])] return self.respond(diff_info)
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 get(self, diff_ident): if not diff_ident.startswith('D') or not diff_ident[1:].isdigit(): return error('diff id not valid') # grab diff info from phabricator. phabricator_info = {} try: request = PhabricatorClient() request.connect() phabricator_info = request.call('differential.query', {'ids': [int(diff_ident[1:])]}) if len(phabricator_info) == 0: return error('%s not found in phabricator' % diff_ident, http_code=404) assert len(phabricator_info) == 1 phabricator_info = phabricator_info[0] phabricator_info["fetched_data_from_phabricator"] = True except Exception as e: # If the phabricator call fails for whatever reason, we'll still # return the builds info from changes. We don't want changes to # be unusable if phabricator is down print e phabricator_info = {"fetched_data_from_phabricator": False} pass # TODO: if we want the name/email of the author of the diff, we'd have # to make another conduit call. Instead, we'll let the frontend rely # on the fact that any phabricator-tagged build always has the same # author as the diff # grab builds rows = list( db.session.query(Build, PhabricatorDiff).join( PhabricatorDiff, Build.source_id == PhabricatorDiff.source_id, ).filter(PhabricatorDiff.revision_id == diff_ident[1:])) build_ids = set([row.Build.id for row in rows]) jobs = [] if len(build_ids) > 0: jobs = self.serialize( list(Job.query.filter(Job.build_id.in_(build_ids)))) serialized_builds = zip(self.serialize([row.Build for row in rows]), [row.PhabricatorDiff for row in rows]) build_info = {} for build, phabricator_diff in serialized_builds: # we may have multiple diffs within a single differential revision single_diff_id = phabricator_diff.diff_id if single_diff_id not in build_info: build_info[single_diff_id] = { 'id': phabricator_diff.id, 'builds': [], 'diff_id': phabricator_diff.diff_id, 'revision_id': phabricator_diff.revision_id, 'url': phabricator_diff.url, 'source_id': phabricator_diff.source_id, 'dateCreated': phabricator_diff.date_created } build['jobs'] = [ j for j in jobs if j['build']['id'] == build['id'] ] build_info[single_diff_id]['builds'].append(build) phabricator_info['changes'] = build_info return self.respond(phabricator_info)