forked from EESSI/eessi-bot-software-layer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheessi_bot_event_handler.py
183 lines (155 loc) · 6.48 KB
/
eessi_bot_event_handler.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env python3
#
# This file is part of the EESSI build-and-deploy bot,
# see https://github.com/EESSI/eessi-bot-software-layer
#
# The bot helps with requests to add software installations to the
# EESSI software layer, see https://github.com/EESSI/software-layer
#
# author: Kenneth Hoste (@boegel)
# author: Bob Droege (@bedroge)
# author: Hafsa Naeem (@hafsa-naeem)
# author: Thomas Roeblitz (@trz42)
#
# license: GPLv2
#
import waitress
import sys
from connections import github
from tools import config
from tools.args import event_handler_parse
from tasks.build import check_build_permission, submit_build_jobs, get_repo_cfg
from tasks.deploy import deploy_built_artefacts
from pyghee.lib import PyGHee, create_app, get_event_info, read_event_from_json
from pyghee.utils import log
class EESSIBotSoftwareLayer(PyGHee):
def __init__(self, *args, **kwargs):
"""
EESSIBotSoftwareLayer constructor.
"""
super(EESSIBotSoftwareLayer, self).__init__(*args, **kwargs)
self.cfg = config.read_config()
event_handler_cfg = self.cfg['event_handler']
self.logfile = event_handler_cfg.get('log_path')
def log(self, msg, *args):
"""
Logs a message incl the caller's function name by passing msg and *args to PyGHee's log method.
Args:
msg (string): message (format) to log to event handler log
*args (any): any values to be substituted into msg
"""
funcname = sys._getframe().f_back.f_code.co_name
if args:
msg = msg % args
msg = "[%s]: %s" % (funcname, msg)
log(msg, log_file=self.logfile)
def handle_issue_comment_event(self, event_info, log_file=None):
"""
Handle adding/removing of comment in issue or PR.
"""
request_body = event_info['raw_request_body']
issue_url = request_body['issue']['url']
comment_author = request_body['comment']['user']['login']
comment_txt = request_body['comment']['body']
self.log("Comment posted in %s by @%s: %s", issue_url, comment_author, comment_txt)
self.log("issue_comment event handled!")
def handle_installation_event(self, event_info, log_file=None):
"""
Handle installation of app.
"""
request_body = event_info['raw_request_body']
user = request_body['sender']['login']
action = request_body['action']
# repo_name = request_body['repositories'][0]['full_name'] # not every action has that attribute
self.log("App installation event by user %s with action '%s'", user, action)
self.log("installation event handled!")
def handle_pull_request_labeled_event(self, event_info, pr):
"""
Handle adding of a label to a pull request.
"""
# determine label
label = event_info['raw_request_body']['label']['name']
self.log("Process PR labeled event: PR#%s, label '%s'", pr.number, label)
if label == "bot:build":
# run function to build software stack
if check_build_permission(pr, event_info):
submit_build_jobs(pr, event_info)
elif label == "bot:deploy":
# run function to deploy built artefacts
deploy_built_artefacts(pr, event_info)
else:
self.log("handle_pull_request_labeled_event: no handler for label '%s'", label)
def handle_pull_request_opened_event(self, event_info, pr):
"""
Handle opening of a pull request.
"""
self.log("PR opened: waiting for label bot:build")
app_name = self.cfg['github']['app_name']
# TODO check if PR already has a comment with arch targets and
# repositories
repo_cfg = get_repo_cfg(self.cfg)
comment = f"Instance `{app_name}` is configured to build:"
for arch in repo_cfg['repo_target_map'].keys():
for repo_id in repo_cfg['repo_target_map'][arch]:
comment += f"\n- arch `{'/'.join(arch.split('/')[1:])}` for repo `{repo_id}`"
self.log(f"PR opened: comment '{comment}'")
# create comment to pull request
repo_name = pr.base.repo.full_name
gh = github.get_instance()
repo = gh.get_repo(repo_name)
pull_request = repo.get_pull(pr.number)
pull_request.create_issue_comment(comment)
def handle_pull_request_event(self, event_info, log_file=None):
"""
Handle 'pull_request' event
"""
action = event_info['action']
gh = github.get_instance()
self.log("repository: '%s'", event_info['raw_request_body']['repository']['full_name'])
pr = gh.get_repo(event_info['raw_request_body']['repository']
['full_name']).get_pull(event_info['raw_request_body']['pull_request']['number'])
self.log("PR data: %s", pr)
handler_name = 'handle_pull_request_%s_event' % action
if hasattr(self, handler_name):
handler = getattr(self, handler_name)
self.log("Handling PR action '%s' for PR #%d...", action, pr.number)
handler(event_info, pr)
else:
self.log("No handler for PR action '%s'", action)
def start(self, app, port=3000):
"""starts the app and log information in the log file
Args:
app (object): instance of class EESSIBotSoftwareLayer
port (int, optional): Defaults to 3000.
"""
start_msg = "EESSI bot for software layer started!"
print(start_msg)
self.log(start_msg)
port_info = "app is listening on port %s" % port
print(port_info)
self.log(port_info)
event_handler_cfg = self.cfg['event_handler']
my_logfile = event_handler_cfg.get('log_path')
log_file_info = "logging in to %s" % my_logfile
print(log_file_info)
self.log(log_file_info)
waitress.serve(app, listen='*:%s' % port)
def main():
"""Main function."""
opts = event_handler_parse()
# config is read to raise an exception early when the event_handler starts.
config.read_config()
github.connect()
if opts.file:
app = create_app(klass=EESSIBotSoftwareLayer)
event = read_event_from_json(opts.file)
event_info = get_event_info(event)
app.handle_event(event_info)
elif opts.cron:
app.log("Running in cron mode")
else:
# Run as web app
app = create_app(klass=EESSIBotSoftwareLayer)
app.start(app, port=opts.port)
if __name__ == '__main__':
main()