Download:
child 151:640c160d89a2
parent 149:7dc53d7e465f
150:498f984cd1ef
Anton Shestakov <av6@dwimlabs.net>, Sun, 17 Jul 2016 22:38:03 +0800
queue: add hook handler (only for bitbucket at the moment)

3 файлов изменено, 113 вставок(+), 0 удалений(-) [+]
candolint/utils.py file | annotate | diff | comparison | revisions
hooks-queue.py file | annotate | diff | comparison | revisions
requirements.txt file | annotate | diff | comparison | revisions
--- a/candolint/utils.py Sun Jul 17 22:30:04 2016 +0800
+++ b/candolint/utils.py Sun Jul 17 22:38:03 2016 +0800
@@ -15,3 +15,10 @@
def parse_timestamp(value):
return datetime.strptime(value, '%Y-%m-%dT%H:%M:%S+00:00')
+
+
+def lookup_option(key, args, config, default=None):
+ argskey = key.replace('-', '_')
+ if hasattr(args, argskey):
+ return getattr(args, argskey)
+ return config.get(key, default)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hooks-queue.py Sun Jul 17 22:38:03 2016 +0800
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+import json
+import logging
+from argparse import ArgumentParser, FileType, SUPPRESS
+
+import redis
+import yaml
+from tornado.ioloop import IOLoop
+from tornado.options import define, options
+from tornado.web import Application, RequestHandler, URLSpec
+
+from candolint.utils import lookup_option, timestamp
+
+
+define('listen', metavar='IP', default='127.0.0.1')
+define('port', metavar='PORT', default=8034, type=int)
+define('xheaders', metavar='True|False', default=False, type=bool)
+options.logging = None
+
+
+class BitbucketHookHandler(RequestHandler):
+ def post(self):
+ payload = json.loads(self.request.body)
+ base = {
+ 'url': payload['repository']['links']['html']['href'],
+ 'scm': payload['repository']['scm'],
+ 'repo': payload['repository']['name'],
+ 'timestamp': timestamp(),
+ 'source': 'bitbucket.org'
+ }
+
+ items = []
+ for change in payload['push']['changes']:
+ for head in change['new']['heads']:
+ item = base.copy()
+ item.update(change=head['hash'])
+ items.append(item)
+
+ for item in items:
+ data = json.dumps(item)
+ logging.debug('Pushing %s', data)
+ self.rconn.rpush('candolint:queue:changes', data)
+ logging.info('Pushed a change for %s', data['repo'])
+
+ self.finish({'message': 'OK, added {}'.format(len(items))})
+
+ @property
+ def rconn(self):
+ return self.application.rconn
+
+
+class CandolintHooks(Application):
+ def __init__(self, rconn, debug):
+ handlers = [
+ URLSpec(r'/bb', BitbucketHookHandler),
+ ]
+ super(CandolintHooks, self).__init__(handlers, debug=debug)
+ self.rconn = rconn
+
+ def listen(self, port, address='', **kwargs):
+ name = self.__class__.__name__
+ logging.info('%s is serving on %s:%d', name, address, port)
+ super(CandolintHooks, self).listen(port, address, **kwargs)
+
+
+def main():
+ parser = ArgumentParser(argument_default=SUPPRESS)
+ parser.add_argument(
+ '-c', '--config', type=FileType('r'),
+ help='configuration file (YAML)')
+ parser.add_argument(
+ '-d', '--debug', action='store_true', default=False,
+ help='enable debugging output')
+
+ group = parser.add_argument_group(
+ 'queue configuration',
+ 'these options that can also be specified in the configuration file')
+ group.add_argument('--redis-host', help='(default: 127.0.0.1)')
+ group.add_argument('--redis-port', type=int, help='(default: 6379)')
+ group.add_argument('--redis-password')
+
+ args, extra = parser.parse_known_args()
+ options.parse_command_line(extra)
+ config = yaml.safe_load(args.config) if hasattr(args, 'config') else {}
+
+ rhost = lookup_option('redis-host', args, config, default='127.0.0.1')
+ rport = lookup_option('redis-port', args, config, default=6379)
+ rpass = lookup_option('redis-password', args, config)
+
+ logging.basicConfig(
+ level=logging.DEBUG if args.debug else logging.INFO,
+ format='%(asctime)s %(levelname)-8s %(message)s')
+
+ logging.debug('Connecting to Redis server')
+ rconn = redis.StrictRedis(host=rhost, port=rport, password=rpass, db=0)
+ logging.info('Connected to Redis server')
+
+ application = CandolintHooks(rconn, args.debug)
+ application.listen(options.port, options.listen, xheaders=options.xheaders)
+
+ IOLoop.instance().start()
+
+
+if __name__ == '__main__':
+ main()
--- a/requirements.txt Sun Jul 17 22:30:04 2016 +0800
+++ b/requirements.txt Sun Jul 17 22:38:03 2016 +0800
@@ -1,3 +1,4 @@
peewee==2.8.1
PyYAML==3.11
+redis==2.10.5
tornado==4.4