Using 00:00 as a start time
[rnaseq-cwl-training.git] / bin / repo_check.py
1 #!/usr/bin/env python
2
3 """
4 Check repository settings.
5 """
6
7 import sys
8 import os
9 import re
10 from optparse import OptionParser
11
12 from util import Reporter, load_yaml, require
13
14 # Import this way to produce a more useful error message.
15 try:
16     import requests
17 except ImportError:
18     print('Unable to import requests module: please install requests', file=sys.stderr)
19     sys.exit(1)
20
21
22 # Pattern to match repository URLs and extract username and project name.
23 P_REPO_URL = re.compile(r'https?://github\.com/([^.]+)/([^/]+)/?')
24
25 # API URL format string.
26 F_API_URL = 'https://api.github.com/repos/{0}/{1}/labels'
27
28 # Expected labels and colors.
29 EXPECTED = {
30     'bug' : 'bd2c00',
31     'discussion' : 'fc8dc1',
32     'enhancement' : '9cd6dc',
33     'help-wanted' : 'f4fd9c',
34     'instructor-training' : '6e5494',
35     'newcomer-friendly' : 'eec275',
36     'question' : '808040',
37     'template-and-tools' : '2b3990',
38     'work-in-progress' : '7ae78e'
39 }
40
41
42 def main():
43     """
44     Main driver.
45     """
46
47     args = parse_args()
48     reporter = Reporter()
49     repo_url = get_repo_url(args.source_dir)
50     check_labels(reporter, repo_url)
51     reporter.report()
52
53
54 def parse_args():
55     """
56     Parse command-line arguments.
57     """
58
59     parser = OptionParser()
60     parser.add_option('-s', '--source',
61                       default=os.curdir,
62                       dest='source_dir',
63                       help='source directory')
64
65     args, extras = parser.parse_args()
66     require(not extras,
67             'Unexpected trailing command-line arguments "{0}"'.format(extras))
68
69     return args
70
71
72 def get_repo_url(source_dir):
73     """
74     Figure out which repository to query.
75     """
76
77     config_file = os.path.join(source_dir, '_config.yml')
78     config = load_yaml(config_file)
79     if 'repo' not in config:
80         print('"repo" not found in {0}'.format(config_file), file=sys.stderr)
81         sys.exit(1)
82
83     return config['repo']
84
85
86 def check_labels(reporter, repo_url):
87     """
88     Check labels in repository.
89     """
90
91     actual = get_labels(repo_url)
92     extra = set(actual.keys()) - set(EXPECTED.keys())
93
94     reporter.check(not extra,
95                    None,
96                    'Extra label(s) in repository {0}: {1}',
97                    repo_url, ', '.join(sorted(extra)))
98
99     missing = set(EXPECTED.keys()) - set(actual.keys())
100     reporter.check(not missing,
101                    None,
102                    'Missing label(s) in repository {0}: {1}',
103                    repo_url, ', '.join(sorted(missing)))
104
105     overlap = set(EXPECTED.keys()).intersection(set(actual.keys()))
106     for name in sorted(overlap):
107         reporter.check(EXPECTED[name] == actual[name],
108                        None,
109                        'Color mis-match for label {0} in {1}: expected {2}, found {3}',
110                        name, repo_url, EXPECTED[name], actual[name])
111
112
113 def get_labels(repo_url):
114     """
115     Get actual labels from repository.
116     """
117
118     m = P_REPO_URL.match(repo_url)
119     require(m, 'repository URL {0} does not match expected pattern'.format(repo_url))
120
121     username = m.group(1)
122     require(username, 'empty username in repository URL {0}'.format(repo_url))
123
124     project_name = m.group(2)
125     require(username, 'empty project name in repository URL {0}'.format(repo_url))
126
127     url = F_API_URL.format(username, project_name)
128     r = requests.get(url)
129     require(r.status_code == 200,
130             'Request for {0} failed with {1}'.format(url, r.status_code))
131
132     result = {}
133     for entry in r.json():
134         result[entry['name']] = entry['color']
135     return result
136
137
138 if __name__ == '__main__':
139     main()