@ -100,8 +100,33 @@ Laminar::Laminar(Server &server, Settings settings) :
" 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, "
" sourceBranch TEXT, sourceVersion TEXT, "
" PRIMARY KEY (name, number DESC)) " ;
db - > exec ( create_table_stmt ) ;
// Update 'sourceBranch' if not existing;
db - > stmt (
" SELECT COUNT(*) AS CNT FROM pragma_table_info('builds') "
" WHERE name='sourceBranch' " )
. fetch < int > ( [ & ] ( int has_source_branch ) {
if ( ! has_source_branch )
{
LLOG ( WARNING , " Updating database to contain 'sourceBranch' " ) ;
db - > exec ( " ALTER TABLE 'builds' ADD COLUMN 'sourceBranch' TEXT " ) ;
}
} ) ;
// Update 'sourceVersion' if not existing;
db - > stmt (
" SELECT COUNT(*) AS CNT FROM pragma_table_info('builds') "
" WHERE name='sourceVersion' " )
. fetch < int > ( [ & ] ( int has_source_version ) {
if ( ! has_source_version )
{
LLOG ( WARNING , " Updating database to contain 'sourceVersion' " ) ;
db - > exec ( " ALTER TABLE 'builds' ADD COLUMN 'sourceVersion' TEXT " ) ;
}
} ) ;
// Migrate from (name, number) primary key to (name, number DESC).
// SQLite does not allow to alter primary key of existing table, so
@ -250,17 +275,22 @@ std::string Laminar::getStatus(MonitorScope scope) {
j . set ( " time " , time ( nullptr ) ) ;
j . startObject ( " data " ) ;
if ( scope . type = = MonitorScope : : RUN ) {
db - > stmt ( " SELECT queuedAt,startedAt,completedAt,result,reason, parentJob,parentBuild,q.lr IS NOT NULL,q.lr FROM builds "
db - > stmt ( " SELECT queuedAt,startedAt,completedAt,result,reason, sourceBranch,sourceVersion, parentJob,parentBuild,q.lr IS NOT NULL,q.lr FROM builds "
" LEFT JOIN (SELECT name n, MAX(number), completedAt-startedAt lr FROM builds WHERE result IS NOT NULL GROUP BY n) q ON q.n = name "
" WHERE name = ? AND number = ? " )
. bind ( scope . job , scope . num )
. fetch < time_t , time_t , time_t , int , std : : string , std : : string , uint , uint , uint > ( [ & ] ( time_t queued , time_t started , time_t completed , int result , std : : string reason , std : : string parentJob , uint parentBuild , uint lastRuntimeKnown , uint lastRuntime ) {
. fetch < time_t , time_t , time_t , int , std : : string , std : : string , std : : string , std : : string , uint , uint , uint > (
[ & ] ( time_t queued , time_t started , time_t completed , int result ,
std : : string reason , std : : string sourceBranch , std : : string sourceVersion ,
std : : string parentJob , uint parentBuild , uint lastRuntimeKnown , uint lastRuntime ) {
j . set ( " queued " , queued ) ;
j . set ( " started " , started ) ;
if ( completed )
j . set ( " completed " , completed ) ;
j . set ( " result " , to_string ( completed ? RunState ( result ) : started ? RunState : : RUNNING : RunState : : QUEUED ) ) ;
j . set ( " reason " , reason ) ;
j . set ( " sourceBranch " , sourceBranch ) ;
j . set ( " sourceVersion " , sourceVersion ) ;
j . startObject ( " upstream " ) . set ( " name " , parentJob ) . set ( " num " , parentBuild ) . EndObject ( 2 ) ;
if ( lastRuntimeKnown )
j . set ( " etc " , started + lastRuntime ) ;
@ -287,18 +317,20 @@ std::string Laminar::getStatus(MonitorScope scope) {
order_by = " (completedAt-startedAt) " + direction + " , number DESC " ;
else
order_by = " number DESC " ;
std : : string stmt = " SELECT number,startedAt,completedAt,result,reason FROM builds "
std : : string stmt = " SELECT number,startedAt,completedAt,result,reason ,sourceBranch,sourceVersion FROM builds "
" WHERE name = ? AND result IS NOT NULL ORDER BY "
+ order_by + " LIMIT ?,? " ;
db - > stmt ( stmt . c_str ( ) )
. bind ( scope . job , scope . page * runsPerPage , runsPerPage )
. fetch < uint , time_t , time_t , int , str > ( [ & ] ( uint build , time_t started , time_t completed , int result , str reas on) {
. fetch < uint , time_t , time_t , int , str , str , str > ( [ & ] ( uint build , time_t started , time_t completed , int result , str reas on, str sourceBranch , str sourceVersi on) {
j . StartObject ( ) ;
j . set ( " number " , build )
. set ( " completed " , completed )
. set ( " started " , started )
. set ( " result " , to_string ( RunState ( result ) ) )
. set ( " reason " , reason )
. set ( " sourceBranch " , sourceBranch )
. set ( " sourceVersion " , sourceVersion )
. EndObject ( ) ;
} ) ;
j . EndArray ( ) ;
@ -323,6 +355,8 @@ std::string Laminar::getStatus(MonitorScope scope) {
j . set ( " started " , run - > startedAt ) ;
j . set ( " result " , to_string ( RunState : : RUNNING ) ) ;
j . set ( " reason " , run - > reason ( ) ) ;
j . set ( " sourceBranch " , run - > sourceBranch ( ) ) ;
j . set ( " sourceVersion " , run - > sourceVersion ( ) ) ;
j . EndObject ( ) ;
}
j . EndArray ( ) ;
@ -333,6 +367,8 @@ std::string Laminar::getStatus(MonitorScope scope) {
j . set ( " number " , run - > build ) ;
j . set ( " result " , to_string ( RunState : : QUEUED ) ) ;
j . set ( " reason " , run - > reason ( ) ) ;
j . set ( " sourceBranch " , run - > sourceBranch ( ) ) ;
j . set ( " sourceVersion " , run - > sourceVersion ( ) ) ;
j . EndObject ( ) ;
}
}
@ -358,9 +394,12 @@ 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 "
db - > stmt ( " SELECT name, number, startedAt, completedAt, result, reason, "
" sourceBranch, sourceVersion "
" FROM builds GROUP BY name HAVING number = MAX(number) " )
. 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 , str > ( [ & ] ( str name , uint number ,
time_t started , time_t completed , int result , str reason ,
str sourceBranch , str sourceVersion ) {
j . StartObject ( ) ;
j . set ( " name " , name ) ;
j . set ( " number " , number ) ;
@ -368,6 +407,8 @@ std::string Laminar::getStatus(MonitorScope scope) {
j . set ( " started " , started ) ;
j . set ( " completed " , completed ) ;
j . set ( " reason " , reason ) ;
j . set ( " sourceBranch " , sourceBranch ) ;
j . set ( " sourceVersion " , sourceVersion ) ;
j . EndObject ( ) ;
} ) ;
j . EndArray ( ) ;
@ -387,8 +428,11 @@ std::string Laminar::getStatus(MonitorScope scope) {
j . EndObject ( ) ;
} else { // Home page
j . startArray ( " recent " ) ;
db - > stmt ( " SELECT name,number,node,queuedAt,startedAt,completedAt,result,reason FROM builds WHERE completedAt IS NOT NULL ORDER BY completedAt DESC LIMIT 20 " )
. fetch < str , uint , str , time_t , time_t , time_t , int , str > ( [ & ] ( str name , uint build , str context , time_t queued , time_t started , time_t completed , int result , str reason ) {
db - > stmt ( " SELECT name,number,node,queuedAt,startedAt,completedAt,result, "
" reason,sourceBranch,sourceVersion FROM builds WHERE completedAt IS NOT NULL ORDER BY completedAt DESC LIMIT 20 " )
. fetch < str , uint , str , time_t , time_t , time_t , int , str , str , str >
( [ & ] ( str name , uint build , str context , time_t queued , time_t started ,
time_t completed , int result , str reason , str sourceBranch , str sourceVersion ) {
j . StartObject ( ) ;
j . set ( " name " , name )
. set ( " number " , build )
@ -398,6 +442,8 @@ std::string Laminar::getStatus(MonitorScope scope) {
. set ( " completed " , completed )
. set ( " result " , to_string ( RunState ( result ) ) )
. set ( " reason " , reason )
. set ( " sourceBranch " , sourceBranch )
. set ( " sourceVersion " , sourceVersion )
. EndObject ( ) ;
} ) ;
j . EndArray ( ) ;
@ -620,8 +666,10 @@ std::shared_ptr<Run> Laminar::queueJob(std::string name, ParamMap params, bool f
else
queuedJobs . push_back ( run ) ;
db - > stmt ( " INSERT INTO builds(name,number,queuedAt,parentJob,parentBuild,reason) VALUES(?,?,?,?,?,?) " )
. bind ( run - > name , run - > build , run - > queuedAt , run - > parentName , run - > parentBuild , run - > reason ( ) )
db - > stmt ( " INSERT INTO builds(name,number,queuedAt,parentJob,parentBuild,reason,sourceBranch,sourceVersion) VALUES(?,?,?,?,?,?,?,?) " )
. bind ( run - > name , run - > build , run - > queuedAt , run - > parentName ,
run - > parentBuild , run - > reason ( ) ,
run - > sourceBranch ( ) , run - > sourceVersion ( ) )
. exec ( ) ;
// notify clients
@ -633,6 +681,8 @@ std::shared_ptr<Run> Laminar::queueJob(std::string name, ParamMap params, bool f
. set ( " result " , to_string ( RunState : : QUEUED ) )
. set ( " queueIndex " , frontOfQueue ? 0 : ( queuedJobs . size ( ) - 1 ) )
. set ( " reason " , run - > reason ( ) )
. set ( " sourceBranch " , run - > sourceBranch ( ) )
. set ( " sourceVersion " , run - > sourceVersion ( ) )
. EndObject ( ) ;
http - > notifyEvent ( j . str ( ) , name . c_str ( ) ) ;
@ -722,7 +772,10 @@ bool Laminar::tryStartRun(std::shared_ptr<Run> run, int queueIndex) {
. set ( " queued " , run - > queuedAt )
. set ( " started " , run - > startedAt )
. set ( " number " , run - > build )
. set ( " reason " , run - > reason ( ) ) ;
. set ( " reason " , run - > reason ( ) )
. set ( " sourceBranch " , run - > sourceBranch ( ) )
. set ( " sourceVersion " , run - > sourceVersion ( ) ) ;
db - > stmt ( " SELECT completedAt - startedAt FROM builds WHERE name = ? ORDER BY completedAt DESC LIMIT 1 " )
. bind ( run - > name )
. fetch < uint > ( [ & ] ( uint etc ) {
@ -767,9 +820,13 @@ void Laminar::handleRunFinished(Run * r) {
std : : swap ( maybeZipped , zipped ) ;
}
}
db - > stmt ( " UPDATE builds SET completedAt = ?, result = ?, output = ?, outputLen = ? WHERE name = ? AND number = ? " )
. bind ( completedAt , int ( r - > result ) , maybeZipped , logsize , r - > name , r - > build )
r - > digestBuildEnv ( * fsHome ) ;
db - > stmt ( " UPDATE builds SET completedAt = ?, result = ?, output = ?, outputLen = ? "
" , sourceBranch = ?, sourceVersion = ? WHERE name = ? AND number = ? " )
. bind ( completedAt , int ( r - > result ) , maybeZipped , logsize ,
r - > sourceBranch ( ) , r - > sourceVersion ( ) , r - > name , r - > build )
. exec ( ) ;
// notify clients
@ -782,7 +839,9 @@ void Laminar::handleRunFinished(Run * r) {
. set ( " completed " , completedAt )
. set ( " started " , r - > startedAt )
. set ( " result " , to_string ( r - > result ) )
. set ( " reason " , r - > reason ( ) ) ;
. set ( " reason " , r - > reason ( ) )
. set ( " sourceBranch " , r - > sourceBranch ( ) )
. set ( " sourceVersion " , r - > sourceVersion ( ) ) ;
j . startArray ( " artifacts " ) ;
populateArtifacts ( j , r - > name , r - > build ) ;
j . EndArray ( ) ;