-
Notifications
You must be signed in to change notification settings - Fork 1
/
suite.py
146 lines (126 loc) · 4.59 KB
/
suite.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import datetime
import logging
import os
import re
import sys
import urllib.parse
import yaml
from lintipy import COMPLETED, ACTION_REQUIRED, QUEUED, DownloadCodeMixin, GitHubEvent
logger = logging.getLogger('suite')
class CheckSuite(DownloadCodeMixin, GitHubEvent):
"""AWS lambda handler for GitHub ``check_suite`` events."""
CHECK_SUITE = 'check_suite'
COMPLETED = 'completed'
REQUESTED = 'requested'
REREQUESTED = 'rerequested'
PULL_REQUEST = 'pull_request'
OPENED = 'opened'
REOPENED = 'reopened'
EDITED = 'edited'
SYNCHRONIZE = 'synchronize'
config_file_default = '.fussyfox.yml'
config_file_pattern = re.compile(
r'(.github/)?\.?(checks|fussyfox)\.(yml|yaml|json)',
re.IGNORECASE,
)
def __call__(self, event, context):
super().__call__(event, context)
if self.event_type == self.CHECK_SUITE and \
self.hook['action'] in [self.REQUESTED, self.REREQUESTED]:
pass
elif self.event_type == self.PULL_REQUEST and \
self.hook['action'] in [self.OPENED, self.REOPENED, self.SYNCHRONIZE]:
pass
else:
logger.info('no action required')
return
path = self.download_code()
config = set(self.load_config(path) or [])
logger.debug(config)
self.create_check_run(
'BYE BYE',
status=COMPLETED,
body='Since GitHub have been getting so fast (especially with caching),'
' we decided to discontinue this service. Thank you for your trust!',
conclusion=ACTION_REQUIRED,
)
@staticmethod
def find_config_file(path, regexpr):
"""Return first file matching the regular expression."""
for base_dir, dir_names, filenames in os.walk(path):
for filename in filenames:
if regexpr.match(filename):
return os.path.join(path, filename)
@property
def sha(self):
event = self.hook[self.event_type]
try:
return event['head_sha']
except KeyError:
return event['head']['sha']
@property
def archive_url(self):
return self.hook['repository']['archive_url'].format(**{
'archive_format': 'tarball',
'/ref': '/%s' % self.sha,
})
@property
def check_runs_url(self):
return "https://api.github.com/repos/{full_name}/check-runs".format(
full_name=self.hook['repository']['full_name']
)
def load_config(self, path):
"""Return config dictionary or ``None`` if no config was found."""
config_path = self.find_config_file(path, self.config_file_pattern)
if config_path is None:
return
logger.info("Reading config: %s", config_path)
try:
with open(config_path) as fs:
return yaml.safe_load(fs)
except FileNotFoundError:
logger.error("file not found")
return None
def create_getting_started_guide(self, services):
with open('getting_started.md') as fp:
body = fp.read()
hyperlink_pattern = "* [{title}]({href})"
service_links = (
hyperlink_pattern.format(title=title, href=url)
for title, url in services.items()
)
body += "\n".join(service_links)
body += "\n\n[template]: %s\n" % self.get_new_config_link()
return body
def create_check_run(self, name, status=QUEUED, body=None, conclusion=None):
logger.info("createing check run: %s", name)
data = {
'name': name,
'head_sha': self.sha,
'status': status,
}
if body is not None:
data['output'] = {
'title': name,
'summary': body,
}
if conclusion:
data['conclusion'] = conclusion
if status == COMPLETED:
data['completed_at'] = datetime.datetime.utcnow() \
.strftime('%Y-%m-%dT%H:%M:%SZ')
response = self.session.post(self.check_runs_url, json=data)
logger.debug(response.content.decode())
response.raise_for_status()
def get_new_config_link(self):
url = "https://github.com/{full_name}/new/master?".format(
full_name=self.hook['repository']['full_name']
)
with open('template.yml') as f:
template = f.read()
kwargs = {
'filename': self.config_file_default,
'value': template
}
return url + urllib.parse.urlencode(kwargs)
handler = CheckSuite.as_handler()