Skip to content

Instantly share code, notes, and snippets.

@scturtle
Created April 7, 2016 04:13
Show Gist options
  • Select an option

  • Save scturtle/d9b2f207d14c660da5caecb1fd883e59 to your computer and use it in GitHub Desktop.

Select an option

Save scturtle/d9b2f207d14c660da5caecb1fd883e59 to your computer and use it in GitHub Desktop.
auto depolyment and monitor based on github webhook
#!/usr/bin/env python3
import os
import time
import shlex
import bottle
import pprint
import subprocess
from threading import Thread
blue = lambda s: '\033[94m%s\033[0m' % s
green = lambda s: '\033[92m%s\033[0m' % s
red = lambda s: '\033[91m%s\033[0m' % s
work_dir = '/home/scturtle/hathverse'
build_proc = web_proc = None
def build_and_restart():
build_proc.restart()
while build_proc.get_status().startswith('running'):
time.sleep(1)
web_proc.restart()
class Proc:
proc = None
def __init__(self, *, name, cmd, logfile, after=None):
self.name = name
self.cmd = cmd
self.logfile = logfile
def restart(self):
if self.proc and self.proc.poll() is None:
# if running, kill it first
print(blue('Killed proc'), self.name, str(self.proc.pid))
self.proc.terminate()
self.proc = subprocess.Popen(shlex.split(self.cmd),
stdout=open(self.logfile, 'w', 1),
stderr=subprocess.STDOUT)
print(blue('Started proc'), self.name, str(self.proc.pid))
def get_log(self):
if os.path.exists(self.logfile):
return open(self.logfile).read()
else:
return ''
def get_status(self):
if not self.proc:
status = 'not started'
elif self.proc.poll() is None:
status = 'running({})'.format(self.proc.pid)
else: # dead
status = 'exited({})'.format(self.proc.returncode)
return status
@bottle.get('/hook')
@bottle.post('/hook')
def hook():
''' web hook '''
data = bottle.request.json
print(green('Hook:\n') + pprint.pformat(data))
(status, output) = subprocess.getstatusoutput('git pull')
if status != 0:
print(red('Error in pull:'), output)
return 'error {} in pull: {}'.format(status, output)
print(green('Pulled:\n'))
# build and restart in new thread
Thread(target=build_and_restart).start()
return 'fine'
@bottle.route('/')
# @bottle.auth_basic(lambda username, password:
# username == '' and password == '')
def main():
BRANCH_CMD = 'git symbolic-ref --short HEAD'
(_, branch) = subprocess.getstatusoutput(BRANCH_CMD)
HEAD_CMD = 'git log -n 1 --oneline'
(_, head) = subprocess.getstatusoutput(HEAD_CMD)
build_status = build_proc.get_status()
build_log = build_proc.get_log()
web_status = web_proc.get_status()
web_log = web_proc.get_log()
return '''\
<html><body>
current branch: {branch}<br/>
current HEAD: {head}<br/>
<a href="/hook"><button type="button">pull and restart</button></a><br/><br/>
build proc: {build_status}<br/>
<pre>{build_log}</pre><br/>
web proc: {web_status}<br/>
<pre>{web_log}</pre><br/>
</body></html>\
'''.format(branch=branch,
head=head,
build_status=build_status,
build_log=build_log,
web_status=web_status,
web_log=web_log)
if __name__ == '__main__':
os.chdir(work_dir)
build_proc = Proc(name='build', cmd='stack build', logfile='build.log')
web_proc = Proc(name='web', cmd='stack exec hathverse', logfile='web.log')
Thread(target=build_and_restart).start()
bottle.run(host='', port=3001, debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment