github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/check-pr-has-label.py (about) 1 #!/usr/bin/python3 2 3 import argparse 4 import urllib.request 5 import logging 6 7 from html.parser import HTMLParser 8 9 LABELS = { 10 # PR label indicating that spread job should be skipped 11 'LABEL_SKIP_SPREAD_JOB': "Skip spread", 12 # PR label indicating that nested tests need to be executed 13 'LABEL_RUN_SPREAD_NESTED': "Run nested" 14 } 15 16 17 class GithubLabelsParser(HTMLParser): 18 def __init__(self): 19 super().__init__() 20 self.in_labels = False 21 self.deep = 0 22 self.labels = [] 23 24 def handle_starttag(self, tag, attributes): 25 logging.debug(attributes) 26 27 if not self.in_labels: 28 attr_class = [attr[1] for attr in attributes if attr[0] == "class"] 29 if len(attr_class) == 0: 30 return 31 # labels are in separate div defined like: 32 # <div class=".. labels .." .. > 33 elems = attr_class[0].split(" ") 34 if "labels" in elems: 35 self.in_labels = True 36 self.deep = 1 37 logging.debug("labels start") 38 else: 39 # nesting counter 40 self.deep += 1 41 42 # inside labels 43 # label entry has 44 # <a class=".." data-name="<label name>" /> 45 attr_data_name = [attr[1] for attr in attributes if attr[0] == "data-name"] 46 if len(attr_data_name) == 0: 47 return 48 data_name = attr_data_name[0] 49 logging.debug("found label: %s", data_name) 50 self.labels.append(data_name) 51 52 def handle_endtag(self, tag): 53 if self.in_labels: 54 self.deep -= 1 55 if self.deep < 1: 56 logging.debug("labels end") 57 self.in_labels = False 58 59 def handle_data(self, data): 60 if self.in_labels: 61 logging.debug("data: %s", data) 62 63 64 def grab_pr_labels(pr_number: int): 65 # ideally we would use the github API - however we can't because: 66 # a) its rate limiting and travis IPs hit the API a lot so we regularly 67 # get errors 68 # b) using a API token is tricky because travis will not allow the secure 69 # vars for forks 70 # so instead we just scrape the html title which is unlikely to change 71 # radically 72 parser = GithubLabelsParser() 73 with urllib.request.urlopen( 74 "https://github.com/snapcore/snapd/pull/{}".format(pr_number) 75 ) as f: 76 parser.feed(f.read().decode("utf-8")) 77 return parser.labels 78 79 80 def main(): 81 parser = argparse.ArgumentParser() 82 parser.add_argument( 83 "pr_number", 84 metavar="PR number", 85 help="the github PR number to check" 86 ) 87 parser.add_argument( 88 "label", 89 metavar="Label name", 90 choices=LABELS.keys(), 91 help="the github PR label to check" 92 ) 93 parser.add_argument( 94 "-d", "--debug", help="enable debug logging", action="store_true" 95 ) 96 args = parser.parse_args() 97 98 lvl = logging.INFO 99 if args.debug: 100 lvl = logging.DEBUG 101 logging.basicConfig(level=lvl) 102 103 pr_labels = grab_pr_labels(args.pr_number) 104 print("pr labels:", pr_labels) 105 106 if LABELS.get(args.label) not in pr_labels: 107 raise SystemExit(1) 108 109 print("Label: '{}' found in PR: '{}'".format( 110 LABELS.get(args.label), args.pr_number)) 111 112 113 if __name__ == "__main__": 114 main()