mirror of
				https://github.com/ohwgiles/laminar.git
				synced 2025-06-13 12:54:29 +00:00 
			
		
		
		
	cleanup, dynamically present artifacts
This commit is contained in:
		
							parent
							
								
									b3cd9929b7
								
							
						
					
					
						commit
						e140221c72
					
				| @ -30,8 +30,6 @@ namespace fs = boost::filesystem; | ||||
| #include <rapidjson/stringbuffer.h> | ||||
| #include <rapidjson/writer.h> | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // rapidjson::Writer with a StringBuffer is used a lot in Laminar for
 | ||||
| // preparing JSON messages to send to Websocket clients. A small wrapper
 | ||||
| // class here reduces verbosity later for this common use case.
 | ||||
| @ -51,8 +49,6 @@ template<> Json& Json::set(const char* key, std::string value) { String(key); St | ||||
| template<> Json& Json::set(const char* key, int value) { String(key); Int(value); return *this; } | ||||
| template<> Json& Json::set(const char* key, time_t value) { String(key); Int64(value); return *this; } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| // Default values when none were supplied in $LAMINAR_CONF_FILE (/etc/laminar.conf)
 | ||||
| constexpr const char* INTADDR_RPC_DEFAULT = "unix:\0laminar"; | ||||
| @ -97,20 +93,36 @@ void Laminar::deregisterClient(LaminarClient* client) { | ||||
| } | ||||
| 
 | ||||
| bool Laminar::setParam(std::string job, int buildNum, std::string param, std::string value) { | ||||
|     auto it = activeJobs.get<1>().find(std::make_tuple(job, buildNum)); | ||||
|     if(it == activeJobs.get<1>().end()) | ||||
|         return false; | ||||
|     std::shared_ptr<Run> run = *it; | ||||
|     run->params[param] = value; | ||||
|     return true; | ||||
|     if(Run* run = activeRun(job, buildNum)) { | ||||
|         run->params[param] = value; | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Laminar::populateArtifacts(Json &j, std::string job, int num) const { | ||||
|     fs::path dir(fs::path(homeDir)/"archive"/job/std::to_string(num)); | ||||
|     if(fs::is_directory(dir)) { | ||||
|         fs::recursive_directory_iterator rdt(dir); | ||||
|         int prefixLen = (fs::path(homeDir)/"archive").string().length(); | ||||
|         int scopeLen = dir.string().length(); | ||||
|         for(fs::directory_entry e : rdt) { | ||||
|             if(!fs::is_regular_file(e)) | ||||
|                 continue; | ||||
|             j.StartObject(); | ||||
|             j.set("url", archiveUrl + e.path().string().substr(prefixLen)); | ||||
|             j.set("filename", e.path().string().substr(scopeLen+1)); | ||||
|             j.EndObject(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Laminar::sendStatus(LaminarClient* client) { | ||||
|     if(client->scope.type == MonitorScope::LOG) { | ||||
|         // If the requested job is currently in progress
 | ||||
|         auto it = activeJobs.get<1>().find(std::make_tuple(client->scope.job, client->scope.num)); | ||||
|         if(it != activeJobs.get<1>().end()) { | ||||
|             client->sendMessage((*it)->log.c_str()); | ||||
|         if(const Run* run = activeRun(client->scope.job, client->scope.num)) { | ||||
|             client->sendMessage(run->log.c_str()); | ||||
|         } else { // it must be finished, fetch it from the database
 | ||||
|             db->stmt("SELECT output FROM builds WHERE name = ? AND number = ?") | ||||
|               .bind(client->scope.job, client->scope.num) | ||||
| @ -136,22 +148,19 @@ void Laminar::sendStatus(LaminarClient* client) { | ||||
|             j.set("result", to_string(RunState(result))); | ||||
|             j.set("reason", reason); | ||||
|         }); | ||||
|         if(const Run* run = activeRun(client->scope.job, client->scope.num)) { | ||||
|             j.set("queued", run->startedAt - run->queuedAt); | ||||
|             j.set("started", run->startedAt); | ||||
|             j.set("reason", run->reason()); | ||||
|             db->stmt("SELECT completedAt - startedAt FROM builds WHERE name = ? ORDER BY completedAt DESC LIMIT 1") | ||||
|              .bind(run->name) | ||||
|              .fetch<int>([&](int etc){ | ||||
|                 j.set("etc", time(0) + etc); | ||||
|             }); | ||||
|         } | ||||
|         j.set("latestNum", int(buildNums[client->scope.job])); | ||||
|         j.startArray("artifacts"); | ||||
|         fs::path dir(fs::path(homeDir)/"archive"/client->scope.job/std::to_string(client->scope.num)); | ||||
|         if(fs::is_directory(dir)) { | ||||
|             fs::recursive_directory_iterator rdt(dir); | ||||
|             int prefixLen = (fs::path(homeDir)/"archive").string().length(); | ||||
|             int scopeLen = dir.string().length(); | ||||
|             for(fs::directory_entry e : rdt) { | ||||
|                 if(!fs::is_regular_file(e)) | ||||
|                     continue; | ||||
|                 j.StartObject(); | ||||
|                 j.set("url", archiveUrl + e.path().string().substr(prefixLen)); | ||||
|                 j.set("filename", e.path().string().substr(scopeLen+1)); | ||||
|                 j.EndObject(); | ||||
|             } | ||||
|         } | ||||
|         populateArtifacts(j, client->scope.job, client->scope.num); | ||||
|         j.EndArray(); | ||||
|     } else if(client->scope.type == MonitorScope::JOB) { | ||||
|         j.startArray("recent"); | ||||
| @ -433,10 +442,9 @@ std::shared_ptr<Run> Laminar::queueJob(std::string name, ParamMap params) { | ||||
| } | ||||
| 
 | ||||
| kj::Promise<RunState> Laminar::waitForRun(std::string name, int buildNum) { | ||||
|     auto it = activeJobs.get<1>().find(std::make_tuple(name, buildNum)); | ||||
|     if(it == activeJobs.get<1>().end()) | ||||
|         return RunState::UNKNOWN; | ||||
|     return waitForRun(it->get()); | ||||
|     if(const Run* run = activeRun(name, buildNum)) | ||||
|         return waitForRun(run); | ||||
|     return RunState::UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| kj::Promise<RunState> Laminar::waitForRun(const Run* run) { | ||||
| @ -635,7 +643,11 @@ void Laminar::runFinished(const Run * r) { | ||||
|             .set("duration", completedAt - r->startedAt) | ||||
|             .set("started", r->startedAt) | ||||
|             .set("result", to_string(r->result)) | ||||
|             .EndObject(); | ||||
|             .set("reason", r->reason()); | ||||
|     j.startArray("artifacts"); | ||||
|     populateArtifacts(j, r->name, r->build); | ||||
|     j.EndArray(); | ||||
|     j.EndObject(); | ||||
|     const char* msg = j.str(); | ||||
|     for(LaminarClient* c : clients) { | ||||
|         if(c->scope.wantsStatus(r->name, r->build)) | ||||
|  | ||||
| @ -30,6 +30,7 @@ | ||||
| typedef std::unordered_map<std::string,Node> NodeMap; | ||||
| 
 | ||||
| struct Server; | ||||
| class Json; | ||||
| 
 | ||||
| // The main class implementing the application's business logic.
 | ||||
| // It owns a Server to manage the HTTP/websocket and Cap'n Proto RPC
 | ||||
| @ -62,6 +63,13 @@ private: | ||||
|     bool stepRun(std::shared_ptr<Run> run); | ||||
|     void runFinished(const Run*); | ||||
|     bool nodeCanQueue(const Node&, const Run&) const; | ||||
|     // expects that Json has started an array
 | ||||
|     void populateArtifacts(Json& out, std::string job, int num) const; | ||||
| 
 | ||||
|     Run* activeRun(std::string name, int num) { | ||||
|         auto it = activeJobs.get<1>().find(std::make_tuple(name, num)); | ||||
|         return it == activeJobs.get<1>().end() ? nullptr : it->get(); | ||||
|     } | ||||
| 
 | ||||
|     std::list<std::shared_ptr<Run>> queuedJobs; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user