13 from common import decompress_stream, yield_lines, yield_chunks
15 def scan_log_status(filelike):
16 it = yield_chunks(filelike)
17 it = decompress_stream(it, lzma.LZMADecompressor())
19 last_lines = collections.deque(it, 25)
20 status = [l.split(b':', 1)[1].strip()
21 for l in last_lines if l.startswith(b"Status:")]
23 return status[0].decode("ascii")
27 def do_build(source, version, architecture, server):
28 now = datetime.datetime.utcnow().replace(microsecond=0)
29 logtarget = "%s_%s_%s_%s.log.xz" % (source, version, architecture,
30 now.strftime("%Y%m%d%H%M%S"))
31 cmdline = ["ssh", server, "sh", "/dev/stdin", architecture,
32 "%s_%s" % (source, version)]
33 with open(os.path.join("logs", logtarget), "w+b") as output:
34 with open("build.sh", "rb") as instructions:
35 code = subprocess.call(cmdline, stdin=instructions, stdout=output)
37 status = scan_log_status(output)
38 print("status %s code %d" % (status, code))
39 return (now, code == 0, logtarget, status == "given-back")
42 argp = argparse.ArgumentParser()
43 argp.add_argument("server", help="machine to build on")
44 args = argp.parse_args()
45 db = sqlite3.connect("db", detect_types=sqlite3.PARSE_DECLTYPES)
46 with contextlib.closing(db.cursor()) as cur:
47 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;")
50 print("no package satisfiable")
53 source, version, architecture = row
54 print("building %s_%s for %s" % (source, version, architecture))
55 timestamp, success, filename, giveback = \
56 do_build(source, version, architecture, args.server)
57 with contextlib.closing(db.cursor()) as cur:
58 cur.execute("INSERT INTO builds (source, version, architecture, success, starttime, filename) VALUES (?, ?, ?, ?, ?, ?);",
59 (source, version, architecture, success, timestamp,
62 cur.execute("UPDATE depcheck SET giveback = 1 WHERE architecture = ?;",
66 if __name__ == "__main__":