mirror of
https://github.com/ohwgiles/laminar.git
synced 2026-10-18 00:54:25 +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
|
## 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
|
DUT_IP=192.168.3.2
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Documentation=https://laminar.ohwg.net/docs.html
|
|||||||
[Service]
|
[Service]
|
||||||
User=laminar
|
User=laminar
|
||||||
EnvironmentFile=-/etc/laminar.conf
|
EnvironmentFile=-/etc/laminar.conf
|
||||||
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard -v
|
ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/laminard
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
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([&]{
|
return timer.afterDelay(15 * kj::SECONDS).then([&]{
|
||||||
for(EventPeer* p : eventPeers) {
|
for(EventPeer* p : eventPeers) {
|
||||||
// Even single threaded, if load causes this timeout to be serviced
|
// an empty SSE message is a colon followed by two newlines
|
||||||
// before writeEvents has created a fulfiller, or if an exception
|
p->pendingOutput.push_back(":\n\n");
|
||||||
// caused the destruction of the promise but attach(peer) hasn't yet
|
p->fulfiller->fulfill();
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cleanupPeers(timer);
|
return cleanupPeers(timer);
|
||||||
}).eagerlyEvaluate(nullptr);
|
}).eagerlyEvaluate(nullptr);
|
||||||
|
|||||||
@@ -95,31 +95,11 @@ Laminar::Laminar(Server &server, Settings settings) :
|
|||||||
db = new Database((homePath/"laminar.sqlite").toString(true).cStr());
|
db = new Database((homePath/"laminar.sqlite").toString(true).cStr());
|
||||||
// Prepare database for first use
|
// Prepare database for first use
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
const char *create_table_stmt =
|
db->exec("CREATE TABLE IF NOT EXISTS builds("
|
||||||
"CREATE TABLE IF NOT EXISTS builds("
|
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
|
||||||
"name TEXT, number INT UNSIGNED, node TEXT, queuedAt INT, "
|
"startedAt INT, completedAt INT, result INT, output TEXT, "
|
||||||
"startedAt INT, completedAt INT, result INT, output TEXT, "
|
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
|
||||||
"outputLen INT, parentJob TEXT, parentBuild INT, reason TEXT, "
|
"PRIMARY KEY (name, number))");
|
||||||
"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 INDEX IF NOT EXISTS idx_completion_time ON builds("
|
db->exec("CREATE INDEX IF NOT EXISTS idx_completion_time ON builds("
|
||||||
"completedAt DESC)");
|
"completedAt DESC)");
|
||||||
|
|
||||||
@@ -358,8 +338,9 @@ std::string Laminar::getStatus(MonitorScope scope) {
|
|||||||
j.set("description", desc == jobDescriptions.end() ? "" : desc->second);
|
j.set("description", desc == jobDescriptions.end() ? "" : desc->second);
|
||||||
} else if(scope.type == MonitorScope::ALL) {
|
} else if(scope.type == MonitorScope::ALL) {
|
||||||
j.startArray("jobs");
|
j.startArray("jobs");
|
||||||
db->stmt("SELECT name, number, startedAt, completedAt, result, reason "
|
db->stmt("SELECT name,number,startedAt,completedAt,result,reason FROM builds b "
|
||||||
"FROM builds GROUP BY name HAVING number = MAX(number)")
|
"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){
|
.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.StartObject();
|
||||||
j.set("name", name);
|
j.set("name", name);
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
<template id="run"><div style="display: grid; grid-template-rows: auto 1fr">
|
<template id="run"><div style="display: grid; grid-template-rows: auto 1fr">
|
||||||
<div style="padding: 15px">
|
<div style="padding: 15px">
|
||||||
<div style="display: grid; grid-template-columns: auto 25px auto auto 1fr 400px; gap: 5px; align-items: center">
|
<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>
|
<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 == 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>
|
<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