import urllib import os import simplejson as json import web from datetime import datetime from subprocess import Popen from socket import socket, AF_INET, SOCK_DGRAM import settings """ Recieve pings from Github Webhook API and perform actions. Examples of actions: - Run a script to deploy on your webserver. Yup. - Send a message to IRC (via an ircbot listening for UDP-messages). Yup. - Send an email. - Send a signal to an Arduino. TODO: - Provide deploy log - Send mail to commiter on error. Written in web.py """ urls = ( '/', 'ping', ) class ping: def script_path(self): return os.path.dirname(os.path.abspath(__file__)) def url_allowed(self,url): for allowed_url, deploy_to in settings.REPOS.iteritems(): if url == allowed_url: return True return False def POST(self): post_data = web.input() try: data = json.loads(post_data['payload']) except ValueError: error = "Got ping with non-JSON POST-data: \'" + str(post_data) + "\'" self.log(error) return json.dumps({'result': error}) repo_url = data['repository']['url'] repo_name = data['repository']['name'] self.log("Got ping. Repo: " + repo_name + " Commit by: " + self.format_who(data['commits']) + ".") if not self.url_allowed(repo_url): not_allowed = "Repository URL \'" + repo_url + "\' not allowed." self.log(not_allowed) return not_allowed # TODO: Make optional in settings self.update_repo(data['repository']['name'], repo_url) self.send_to_irc(data) return json.dumps({'result' : "Thank you :-)"}) def update_repo(self, name, url): if not settings.REPOS[url]: self.log("No deploy path defined.") return # run the deployscript args = ['/bin/sh', settings.DEPLOY_SCRIPT_PATH, settings.REPOS[url], name] self.log("Updating repo: \'" + " ".join(args) + "\'") p = Popen(args) def format_who(self, commits): who = "" if len(commits) == 1: who = commits[0]['author']['name'] else: who = set() # unique entries for commit in commits: who.add(commit['author']['name']) who = ", ".join(who) return who def format_for_irc(self, data): # String to be sent to irc. who = self.format_who(data['commits']) return "Git commit: \'{0}\': {1} by {2}".format(data['repository']['name'], data['compare'], who) def send_to_irc(self, data): # Send the message to snurr via UDP. data = self.format_for_irc(data) udp = socket(AF_INET, SOCK_DGRAM) udp.sendto(data, settings.IRC_BOT_HOST) def log(self, msg): # Log pings. log = open(self.script_path() + "/pings.log", "a+") log.write(datetime.now().isoformat() + ": " + msg + "\n") log.close() app = web.application(urls, globals(), autoreload=True) application = app.wsgifunc() if __name__ == "__main__": app.run()