#!/usr/bin/python3 import argparse import os import subprocess import sys import tarfile class RunScript: def __init__(self, args, log): self.args = args self.act = not args.dry_run self.root = args.root self.log = log def msg(self, txt): self.log.write(f"{txt}\n") self.log.flush() def join(self, path): return os.path.join(self.root, f"./{path}") def mkdir(self, path): path = self.join(path) self.msg(f"mkdir {path}") if not os.path.isdir(path): os.mkdir(path) def untar(self, tar_filename, target_directory): self.msg(f"untar {tar_filename} to {target_directory}") tar = tarfile.open(name=tar_filename, mode="r:") tar.extractall(path=self.join(target_directory)) def tar(self, filename, directory): self.msg(f"tar up {directory} as {filename}") tar = tarfile.open(name=filename, mode="w:") tar.add(directory, arcname=".") tar.close() def run(self): self.create_workspace() self.extract_sources() if self.args.cache: self.extract_cache() if self.args.dependencies: self.extract_deps() self.build() if self.args.cache: self.save_cache() def create_workspace(self): self.msg("create /workspace") if self.act: self.mkdir("/workspace") for subdir in ("src", "cache", "deps"): self.mkdir(f"/workspace/{subdir}") def extract_sources(self): self.msg(f"extract {self.args.src} to /workspace/src") if self.act: self.untar(self.args.src, "/workspace/src") def extract_cache(self): self.msg(f"extract {self.args.cache} to /workspace/cache") if self.act: self.untar(self.args.cache, "/workspace/cache") def extract_deps(self): self.msg(f"extract {self.args.dependencies} to /workspace/deps") if self.act: self.untar(self.args.dependencies, "/workspace/deps") def build(self): self.msg(f"build in /workspace/src") if self.act: src = self.join("/workspace/src") script = ".ambient-script" self.msg(f"run {script} in {src}") os.chmod(os.path.join(src, script), 0o755) with open(self.args.tty, "wb") as stdout: p = subprocess.run( [f"./{script}", os.path.abspath(self.args.artifact)], stdout=stdout, stderr=subprocess.STDOUT, cwd=src, ) self.msg(f"\nEXIT CODE: {p.returncode}\n") def save_cache(self): self.msg(f"save /workspace/cache to {self.args.cache}") if self.act: cache = self.join("/workspace/cache") self.tar(self.args.cache, cache) def parse_args(): p = argparse.ArgumentParser(prog="ambient-run-script") p.add_argument("--dump-config") p.add_argument("--dry-run") p.add_argument("-t", "--tty", required=True) p.add_argument("-s", "--source", required=True, dest="src") p.add_argument("-a", "--artifact") p.add_argument("-c", "--cache") p.add_argument("-d", "--dependencies") p.add_argument("--root", default="/") return p.parse_args() def dump_config(args, log): log.write("ambient-run-script:\n") log.write(f"- dump: {args.dump_config}\n") log.write(f"- tty: {args.tty}\n") log.write(f"- src: {args.src}\n") log.write(f"- artifact: {args.artifact}\n") log.write(f"- cache: {args.cache}\n") log.write(f"- dependencies: {args.dependencies}\n") log.write(f"- root: {args.root}\n") log.write(f"- dry_run: {args.dry_run}\n") log.flush() def run(args, log): RunScript(args, log).run() def main(): args = parse_args() print(args) if args.dump_config is not None: with open(args.dump_config, "w") as log: dump_config(args, log) elif args.dry_run: with open(args.dry_run, "w") as log: run(args, log) else: with open(args.tty, "w") as log: run(args, log) main()