Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pstauffer committed Feb 7, 2017
1 parent d186c1c commit 5663516
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
./config.yaml

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,63 @@
# gitlab-webhook-receiver
Simple gitlab webhook receiver
Simple gitlab webhook receiver.

## Source
The idea and base of the script is from this [github repo](https://github.com/schickling/docker-hook).

## Configuration

### Gitlab Secret Token
The script requires, that the gitlab secret token is set! You can define the value in the [configuration file](#example-config).

### Gitlab Project Homepage
The structure of the [configuration file](#example-config) requires the homepage of the gitlab project as key.

### Command
Define, which command should be run after the hook was received.

### Example config
```
# file: config.yaml
---
# myrepo
https://git.example.ch/exmaple/myrepo:
command: uname
gitlab_token: mysecret-myrepo
# test-repo
https://git.example.ch/exmaple/test-repo:
command: uname
gitlab_token: mysecret-test-repo
```

## Script Arguments

### Port
Define the listen port for the webserver. Default: **8666**

### Addr
Define the listen address for the webserver. Default: **0.0.0.0**

### Cfg
Define the path to your configuration file. Default: **config.yaml**



## Run Script

```
python gitlab-webhook-receiver.py --port 8080 --cfg /etc/hook.yaml
```


### Help
```
usage: gitlab-webhook-receiver.py [-h] [--addr ADDR] [--port PORT] [--cfg CFG]
Gitlab Webhook Receiver
optional arguments:
-h, --help show this help message and exit
--addr ADDR address where it listens (default: 0.0.0.0)
--port PORT port where it listens (default: 8666)
--cfg CFG path to the config file (default: config.yaml)
```
9 changes: 9 additions & 0 deletions examples/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# myrepo
https://git.example.ch/exmaple/myrepo:
command: uname
gitlab_token: mysecret-myrepo
# test-repo
https://git.example.ch/exmaple/test-repo:
command: uname
gitlab_token: mysecret-test-repo
9 changes: 9 additions & 0 deletions examples/gitlab-webhook-receiver.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Gitlab Webhook Receiver
After=network.target

[Service]
ExecStart=gitlab-webhook-receiver.py

[Install]
WantedBy=multi-user.target
118 changes: 118 additions & 0 deletions gitlab-webhook-receiver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-

""" Gitlab Webhook Receiver """
# Based on: https://github.com/schickling/docker-hook

import json
import yaml
import subprocess
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
try:
# For Python 3.0 and later
from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
except ImportError:
# Fall back to Python 2
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer as HTTPServer
import sys
import logging

logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
level=logging.DEBUG,
stream=sys.stdout)


class RequestHandler(BaseHTTPRequestHandler):
"""A POST request handler."""

def do_POST(self):
logging.info("Hook received")

# get payload
header_length = int(self.headers.getheader('content-length', "0"))
json_payload = self.rfile.read(header_length)
json_params = {}
if len(json_payload) > 0:
json_params = json.loads(json_payload)

# get gitlab secret token
gitlab_token_header = self.headers.getheader('X-Gitlab-Token')

# get project homepage
project = json_params['project']['homepage']

try:
# get command and token from config file
command = config[project]['command']
gitlab_token = config[project]['gitlab_token']

logging.info("Load project '%s' and run command '%s'", project, command)
except KeyError as err:
self.send_response(500, "KeyError")
logging.error("Project '%s' not found in %s", project, args.cfg)
self.end_headers()
return

# Check if the gitlab token is valid
if gitlab_token_header == gitlab_token:
logging.info("Start executing '%s'" % command)
try:
subprocess.call(command)
self.send_response(200, "OK")
except OSError as err:
self.send_response(500, "OSError")
logging.error("Command could not run successfully.")
logging.error(err)
else:
logging.error("Not authorized, Gitlab_Token not authorized")
self.send_response(401, "Gitlab Token not authorized")
self.end_headers()


def get_parser():
"""Get a command line parser."""
parser = ArgumentParser(description=__doc__,
formatter_class=ArgumentDefaultsHelpFormatter)

parser.add_argument("--addr",
dest="addr",
default="0.0.0.0",
help="address where it listens")
parser.add_argument("--port",
dest="port",
type=int,
default=8666,
metavar="PORT",
help="port where it listens")
parser.add_argument("--cfg",
dest="cfg",
default="config.yaml",
help="path to the config file")
return parser


def main(addr, port):
"""Start a HTTPServer which waits for requests."""
httpd = HTTPServer((addr, port), RequestHandler)
httpd.serve_forever()


if __name__ == '__main__':
parser = get_parser()

if len(sys.argv) == 0:
parser.print_help()
sys.exit(1)
args = parser.parse_args()

# load config file
try:
with open(args.cfg, 'r') as stream:
config = yaml.load(stream)
except IOError as err:
logging.error("Config file %s could not be loaded", args.cfg)
sys.exit(1)

main(args.addr, args.port)

0 comments on commit 5663516

Please sign in to comment.