#!/usr/bin/env python """ Check repository settings. """ import sys import os import re from optparse import OptionParser from util import Reporter, load_yaml, require # Import this way to produce a more useful error message. try: import requests except ImportError: print('Unable to import requests module: please install requests', file=sys.stderr) sys.exit(1) # Pattern to match repository URLs and extract username and project name. P_REPO_URL = re.compile(r'https?://github\.com/([^.]+)/([^/]+)/?') # API URL format string. F_API_URL = 'https://api.github.com/repos/{0}/{1}/labels' # Expected labels and colors. EXPECTED = { 'bug' : 'bd2c00', 'discussion' : 'fc8dc1', 'enhancement' : '9cd6dc', 'help-wanted' : 'f4fd9c', 'instructor-training' : '6e5494', 'newcomer-friendly' : 'eec275', 'question' : '808040', 'template-and-tools' : '2b3990', 'work-in-progress' : '7ae78e' } def main(): """ Main driver. """ args = parse_args() reporter = Reporter() repo_url = get_repo_url(args.source_dir) check_labels(reporter, repo_url) reporter.report() def parse_args(): """ Parse command-line arguments. """ parser = OptionParser() parser.add_option('-s', '--source', default=os.curdir, dest='source_dir', help='source directory') args, extras = parser.parse_args() require(not extras, 'Unexpected trailing command-line arguments "{0}"'.format(extras)) return args def get_repo_url(source_dir): """ Figure out which repository to query. """ config_file = os.path.join(source_dir, '_config.yml') config = load_yaml(config_file) if 'repo' not in config: print('"repo" not found in {0}'.format(config_file), file=sys.stderr) sys.exit(1) return config['repo'] def check_labels(reporter, repo_url): """ Check labels in repository. """ actual = get_labels(repo_url) extra = set(actual.keys()) - set(EXPECTED.keys()) reporter.check(not extra, None, 'Extra label(s) in repository {0}: {1}', repo_url, ', '.join(sorted(extra))) missing = set(EXPECTED.keys()) - set(actual.keys()) reporter.check(not missing, None, 'Missing label(s) in repository {0}: {1}', repo_url, ', '.join(sorted(missing))) overlap = set(EXPECTED.keys()).intersection(set(actual.keys())) for name in sorted(overlap): reporter.check(EXPECTED[name] == actual[name], None, 'Color mis-match for label {0} in {1}: expected {2}, found {3}', name, repo_url, EXPECTED[name], actual[name]) def get_labels(repo_url): """ Get actual labels from repository. """ m = P_REPO_URL.match(repo_url) require(m, 'repository URL {0} does not match expected pattern'.format(repo_url)) username = m.group(1) require(username, 'empty username in repository URL {0}'.format(repo_url)) project_name = m.group(2) require(username, 'empty project name in repository URL {0}'.format(repo_url)) url = F_API_URL.format(username, project_name) r = requests.get(url) require(r.status_code == 200, 'Request for {0} failed with {1}'.format(url, r.status_code)) result = {} for entry in r.json(): result[entry['name']] = entry['color'] return result if __name__ == '__main__': main()