summary refs log tree commit diff
path: root/maintainers/scripts/hydra-eval-failures.py
diff options
context:
space:
mode:
Diffstat (limited to 'maintainers/scripts/hydra-eval-failures.py')
-rwxr-xr-xmaintainers/scripts/hydra-eval-failures.py112
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()