Skip to content
This repository was archived by the owner on Mar 14, 2023. It is now read-only.

Commit e898145

Browse files
committed
move to a flask webserver instead of cgi
1 parent e21037b commit e898145

File tree

8 files changed

+90
-80
lines changed

8 files changed

+90
-80
lines changed

Dockerfile

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,22 @@
11
FROM ubuntu:bionic
22

3-
RUN apt-get update && apt-get install -y apache2 \
4-
ca-certificates \
5-
python
3+
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
4+
ca-certificates \
5+
python \
6+
python-setuptools \
7+
python-wheel \
8+
python-pip
69

7-
# Set up Highfive
810
RUN mkdir /highfive
911
WORKDIR /highfive
1012

1113
COPY setup.py .
1214
COPY highfive/*.py highfive/
1315
COPY highfive/configs/ highfive/configs/
14-
RUN python setup.py install
16+
RUN pip install .
1517
RUN touch highfive/config
16-
RUN chown -R www-data:www-data .
17-
18-
# Set up Apache
19-
WORKDIR /etc/apache2
20-
COPY deployment/highfive.conf conf-available/highfive.conf
21-
RUN a2enmod cgi
22-
RUN rm conf-enabled/serve-cgi-bin.conf
23-
RUN rm sites-enabled/*
24-
RUN ln -s ../conf-available/highfive.conf conf-enabled
25-
26-
RUN mkdir /var/log/highfive-tracebacks && chown www-data: /var/log/highfive-tracebacks
2718

2819
EXPOSE 80
29-
CMD apachectl -D FOREGROUND
20+
ENV HIGHFIVE_PORT 80
21+
22+
CMD highfive

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,21 @@ Local Development
142142
You can run Highfive on your machine and configure a repository to use
143143
your local instance. Here is one approach for running a local server:
144144

145-
- Use [serve.py](/serve.py) to run the Highfive service. From the
146-
repository root, do:
145+
- Create a [virtualenv](https://virtualenv.pypa.io/en/stable/) to isolate the
146+
Python environment from the rest of the system, and install highfive in it:
147147
```
148-
$ PYTHONPATH=$PYTHONPATH:$PWD python serve.py
148+
$ virtualenv -p python2 env
149+
$ env/bin/pip install -e .
149150
```
150-
Now you have Highfive listening on port 8000 of your machine.
151-
- Your Highfive instance will need to be reachable from outside of your machine. One way to do this is to use [ngrok](https://ngrok.com/) to get a temporary domain name that proxies to your Highfive instance. Additionally, you will be able to use ngrok's inspector to easily examine and replay the requests.
151+
- Run the highfive command to start a development server on port 8000:
152+
```
153+
$ env/bin/highfive
154+
```
155+
- Your Highfive instance will need to be reachable from outside of your
156+
machine. One way to do this is to use [ngrok](https://ngrok.com/) to get a
157+
temporary domain name that proxies to your Highfive instance. Additionally,
158+
you will be able to use ngrok's inspector to easily examine and replay the
159+
requests.
152160
- Set up the webhook by following the instructions in [Enabling a
153161
Repo](#enabling-a-repo), substituting your local Highfive IP address
154162
or domain name and port number (if necessary).

deployment/highfive.conf

Lines changed: 0 additions & 7 deletions
This file was deleted.

highfive/app.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import json
2+
3+
from .newpr import HighfiveHandler, UnsupportedRepoError
4+
from .payload import Payload
5+
6+
import click
7+
import flask
8+
import waitress
9+
10+
11+
def create_app():
12+
app = flask.Flask(__name__)
13+
14+
# The canonical URL is /webhook, but other URLs are accepted for backward
15+
# compatibility.
16+
@app.route("/webhook", methods=['POST'])
17+
@app.route("/newpr.py", methods=['POST'])
18+
@app.route("/highfive/newpr.py", methods=['POST'])
19+
def new_pr():
20+
try:
21+
payload = json.loads(flask.request.form['payload'])
22+
except (KeyError, ValueError), _:
23+
return 'Error: missing or invalid payload\n', 400
24+
try:
25+
handler = HighfiveHandler(Payload(payload))
26+
return handler.run(flask.request.headers['X-GitHub-Event'])
27+
except UnsupportedRepoError:
28+
return 'Error: this repository is not configured!\n', 400
29+
30+
@app.route('/')
31+
def index():
32+
return 'Welcome to highfive!\n'
33+
34+
return app
35+
36+
37+
@click.command()
38+
@click.option('--port', default=8000)
39+
def cli(port):
40+
app = create_app()
41+
waitress.serve(app, port=port)
42+
43+
44+
def main():
45+
cli(auto_envvar_prefix='HIGHFIVE')

highfive/newpr.py

100755100644
Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from copy import deepcopy
77
import json
88
import random
9-
import sys
109
import ConfigParser
1110
from StringIO import StringIO
1211
import gzip
@@ -66,14 +65,17 @@ def load_repo_config(self):
6665
except IOError:
6766
raise UnsupportedRepoError
6867

69-
def run(self):
70-
if self.payload["action"] == "opened":
68+
def run(self, event):
69+
if event == "ping":
70+
return "Ping received! The webhook is configured correctly!\n"
71+
elif event == "pull_request" and self.payload["action"] == "opened":
7172
self.new_pr()
72-
elif self.payload["action"] == "created":
73+
return 'OK\n'
74+
elif event == "issue_comment" and self.payload["action"] == "created":
7375
self.new_comment()
76+
return 'OK\n'
7477
else:
75-
print self.payload["action"]
76-
sys.exit(0)
78+
return 'Unsupported webhook event.\n'
7779

7880
def _load_json_file(self, name):
7981
configs_dir = os.path.join(os.path.dirname(__file__), 'configs')
@@ -419,18 +421,3 @@ def new_comment(self):
419421
reviewer, owner, repo, issue, self.integration_user,
420422
author, None
421423
)
422-
423-
424-
if __name__ == "__main__":
425-
print "Content-Type: text/html;charset=utf-8"
426-
print
427-
428-
cgitb.enable(display=0, logdir="/var/log/highfive-tracebacks", format="txt")
429-
430-
post = cgi.FieldStorage()
431-
payload_raw = post.getfirst("payload",'')
432-
try:
433-
handler = HighfiveHandler(payload.Payload(json.loads(payload_raw)))
434-
handler.run()
435-
except UnsupportedRepoError:
436-
print "Unsupported repository"

highfive/tests/test_newpr.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,6 @@ def make_mocks(cls, patcherize):
12441244
cls.mocks = patcherize((
12451245
('new_pr', 'highfive.newpr.HighfiveHandler.new_pr'),
12461246
('new_comment', 'highfive.newpr.HighfiveHandler.new_comment'),
1247-
('sys', 'highfive.newpr.sys'),
12481247
))
12491248

12501249
def handler_mock(self, payload):
@@ -1255,26 +1254,23 @@ def handler_mock(self, payload):
12551254
def test_newpr(self):
12561255
payload = Payload({'action': 'opened'})
12571256
m = self.handler_mock(payload)
1258-
m.handler.run()
1257+
assert m.handler.run('pull_request') == 'OK\n'
12591258
assert m.mock_config.get.call_count == 2
12601259
self.mocks['new_pr'].assert_called_once_with()
12611260
self.mocks['new_comment'].assert_not_called()
1262-
self.mocks['sys'].exit.assert_not_called()
12631261

12641262
def test_new_comment(self):
12651263
payload = Payload({'action': 'created'})
12661264
m = self.handler_mock(payload)
1267-
m.handler.run()
1265+
assert m.handler.run('issue_comment') == 'OK\n'
12681266
assert m.mock_config.get.call_count == 2
12691267
self.mocks['new_pr'].assert_not_called()
12701268
self.mocks['new_comment'].assert_called_once_with()
1271-
self.mocks['sys'].exit.assert_not_called()
12721269

12731270
def test_unsupported_payload(self):
12741271
payload = Payload({'action': 'something-not-supported'})
12751272
m = self.handler_mock(payload)
1276-
m.handler.run()
1273+
assert m.handler.run('issue_comment') != 'OK\n'
12771274
assert m.mock_config.get.call_count == 2
12781275
self.mocks['new_pr'].assert_not_called()
12791276
self.mocks['new_comment'].assert_not_called()
1280-
self.mocks['sys'].exit.assert_called_once_with(0)

serve.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,15 @@
1212
packages = [
1313
'highfive',
1414
],
15+
install_requires = [
16+
'click',
17+
'flask',
18+
'waitress',
19+
],
20+
entry_points = {
21+
'console_scripts': [
22+
'highfive=highfive.app:main',
23+
],
24+
},
25+
zip_safe = False,
1526
)

0 commit comments

Comments
 (0)