#!/usr/bin/python3 import argparse import collections import contextlib import datetime import lzma import os.path import sqlite3 import subprocess import time from common import decompress_stream, yield_lines, yield_chunks def scan_log_status(filelike): it = yield_chunks(filelike) it = decompress_stream(it, lzma.LZMADecompressor()) it = yield_lines(it) last_lines = collections.deque(it, 25) status = [l.split(b':', 1)[1].strip() for l in last_lines if l.startswith(b"Status:")] if status: return status[0].decode("ascii") return "unknown" def do_build(source, version, architecture, server): now = datetime.datetime.utcnow() logtarget = "%s_%s_%s_%s.log.xz" % (source, version, architecture, now.strftime("%Y%m%d%H%M%S")) cmdline = ["ssh", server, "sh", "/dev/stdin", architecture, "%s_%s" % (source, version)] with open(os.path.join("logs", logtarget), "w+b") as output: with open("build.sh", "rb") as instructions: code = subprocess.call(cmdline, stdin=instructions, stdout=output) output.seek(0) status = scan_log_status(output) print("status %s code %d" % (status, code)) return (now, code == 0, logtarget, status == "given-back") def main(): argp = argparse.ArgumentParser() argp.add_argument("server", help="machine to build on") args = argp.parse_args() db = sqlite3.connect("db", detect_types=sqlite3.PARSE_DECLTYPES) with contextlib.closing(db.cursor()) as cur: cur.execute("SELECT source, version, depstate.architecture FROM depstate JOIN depcheck ON depstate.architecture = depcheck.architecture WHERE satisfiable = 1 AND giveback = 0 ORDER BY random() LIMIT 1;") row = cur.fetchone() if not row: print("no package satisfiable") time.sleep(60) return source, version, architecture = row print("building %s_%s for %s" % (source, version, architecture)) timestamp, success, filename, giveback = \ do_build(source, version, architecture, args.server) with contextlib.closing(db.cursor()) as cur: cur.execute("INSERT INTO builds (source, version, architecture, success, starttime, filename) VALUES (?, ?, ?, ?, ?, ?);", (source, version, architecture, success, timestamp, filename)) if giveback: cur.execute("UPDATE depcheck SET giveback = 1 WHERE architecture = ?;", (architecture,)) db.commit() if __name__ == "__main__": main()