diff --git a/swh-team/swh-weekly-report b/swh-team/swh-weekly-report new file mode 100755 --- /dev/null +++ b/swh-team/swh-weekly-report @@ -0,0 +1,88 @@ +#!/usr/bin/python3 + +# Depends: python3-click, python3-phabricator + +import click + +from datetime import datetime +from dateutil.relativedelta import relativedelta +from phabricator import Phabricator + +from swhphab import paginate, whoami +from swhphab import print_commits, print_tasks, print_reviews + + +def list_tasks(phab, newer_than): + """list subscribed tasks, modified after given timestamp + + Args: + phab: Phabricator instance + newer_than: time limit, as seconds sync epoch + """ + r = phab.maniphest.search(queryKey='subscribed', + constraints={'modifiedStart': newer_than}, + order='updated') + + return [task for task in r['data']] + + +def list_commits(phab, newer_than): + """list authored commits newer than given timestamp + + Args: + phab: Phabricator instance + newer_than: time limit, as seconds sync epoch + """ + return paginate(phab.diffusion.commit.search, + {'queryKey': 'authored', 'order': 'newest'}, + lambda c: c['fields']['committer']['epoch'] <= newer_than) + + +def list_reviews(phab, newer_than): + + def recent(c): return c['fields']['dateModified'] <= newer_than + + authored = list(paginate(phab.differential.revision.search, + {'queryKey': 'authored', 'order': 'updated'}, + recent)) + subscribed = list(paginate(phab.differential.revision.search, + {'constraints': {'subscribers': [whoami(phab)]}, + 'order': 'updated'}, + recent)) + + return authored + [r for r in subscribed if r not in authored] + + +@click.command() +@click.option('--days', '-d', default=7, show_default=True, type=int, + help='Look for events no older than N days') +@click.option('--tasks/--no-tasks', default=True, show_default=True, + help='list tasks') +@click.option('--commits/--no-commits', default=True, show_default=True, + help='list commits') +@click.option('--reviews/--no-reviews', default=True, show_default=True, + help='list reviews') +def main(days, tasks, commits, reviews): + phab = Phabricator() + phab.update_interfaces() + + query = {'newer_than': + int((datetime.now() + relativedelta(days=-days)).timestamp())} + + print() + if tasks: + print('Tasks (subscribed):') + print_tasks(phab, list_tasks(phab, **query)) + print() + if commits: + print('Commits (authored):') + print_commits(phab, list_commits(phab, **query)) + print() + if reviews: + print('Reviews (authored & subscribed):') + print_reviews(phab, list_reviews(phab, **query)) + print() + + +if __name__ == '__main__': + main() diff --git a/swh-team/swhphab.py b/swh-team/swhphab.py new file mode 100644 --- /dev/null +++ b/swh-team/swhphab.py @@ -0,0 +1,94 @@ + +from functools import lru_cache + + +def paginate(query, args, stop): + """perform a query paginating through results until stop condition is met + + """ + after = None + keep_going = True + while keep_going: + r = query(**args, after=after) + if not(r['data']): + break + for item in r['data']: + if stop(item): + keep_going = False + break + yield item + + after = r['cursor']['after'] + + +@lru_cache() +def lookup_repo(phab, repo_phid): + """lookup Phabricator repository by PHID + + """ + if repo_phid: + return phab.phid.query(phids=[repo_phid])[repo_phid] + else: + return None # stacked diffs do not have an associated repo + + +def pp_repo(repo): + """pretty print a short name for a given repository + + """ + if repo: + return repo['uri'].split('/')[-2] + else: + return 'None' + + +@lru_cache() +def whoami(phab): + """return current user's PHID + + """ + return phab.user.whoami()['phid'] + + +def print_tasks(phab, tasks): + """print a brief list of Phabricator tasks, with some context + + Args: + phab: Phabricator instance + tasks(iterable): tasks to be printed + """ + for t in tasks: + print('- T{id} | {status} | {name}'.format( + id=t['id'], + status=t['fields']['status']['value'], + name=t['fields']['name'])) + + +def print_commits(phab, commits): + """print a list of Phabricator commits, with some context + + Args: + phab: Phabricator instance + commits(iterable): commits to be printed + """ + for c in commits: + repo = lookup_repo(phab, c['fields']['repositoryPHID']) + print('- {id} | {repo} | {msg}'.format( + id=c['fields']['identifier'][:12], + repo=pp_repo(repo), + msg=c['fields']['message'].split('\n')[0])) + + +def print_reviews(phab, reviews): + """print a list of Phabricator diffs, with some context + + Args: + phab: Phabricator instance + reviews(iterable): diffs to be printed + """ + for r in reviews: + repo = lookup_repo(phab, r['fields']['repositoryPHID']) + print('- D{id} | {repo} | {title}'.format( + id=r['id'], + repo=pp_repo(repo), + title=r['fields']['title']))