summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.py28
-rw-r--r--schema.sql6
-rw-r--r--webapp.py58
3 files changed, 84 insertions, 8 deletions
diff --git a/build.py b/build.py
index 876e21b..8e1d763 100755
--- a/build.py
+++ b/build.py
@@ -45,20 +45,42 @@ def main():
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;")
+ cur.execute("""
+ SELECT d.source, d.version, d.architecture, r.rowid
+ FROM depstate AS d
+ JOIN buildrequests AS r
+ ON d.architecture = ifnull(r.architecture, d.architecture)
+ AND d.source = r.source
+ JOIN depcheck
+ ON d.architecture = depcheck.architecture
+ WHERE d.satisfiable = 1 AND depcheck.giveback = 0
+ ORDER BY r.priority DESC, random() LIMIT 1;""")
row = cur.fetchone()
+ if not row:
+ cur.execute("""
+ SELECT source, version, depstate.architecture, NULL
+ 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))
+ source, version, architecture, requestid = row
+ print("building %s_%s for %s%s" %
+ (source, version, architecture,
+ "" if requestid is None else " (request %d)" % requestid))
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 requestid is not None:
+ cur.execute("DELETE FROM buildrequests WHERE rowid = ?;",
+ (requestid,))
if giveback:
cur.execute("UPDATE depcheck SET giveback = 1 WHERE architecture = ?;",
(architecture,))
diff --git a/schema.sql b/schema.sql
index e76dde0..62ce9c4 100644
--- a/schema.sql
+++ b/schema.sql
@@ -30,3 +30,9 @@ CREATE TABLE builds (
success BOOLEAN NOT NULL CHECK (success in (0, 1)),
starttime TIMESTAMP NOT NULL,
filename TEXT NOT NULL);
+
+CREATE TABLE buildrequests (
+ source TEXT NOT NULL,
+ architecture TEXT,
+ requesttime TIMESTAMP NOT NULL,
+ priority INTEGER NOT NULL DEFAULT 0);
diff --git a/webapp.py b/webapp.py
index bf82bda..d37dbda 100644
--- a/webapp.py
+++ b/webapp.py
@@ -104,9 +104,9 @@ footer {
</li>
</ul>
</section>
- {%- if builds -%}
- <section>
- <h3>Cross builds</h3>
+ <section>
+ <h3>Cross builds</h3>
+ {%- if builds -%}
<table>
<thead>
<tr>
@@ -134,8 +134,21 @@ footer {
{%- endfor -%}
</tbody>
</table>
- </section>
- {%- endif -%}
+ {%- else -%}
+ <p>No build performed yet.</p>
+ {%- endif -%}
+ <form method="POST" action="{{ url_for("request_schedule")|e }}">
+ <input type="submit" name="schedule" value="cross build" />
+ {{ sourcepackage|e }} for
+ <input type="hidden" name="source" value="{{ sourcepackage|e }}" />
+ <select name="architecture">
+ <option value="any">any</option>
+ {%- for architecture in architectures -%}
+ <option value="{{ architecture|e }}">{{ architecture|e }}</option>
+ {%- endfor -%}
+ </select>
+ </form>
+ </section>
<footer>
<h3>Details about this service</h3>
<ul>
@@ -147,6 +160,18 @@ footer {
</html>
"""
+schedule_template = """<!DOCTYPE html>
+<html>
+ <body>
+ <p>Scheduled a build of {{ request.form["source"]|e }}
+ {%- if request.form["architecture"] != "any" %}
+ for {{ request.form["architecture"]|e -}}
+ {%- endif %}.
+ <p>
+ </body>
+</html>
+"""
+
@app.template_filter("sqltimestamp")
def sqltimestamp_filter(s):
strptime = datetime.datetime.strptime
@@ -228,3 +253,26 @@ def show_log(filename):
mimetype="text/plain")
except FileNotFoundError:
raise werkzeug.exceptions.NotFound()
+
+
+@app.route("/schedule", methods=["POST"])
+def request_schedule():
+ source = flask.request.form["source"]
+ architecture = flask.request.form["architecture"]
+ with db.engine.connect() as conn:
+ query = sqlalchemy.text("""
+ SELECT 1 FROM depstate WHERE source = :source;""")
+ if not conn.execute(query, source=source).first():
+ raise werkzeug.exceptions.BadRequest()
+ if architecture == "any":
+ architecture = None
+ else:
+ query = sqlalchemy.text("""
+ SELECT 1 FROM depcheck WHERE architecture = :architecture;""")
+ if not conn.execute(query, architecture=architecture).first():
+ raise werkzeug.exceptions.BadRequest()
+ query = sqlalchemy.text("""
+ INSERT INTO buildrequests (source, architecture, requesttime)
+ VALUES (:source, :architecture, datetime('now'));""")
+ conn.execute(query, source=source, architecture=architecture)
+ return flask.render_template_string(schedule_template)