diff options
Diffstat (limited to 'maintainers/scripts/hydra-eval-failures.py')
-rwxr-xr-x | maintainers/scripts/hydra-eval-failures.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/maintainers/scripts/hydra-eval-failures.py b/maintainers/scripts/hydra-eval-failures.py new file mode 100755 index 00000000000..b7518b12857 --- /dev/null +++ b/maintainers/scripts/hydra-eval-failures.py @@ -0,0 +1,112 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ requests pyquery click ])" + +# To use, just execute this script with --help to display help. + +import subprocess +import json +import sys + +import click +import requests +from pyquery import PyQuery as pq + +def map_dict (f, d): + for k,v in d.items(): + d[k] = f(v) + +maintainers_json = subprocess.check_output([ + 'nix-instantiate', '-A', 'lib.maintainers', '--eval', '--strict', '--json' +]) +maintainers = json.loads(maintainers_json) +MAINTAINERS = map_dict(lambda v: v.get('github', None), maintainers) + +def get_response_text(url): + return pq(requests.get(url).text) # IO + +EVAL_FILE = { + 'nixos': 'nixos/release.nix', + 'nixpkgs': 'pkgs/top-level/release.nix', +} + + +def get_maintainers(attr_name): + try: + nixname = attr_name.split('.') + meta_json = subprocess.check_output([ + 'nix-instantiate', + '--eval', + '--strict', + '-A', + '.'.join(nixname[1:]) + '.meta', + EVAL_FILE[nixname[0]], + '--arg', + 'nixpkgs', + './.', + '--json']) + meta = json.loads(meta_json) + return meta.get('maintainers', []) + except: + return [] + +def filter_github_users(maintainers): + github_only = [] + for i in maintainers: + if i.get('github'): + github_only.append(i) + return github_only + +def print_build(table_row): + a = pq(table_row)('a')[1] + print("- [ ] [{}]({})".format(a.text, a.get('href')), flush=True) + + job_maintainers = filter_github_users(get_maintainers(a.text)) + if job_maintainers: + print(" - maintainers: {}".format(" ".join(map(lambda u: '@' + u.get('github'), job_maintainers)))) + # TODO: print last three persons that touched this file + # TODO: pinpoint the diff that broke this build, or maybe it's transient or maybe it never worked? + + sys.stdout.flush() + +@click.command() +@click.option( + '--jobset', + default="nixos/release-19.09", + help='Hydra project like nixos/release-19.09') +def cli(jobset): + """ + Given a Hydra project, inspect latest evaluation + and print a summary of failed builds + """ + + url = "https://hydra.nixos.org/jobset/{}".format(jobset) + + # get the last evaluation + click.echo(click.style( + 'Getting latest evaluation for {}'.format(url), fg='green')) + d = get_response_text(url) + evaluations = d('#tabs-evaluations').find('a[class="row-link"]') + latest_eval_url = evaluations[0].get('href') + + # parse last evaluation page + click.echo(click.style( + 'Parsing evaluation {}'.format(latest_eval_url), fg='green')) + d = get_response_text(latest_eval_url + '?full=1') + + # TODO: aborted evaluations + # TODO: dependency failed without propagated builds + print('\nFailures:') + for tr in d('img[alt="Failed"]').parents('tr'): + print_build(tr) + + print('\nDependency failures:') + for tr in d('img[alt="Dependency failed"]').parents('tr'): + print_build(tr) + + + +if __name__ == "__main__": + try: + cli() + except Exception as e: + import pdb;pdb.post_mortem() |