2 # SPDX-License-Identifier: GPL-2.0+
14 from common import decompress_stream, yield_lines, yield_chunks
16 def scan_log_status(filelike):
17 it = yield_chunks(filelike)
18 it = decompress_stream(it, lzma.LZMADecompressor())
20 last_lines = collections.deque(it, 25)
21 status = [l.split(b':', 1)[1].strip()
22 for l in last_lines if l.startswith(b"Status:")]
24 return status[0].decode("ascii")
28 def do_build(source, version, architecture, server):
29 now = datetime.datetime.utcnow().replace(microsecond=0)
30 logtarget = "%s_%s_%s_%s.log.xz" % (source, version, architecture,
31 now.strftime("%Y%m%d%H%M%S"))
32 cmdline = ["ssh", server, "sh", "/dev/stdin", architecture,
33 "%s_%s" % (source, version)]
34 logname = os.path.join("logs", logtarget)
35 with open(logname, "w+b") as output:
36 with open("build.sh", "rb") as instructions:
37 code = subprocess.call(cmdline, stdin=instructions, stdout=output)
39 status = scan_log_status(output)
43 raise RuntimeError("ssh failed")
44 print("status %s code %d" % (status, code))
45 return (now, code == 0, logtarget, status == "given-back")
48 argp = argparse.ArgumentParser()
49 argp.add_argument("server", help="machine to build on")
50 args = argp.parse_args()
51 db = sqlite3.connect("db", detect_types=sqlite3.PARSE_DECLTYPES)
52 with contextlib.closing(db.cursor()) as cur:
54 SELECT d.source, d.version, d.architecture, r.id
56 JOIN buildrequests AS r
57 ON d.architecture = ifnull(r.architecture, d.architecture)
58 AND d.source = r.source
60 ON d.architecture = depcheck.architecture
61 WHERE d.satisfiable = 1 AND depcheck.giveback = 0
62 ORDER BY r.priority DESC, r.requesttime ASC, random()
67 SELECT source, version, depstate.architecture, NULL
68 FROM depstate JOIN depcheck
69 ON depstate.architecture = depcheck.architecture
70 WHERE satisfiable = 1 AND giveback = 0
71 ORDER BY random() LIMIT 1;""")
74 print("no package satisfiable")
77 source, version, architecture, requestid = row
78 print("building %s_%s for %s%s" %
79 (source, version, architecture,
80 "" if requestid is None else " (request %d)" % requestid))
81 timestamp, success, filename, giveback = \
82 do_build(source, version, architecture, args.server)
83 with contextlib.closing(db.cursor()) as cur:
84 cur.execute("INSERT INTO builds (source, version, architecture, success, starttime, filename) VALUES (?, ?, ?, ?, ?, ?);",
85 (source, version, architecture, success, timestamp,
87 if requestid is not None:
88 cur.execute("DELETE FROM buildrequests WHERE id = ?;",
91 cur.execute("UPDATE depcheck SET giveback = 1 WHERE architecture = ?;",
95 if __name__ == "__main__":