mirror of
https://github.com/ohwgiles/laminar.git
synced 2026-10-17 08:40:54 +00:00
Compare commits
3 Commits
1.3
...
tmp-better
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ed63abd0d | ||
|
|
9db4211091 | ||
|
|
b38cbe5827 |
@@ -534,7 +534,7 @@ If `CONTEXTS` is empty or absent (or if `JOB.conf` doesn't exist), laminar will
|
||||
|
||||
## Adding environment to a context
|
||||
|
||||
Append desired environment variables to `/var/lib/laminar/cfg/contexts/CONTEXT_NAME.env`:
|
||||
Append desired environment variables to `/var/lib/laminar/cfg/contexts/CONTEXT_NAME.conf`:
|
||||
|
||||
```
|
||||
DUT_IP=192.168.3.2
|
||||
|
||||
@@ -7,7 +7,7 @@ Documentation=https://laminar.ohwg.net/docs.html
|
||||
[Service]
|
||||
User=laminar
|
||||
EnvironmentFile=-/etc/laminar.conf
|
||||
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard -v
|
||||
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
13
src/http.cpp
13
src/http.cpp
@@ -131,16 +131,9 @@ kj::Promise<void> Http::cleanupPeers(kj::Timer& timer)
|
||||
{
|
||||
return timer.afterDelay(15 * kj::SECONDS).then([&]{
|
||||
for(EventPeer* p : eventPeers) {
|
||||
// Even single threaded, if load causes this timeout to be serviced
|
||||
// before writeEvents has created a fulfiller, or if an exception
|
||||
// caused the destruction of the promise but attach(peer) hasn't yet
|
||||
// removed it from the eventPeers list, we will see a null fulfiller
|
||||
// here
|
||||
if(p->fulfiller) {
|
||||
// an empty SSE message is a colon followed by two newlines
|
||||
p->pendingOutput.push_back(":\n\n");
|
||||
p->fulfiller->fulfill();
|
||||
}
|
||||
// an empty SSE message is a colon followed by two newlines
|
||||
p->pendingOutput.push_back(":\n\n");
|
||||
p->fulfiller->fulfill();
|
||||
}
|
||||
return cleanupPeers(timer);
|
||||
}).eagerlyEvaluate(nullptr);
|
||||
|
||||
@@ -95,31 +95,11 @@ Laminar::Laminar(Server &server, Settings settings) :
|
||||
db = new Database((homePath/"laminar.sqlite").toString(true).cStr());
|
||||
// Prepare database for first use
|
||||
// TODO: error handling
|
||||
const char *create_table_stmt =
|
||||
"CREATE TABLE IF NOT EXISTS builds("
|
||||
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
|
||||
"startedAt INT, completedAt INT, result INT, output TEXT, "
|
||||
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
|
||||
"PRIMARY KEY (name, number DESC))";
|
||||
db->exec(create_table_stmt);
|
||||
|
||||
// Migrate from (name, number) primary key to (name, number DESC).
|
||||
// SQLite does not allow to alter primary key of existing table, so
|
||||
// we have to create a new table.
|
||||
db->stmt("SELECT sql LIKE '%, PRIMARY KEY (name, number))' "
|
||||
"FROM sqlite_master WHERE type = 'table' AND name = 'builds'")
|
||||
.fetch<int>([&](int has_old_index) {
|
||||
if (has_old_index) {
|
||||
LLOG(INFO, "Migrating table to the new primary key");
|
||||
db->exec("BEGIN TRANSACTION");
|
||||
db->exec("ALTER TABLE builds RENAME TO builds_old");
|
||||
db->exec(create_table_stmt);
|
||||
db->exec("INSERT INTO builds SELECT * FROM builds_old");
|
||||
db->exec("DROP TABLE builds_old");
|
||||
db->exec("COMMIT");
|
||||
}
|
||||
});
|
||||
|
||||
db->exec("CREATE TABLE IF NOT EXISTS builds("
|
||||
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
|
||||
"startedAt INT, completedAt INT, result INT, output TEXT, "
|
||||
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
|
||||
"PRIMARY KEY (name, number))");
|
||||
db->exec("CREATE INDEX IF NOT EXISTS idx_completion_time ON builds("
|
||||
"completedAt DESC)");
|
||||
|
||||
@@ -358,8 +338,9 @@ std::string Laminar::getStatus(MonitorScope scope) {
|
||||
j.set("description", desc == jobDescriptions.end() ? "" : desc->second);
|
||||
} else if(scope.type == MonitorScope::ALL) {
|
||||
j.startArray("jobs");
|
||||
db->stmt("SELECT name, number, startedAt, completedAt, result, reason "
|
||||
"FROM builds GROUP BY name HAVING number = MAX(number)")
|
||||
db->stmt("SELECT name,number,startedAt,completedAt,result,reason FROM builds b "
|
||||
"JOIN (SELECT name n,MAX(number) latest FROM builds WHERE result IS NOT NULL GROUP BY n) q "
|
||||
"ON b.name = q.n AND b.number = latest")
|
||||
.fetch<str,uint,time_t,time_t,int,str>([&](str name,uint number, time_t started, time_t completed, int result, str reason){
|
||||
j.StartObject();
|
||||
j.set("name", name);
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
<template id="run"><div style="display: grid; grid-template-rows: auto 1fr">
|
||||
<div style="padding: 15px">
|
||||
<div style="display: grid; grid-template-columns: auto 25px auto auto 1fr 400px; gap: 5px; align-items: center">
|
||||
<h2 style="white-space: nowrap"><span v-html="runIcon(job.result)"></span> <router-link :to="'jobs/'+route.params.name">{{route.params.name}}</router-link> #{{route.params.number}}</h2>
|
||||
<h2 style="white-space: nowrap"><span v-html="runIcon(job.result)"></span> {{route.params.name}} #{{route.params.number}}</h2>
|
||||
<span></span>
|
||||
<router-link :disabled="route.params.number == 1" :to="'jobs/'+route.params.name+'/'+(route.params.number-1)" tag="button">«</router-link>
|
||||
<router-link :disabled="route.params.number == latestNum" :to="'jobs/'+route.params.name+'/'+(parseInt(route.params.number)+1)" tag="button">»</router-link>
|
||||
|
||||
Reference in New Issue
Block a user