-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
200 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
./config.yaml | ||
|
||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |