#! /usr/bin/env nix-shell #! nix-shell -i python3 -p "python3.withPackages(ps: [ps.pyramid ps.python-gitlab])" from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.view import view_config, view_defaults from pyramid.httpexceptions import HTTPNotFound from subprocess import check_call, CalledProcessError import urllib.request import tarfile from tempfile import TemporaryDirectory from multiprocessing import Pool from gitlab import Gitlab whitelist = ['nyanloutre/site-musique'] secret = open('secret', 'r').readline().splitlines()[0] gitlab_token = open('gitlab_token', 'r').readline().splitlines()[0] out_dir = './run' def build(payload, gl): gl.projects.get(payload['project']['path_with_namespace']).commits.get(payload['checkout_sha']).statuses.create({'state': 'running'}) print("push from " + payload['user_name']) print("repo: " + payload['project']['path_with_namespace']) print("commit: " + payload['checkout_sha']) temp_dir = TemporaryDirectory() repo_dir = temp_dir.name + '/' + payload['project']['name'] + '-' + payload['checkout_sha'] archive_url = payload['project']['web_url'] + '/-/archive/' + payload['checkout_sha'] + \ '/' + payload['project']['name'] + '-' + payload['checkout_sha'] + '.tar.gz' with urllib.request.urlopen(archive_url) as gitlab_archive: with tarfile.open(fileobj=gitlab_archive, mode='r|gz') as gitlab_repo_files: gitlab_repo_files.extractall(path=temp_dir.name) check_call(['ls', '-lha', repo_dir]) try: check_call(['nix-build', '-o', out_dir + '/' + payload['project']['path_with_namespace'], repo_dir]) except CalledProcessError: return {'payload': payload, 'gitlab': gl, 'status': 'failed'} return {'payload': payload, 'gitlab': gl, 'status': 'success'} def build_success(result): gl = result['gitlab'] payload = result['payload'] gl.projects.get(payload['project']['path_with_namespace']).commits.get(payload['checkout_sha']).statuses.create({'state': result['status']}) print("build: " + result['status']) @view_defaults( route_name="gitlab_payload", renderer="json", request_method="POST" ) class PayloadView(object): def __init__(self, request): self.request = request self.payload = self.request.json self.gl = Gitlab('https://gitlab.com', private_token=gitlab_token) @view_config(header="X-Gitlab-Event:Push Hook") def payload_push(self): if self.payload['project']['path_with_namespace'] in whitelist and self.request.headers['X-Gitlab-Token'] == secret: self.gl.projects.get(self.payload['project']['path_with_namespace']).commits.get(self.payload['checkout_sha']).statuses.create({'state': 'pending'}) pool.apply_async(build, (self.payload, self.gl), callback=build_success) return "build started" else: raise HTTPNotFound if __name__ == "__main__": pool = Pool(1) config = Configurator() config.add_route("gitlab_payload", "/gitlab_payload") config.scan() app = config.make_wsgi_app() server = make_server("127.0.0.1", 52350, app) print('listening ...') server.serve_forever()