from bottle import route, run, request, Response, post from subprocess import call, CalledProcessError from threading import Thread from datetime import datetime import os class Logger: def log(self,text): pass class NullLogger(Logger): pass class StdoutLogger(Logger): def log(self,text): print text class FileLogger(Logger): def __init__(self,filepath): self.fh = open(filepath,"a") def log(self,text): self.fh.write("[%s] %s\n" % (datetime.now().strftime("%d.%m.%Y %H:%M"), text)) class Command: def run(self): pass class ExecCommand(Command): def __init__(self,execp,shell=False): self.execp = execp self.shell = shell def run(self, logger): try: logger.log( "Running %s with shell=%s" % ( str(self.execp), str(self.shell) ) ) call(self.execp,shell=self.shell) logger.log( "Execution succeeded." ) return True except CalledProcessError as e: logger.log( "Exception failed. (returncode=%d, cmd=%s, output=%s)" % (e.returncode, e.cmd, e.output) ) return False class GitPullCommand(ExecCommand): def __init__(self): ExecCommand.__init__(self,"git pull",shell=True) class Deploy: def __init__(self,key,branch=None,commands=[],cwd=None): self.key = key self.branch = branch self.commands = commands self.cwd = cwd def invoke(self, logger): if self.cwd is not None: os.chdir(self.cwd) for command in self.commands: if command.run(logger) == False: return def run(self,logger=NullLogger(),threaded=True): if threaded: Thread(target=self.invoke,args=(logger,)).start() else: self.invoke(logger) class DeployManager: def __init__(self, deploys=[]): self.deploys = {} self.addAll(deploys) def addAll(self, deploys=[]): for deploy in deploys: self.add(deploy) def add(self, deploy): self.deploys[(deploy.key,deploy.branch)] = deploy def get(self, key, branch=None): if self.deploys.has_key( (key,branch) ): return self.deploys[ (key,branch) ] elif self.deploys.has_key( (key,None) ): return self.deploys[ (key,None) ] else: return None def run(self, key, branch=None, threaded=True, logger=NullLogger()): deploy = self.get(key=key, branch=branch) if deploy is not None: deploy.run(threaded=threaded, logger=logger) return True else: return False class Object: pass server = Object() @post('/deploy/') def serve(key=None): if key is None: return Response(body="No key.",status=404) server.logger.log("Deploy key: %s" % key) if not request.json.has_key("ref"): return Response(body="No ref.",status=500) branch = request.json["ref"].split("/")[-1] if server.deploymanager.run(key = key, branch = branch, logger = server.logger): server.logger.log("Done.") return "Done." else: server.logger.log("Failed.") return Response(body="key %s not found" % key, status=404 ) def deploy(port=1234,deploys=[],logger=NullLogger()): server.deploymanager = DeployManager(deploys) server.logger = logger run(host="",port=port) deploy(deploys=[ Deploy(key="frontend",branch="master",commands=[ExecCommand("./deploy_master.sh",shell=True)]), Deploy(key="frontend",branch="develop",commands=[ExecCommand("./deploy_develop.sh",shell=True)]) ],logger=FileLogger("deploy.log"))