1
0
mirror of https://github.com/IEEE-SB-Passau/pelican-deployment-system.git synced 2017-09-06 16:35:38 +02:00

Save some build status

This commit is contained in:
2016-06-14 21:16:23 +02:00
parent 7566dc6356
commit 72ba260c8f

View File

@@ -1,11 +1,13 @@
from pathlib import Path from pathlib import Path
from collections import namedtuple from collections import namedtuple, deque
from pelican_deploy.gittool import Repo, log_git_result from pelican_deploy.gittool import Repo, log_git_result
from functools import partial from functools import partial
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from pelican_deploy.util import exception_logged from pelican_deploy.util import exception_logged
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from threading import RLock from threading import RLock
from datetime import datetime
import pytz
import sys import sys
import logging import logging
import shlex import shlex
@@ -18,6 +20,9 @@ log_git = partial(log_git_result, out_logger=log.debug,
BUILD_REPO_DIR = "{name}_build_repo" BUILD_REPO_DIR = "{name}_build_repo"
OUTPUT_DIR = "{name}_output" OUTPUT_DIR = "{name}_output"
STATUS_LEN = 500
BuildStatus = namedtuple("BuildStatus", "date ok msg payload running")
class PullError(Exception): class PullError(Exception):
pass pass
@@ -53,6 +58,12 @@ class DeploymentRunner:
self._build_lock = RLock() self._build_lock = RLock()
self._repo_update_lock = RLock() self._repo_update_lock = RLock()
self.build_status = deque(maxlen=STATUS_LEN)
def update_status(self, ok, msg, payload=None, running=True):
date = pytz.utc.localize(datetime.utcnow())
self.build_status.append(BuildStatus(date, ok, msg, payload, running))
def update_build_repository(self): def update_build_repository(self):
with self._repo_update_lock: with self._repo_update_lock:
self._update_build_repository() self._update_build_repository()
@@ -131,10 +142,18 @@ class DeploymentRunner:
if fut.done(): if fut.done():
self._futures.remove(fut) self._futures.remove(fut)
build_bl = partial(self.build_blocking, ignore_pull_error= def build_job():
build_bl = partial(self._build_blocking, ignore_pull_error=
ignore_pull_error) ignore_pull_error)
build_func = exception_logged(build_bl, log.error) build_func = exception_logged(build_bl, log.error)
future = self._executor.submit(build_func) try:
build_func()
except Exception as e:
self.update_status(False, "Build stopped with exception",
running=False, payload={"exception": e})
raise
future = self._executor.submit(build_job)
self._futures.add(future) self._futures.add(future)
if wait: if wait:
return future.result() return future.result()
@@ -150,6 +169,7 @@ class DeploymentRunner:
def final_install(self): def final_install(self):
args = shlex.split(self.final_install_command) args = shlex.split(self.final_install_command)
self.update_status(True, "Starting final_install")
log.info("%s: Starting final_install `%s`", self.name, args) log.info("%s: Starting final_install `%s`", self.name, args)
proc = Popen(args, stdout=PIPE, stderr=PIPE, universal_newlines=True, proc = Popen(args, stdout=PIPE, stderr=PIPE, universal_newlines=True,
start_new_session=True) start_new_session=True)
@@ -165,25 +185,36 @@ class DeploymentRunner:
log.info('%s final_install_command stderr: %s\n', self.name, errs) log.info('%s final_install_command stderr: %s\n', self.name, errs)
if status > 0: if status > 0:
self.update_status(False, ("final_install_command failed."
" Website may be broken!"),
payload={"status": status,
"stdout": outs, "stderr": errs})
log.error("%s: final_install failed! Website may be broken!", log.error("%s: final_install failed! Website may be broken!",
self.name) self.name)
else:
self.update_status(True, "finished final_install_command",
payload={"stdout": outs, "stderr": errs})
def build_blocking(self, ignore_pull_error=False): def _build_blocking(self, ignore_pull_error=False):
self._abort = False self._abort = False
# preparing build environment # preparing build environment
try: try:
self.update_status(True, "Start updating repository")
self.update_build_repository() self.update_build_repository()
except PullError: except PullError:
if ignore_pull_error: if ignore_pull_error:
log.warning(("Git pull failed, trying" msg = "Git pull failed, trying to continue with what we have"
" to continue with what we have"), exc_info=True) self.update_status(False, msg)
log.warning(msg, exc_info=True)
else: else:
raise raise
# start the build if we should not abort # start the build if we should not abort
if not self._abort: if not self._abort:
args = shlex.split(self.build_command) args = shlex.split(self.build_command)
self.update_status(True, "Starting the main build command",
payload={"cmd": args})
log.info("%s: Starting build_command `%s`", self.name, args) log.info("%s: Starting build_command `%s`", self.name, args)
self._build_proc = Popen(args, stdout=PIPE, stderr=PIPE, self._build_proc = Popen(args, stdout=PIPE, stderr=PIPE,
cwd=str(self.build_repo_path), cwd=str(self.build_repo_path),
@@ -194,6 +225,7 @@ class DeploymentRunner:
status = self._build_proc.wait() status = self._build_proc.wait()
if status < 0: if status < 0:
self.update_status(False, "killed build_command")
log.info("%s: killed build_command", self.name) log.info("%s: killed build_command", self.name)
else: else:
log.info("%s: finished build_command with status %s!", log.info("%s: finished build_command with status %s!",
@@ -201,7 +233,17 @@ class DeploymentRunner:
log.info('%s build_command stdout: %s\n', self.name, outs) log.info('%s build_command stdout: %s\n', self.name, outs)
log.info('%s build_command stderr: %s\n', self.name, errs) log.info('%s build_command stderr: %s\n', self.name, errs)
if status == 0: if status == 0:
self.update_status(True, "finished build_command",
payload={"stdout": outs, "stderr": errs})
self.final_install() self.final_install()
else:
self.update_status(False, "build_command failed",
payload={"status": status,
"stdout": outs, "stderr": errs})
self.update_status(self.build_status[-1].ok, "End of build",
running=False)
def shutdown(self): def shutdown(self):
self.try_abort_build() self.try_abort_build()