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

131 lines
4.6 KiB
Python
Raw Normal View History

2016-06-10 21:59:52 +02:00
from pathlib import Path
from collections import namedtuple
from git import Repo, InvalidGitRepositoryError, NoSuchPathError
from subprocess import Popen
from concurrent.futures import ThreadPoolExecutor
from threading import RLock
import sys
import logging
import shlex
import os
2016-06-11 01:07:18 +02:00
import atexit
2016-06-10 21:59:52 +02:00
log = logging.getLogger(__name__)
2016-06-11 13:19:54 +02:00
BUILD_REPO_DIR = "{name}_build_repo"
OUTPUT_DIR = "{name}_output"
2016-06-10 21:59:52 +02:00
class DeploymentRunner:
2016-06-10 21:59:52 +02:00
def __init__(self, name, runner_config):
self.name = name
self.working_directory = Path(runner_config["working_directory"])
if not self.working_directory.exists():
log.info("creating working directory for %s: %s", name,
self.working_directory)
self.working_directory.mkdir(parents=True)
self.working_directory = self.working_directory.resolve()
self.clone_url = runner_config["clone_url"]
self.git_branch = runner_config["git_branch"]
self.target_directory = runner_config["target_directory"]
2016-06-11 13:19:54 +02:00
self.build_repo_path = self.working_directory / BUILD_REPO_DIR.format(
name=name)
2016-06-11 22:30:22 +02:00
outdir = self.working_directory / OUTPUT_DIR.format(name=name)
2016-06-11 22:04:27 +02:00
self.build_command = runner_config["build_command"].format(
2016-06-11 22:30:22 +02:00
output=outdir)
2016-06-11 15:38:59 +02:00
self._build_proc_env = dict(os.environ,
2016-06-11 22:04:27 +02:00
**runner_config.get("build_env", {}))
2016-06-10 21:59:52 +02:00
2016-06-11 15:38:59 +02:00
self._executor = ThreadPoolExecutor(max_workers=1)
self._futures = set()
self._build_proc = None
self._abort = False
2016-06-10 21:59:52 +02:00
self._build_lock = RLock()
def update_build_repository(self):
try:
build_repo = Repo(str(self.build_repo_path))
except (InvalidGitRepositoryError, NoSuchPathError) as e:
if self.build_repo_path.is_dir() and \
2016-06-10 21:59:52 +02:00
next(self.build_repo_path.iterdir(), None) is not None:
2016-06-11 13:19:54 +02:00
log.error(
"non-empty %s exists but not a valid git repository!",
self.build_repo_path)
2016-06-10 21:59:52 +02:00
raise
else:
log.info("Build repository %s not there, cloneing", e)
build_repo = Repo.clone_from(self.clone_url,
str(self.build_repo_path),
branch=self.git_branch)
if build_repo.remotes.origin.url != self.clone_url:
cw = build_repo.remotes.origin.config_writer
cw.set("url", self.clone_url)
cw.release()
2016-06-10 21:59:52 +02:00
build_repo.head.reference = build_repo.create_head(self.git_branch)
assert not build_repo.head.is_detached
# deinit submodules to avoid removed ones dangling around later
# they should stay around in .git, so reinit should be fast
build_repo.git.submodule("deinit", ".")
2016-06-10 21:59:52 +02:00
build_repo.remotes.origin.pull(
force=True,
no_edit=True,
refspec="+{b}:{b}".format(b=self.git_branch),
recurse_submodules="yes")
2016-06-10 21:59:52 +02:00
# forcefully reset the working tree
build_repo.head.reset(index=True, working_tree=True)
try:
2016-06-11 21:20:45 +02:00
build_repo.git.clean(force=True, d=True, x=True)
2016-06-10 21:59:52 +02:00
except:
log.warning("git clean failed!", exc_info=True)
# update the submodules
build_repo.git.submodule("update", "--init", "--force", "--recursive")
2016-06-10 21:59:52 +02:00
def build(self, abort_running=False):
with self._build_lock:
if abort_running:
self.try_abort_build()
# cancel everything, so we are next
2016-06-11 15:38:59 +02:00
for fut in self._futures.copy():
2016-06-10 21:59:52 +02:00
fut.cancel()
if fut.done():
2016-06-11 15:38:59 +02:00
self._futures.remove(fut)
2016-06-10 21:59:52 +02:00
2016-06-11 15:38:59 +02:00
self._futures.add(self._executor.submit(self.build_blocking))
2016-06-10 21:59:52 +02:00
def try_abort_build(self):
2016-06-11 15:38:59 +02:00
proc = self._build_proc
self._abort = True
2016-06-10 21:59:52 +02:00
if proc:
proc.kill()
def build_blocking(self):
2016-06-11 15:38:59 +02:00
self._abort = False
2016-06-10 21:59:52 +02:00
# preparing build environment
self.update_build_repository()
# TODO: prepare_output()
# start the build if we should not abort
2016-06-11 15:38:59 +02:00
if not self._abort:
2016-06-11 22:04:27 +02:00
args = shlex.split(self.build_command)
2016-06-11 15:38:59 +02:00
self._build_proc = Popen(args,
cwd=str(self.build_repo_path),
env=self._build_proc_env)
atexit.register(self._build_proc.kill)
status = self._build_proc.wait()
atexit.unregister(self._build_proc.kill)
2016-06-11 01:07:18 +02:00
2016-06-10 21:59:52 +02:00
if status == 0:
# TODO: postproc...
pass