* Adjust ci status and log sync logic.

This commit is contained in:
caoyanyi
2024-03-27 11:06:11 +08:00
parent 7531a0c6e4
commit 9e412ce110
6 changed files with 187 additions and 43 deletions
+54 -9
View File
@@ -51,9 +51,9 @@ class ciModel extends model
->from(TABLE_COMPILE)->alias('compile')
->leftJoin(TABLE_JOB)->alias('job')->on('compile.job=job.id')
->leftJoin(TABLE_PIPELINE)->alias('pipeline')->on('job.server=pipeline.id')
->where('compile.status')->notIN('success, failure, create_fail, timeout, canceled')
//->where('compile.status')->notIN('success, failure, create_fail, timeout, canceled')
->where('compile.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
->beginIf($compileID)->andWhere('compile.id')->eq($compileID)->fi()
->andWhere('compile.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
->fetchAll();
$notCompileMR = $this->dao->select('jobID,id')
@@ -164,16 +164,17 @@ class ciModel extends model
public function syncCompileStatus(object $compile, int $MRID = 0): bool
{
/* Max retry times is: 3. */
if($compile->times >= 3)
{
$this->updateBuildStatus($compile, 'failure');
//if($compile->times >= 3)
//{
// $this->updateBuildStatus($compile, 'failure');
/* Added merge request result push to xuanxuan. */
if($MRID) $this->loadModel('message')->send('mr', $MRID, 'compilefail', 0);
return false;
}
// /* Added merge request result push to xuanxuan. */
// if($MRID) $this->loadModel('message')->send('mr', $MRID, 'compilefail', 0);
// return false;
//}
if($compile->engine == 'gitlab') return $this->syncGitlabTaskStatus($compile);
if($compile->engine == 'gitfox') return $this->syncGitFoxTaskStatus($compile);
$jenkinsServer = $compile->url;
$jenkinsPassword = $compile->token ? $compile->token : base64_decode($compile->password);
@@ -245,6 +246,50 @@ class ciModel extends model
return !dao::isError();
}
/**
* 同步gitfox任务状态。
* Sync gitfox task status.
*
* @param object $compile
* @access public
* @return bool
*/
public function syncGitFoxTaskStatus(object $compile): bool
{
/* The value of `$compile->pipeline` is like `'{"project":"46", "name": "test", "reference":"master"}'` in current design. */
$pipeline = json_decode($compile->pipeline);
$compile->project = isset($pipeline->project) ? (int)$pipeline->project : (int)$compile->pipeline;
$compile->pipline = zget($pipeline, 'name', '');
$now = helper::now();
$pipeline = $this->loadModel('gitfox')->apiGetSinglePipeline($compile->server, $compile->project, $compile->pipline, $compile->queue);
if(!isset($pipeline->number) || isset($pipeline->message)) /* The pipeline is not available. */
{
$this->dao->update(TABLE_JOB)->set('lastExec')->eq($now)->set('lastStatus')->eq('create_fail')->where('id')->eq($compile->job)->exec();
return false;
}
$pipeline->name = $compile->pipline;
$logs = $this->gitfox->apiGetPipelineLogs($compile->server, $compile->project, $pipeline);
$data = new stdclass;
$data->status = $pipeline->status;
$data->updateDate = $now;
$data->logs = $this->transformAnsiToHtml($logs);
$this->dao->update(TABLE_COMPILE)->data($data)->where('id')->eq($compile->id)->exec();
$this->dao->update(TABLE_JOB)->set('lastExec')->eq($now)->set('lastStatus')->eq($pipeline->status)->where('id')->eq($compile->job)->exec();
/* Send mr message by compile status. */
$relateMR = $this->dao->select('*')->from(TABLE_MR)->where('compileID')->eq($compile->id)->fetch();
if($relateMR)
{
if($data->status == 'success') $this->loadModel('action')->create('mr', $relateMR->id, 'compilePass');
if($data->status == 'failed') $this->loadModel('action')->create('mr', $relateMR->id, 'compileFail');
}
return !dao::isError();
}
/**
* 把ansi文本转换成html样式。
* Transform ansi text to html.
+66 -27
View File
@@ -228,9 +228,9 @@ class compileModel extends model
* @param int $repoID
* @param int $repoID
* @access public
* @return void
* @return bool
*/
public function syncCompile(int $repoID = 0, int $jobID = 0): void
public function syncCompile(int $repoID = 0, int $jobID = 0): bool
{
if($jobID)
{
@@ -241,22 +241,17 @@ class compileModel extends model
$jobList = $this->loadModel('job')->getList($repoID);
}
$jenkinsPairs = $this->loadModel('pipeline')->getList('jenkins');
$gitlabPairs = $this->loadModel('pipeline')->getList('gitlab');
$servers = $this->loadModel('pipeline')->getList('');
foreach($jobList as $job)
{
if($job->engine == 'jenkins')
{
$server = zget($jenkinsPairs, $job->server);
$this->syncJenkinsBuildList($server, $job);
}
else
{
$server = zget($gitlabPairs, $job->server);
$this->syncGitlabBuildList($server, $job);
}
$server = zget($servers, $job->server);
$method = "sync{$job->engine}BuildList";
$this->$method($server, $job);
$this->compileTao->updateJobLastSyncDate($job->id, helper::now());
}
return !dao::isError();
}
/**
@@ -265,21 +260,21 @@ class compileModel extends model
* @param object $jenkins
* @param object $job
* @access public
* @return void
* @return bool
*/
public function syncJenkinsBuildList(object $jenkins, object $job): void
public function syncJenkinsBuildList(object $jenkins, object $job): bool
{
if(empty($jenkins->account)) return;
if(empty($jenkins->account)) return false;
$userPWD = $this->loadModel('jenkins')->getApiUserPWD($jenkins);
/* Get build list by API. */
$urlPrefix = $this->compileTao->getJenkinsUrlPrefix($jenkins->url, $job->pipeline);
$url = $urlPrefix . 'api/json?tree=builds[id,number,result,queueId,timestamp]';
$response = common::http($url, '', array(CURLOPT_USERPWD => $userPWD));
if(!$response) return;
if(!$response) return false;
$jobInfo = json_decode($response);
if(empty($jobInfo)) return;
if(empty($jobInfo)) return false;
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->gt(0)->fetchPairs();
foreach($jobInfo->builds as $build)
@@ -290,9 +285,7 @@ class compileModel extends model
$this->compileTao->createByBuildInfo($job->name, $job->id, $build, 'jenkins');
}
$now = helper::now();
$this->compileTao->updateJobLastSyncDate($job->id, $now);
return !dao::isError();
}
/**
@@ -301,11 +294,11 @@ class compileModel extends model
* @param object $gitlab
* @param object $job
* @access public
* @return void
* @return bool
*/
public function syncGitlabBuildList(object $gitlab, object $job): void
public function syncGitlabBuildList(object $gitlab, object $job): bool
{
if(empty($gitlab->id)) return;
if(empty($gitlab->id)) return false;
$pipeline = json_decode($job->pipeline);
$projectID = isset($pipeline->project) ? $pipeline->project : '';
@@ -335,9 +328,55 @@ class compileModel extends model
if(count($builds) < 100) break;
}
return !dao::isError();
}
$now = helper::now();
$this->compileTao->updateJobLastSyncDate($job->id, $now);
/**
* Sync gitfox build list.
*
* @param object $gitfox
* @param object $job
* @access public
* @return bool
*/
public function syncGitfoxBuildList(object $gitfox, object $job): bool
{
if(empty($gitfox->id)) return false;
$pipeline = json_decode($job->pipeline);
$projectID = zget($pipeline, 'project', '');
$pipeline = zget($pipeline, 'name', '');
$apiRoot = $this->loadModel('gitfox')->getApiRoot($gitfox->id, false);
$url = sprintf($apiRoot->url, "/repos/{$projectID}/pipelines/{$pipeline}/executions");
/* Get build list by API. */
for($page = 1; true; $page++)
{
$param = $job->lastSyncDate ? '&updated_after=' . strtotime($job->lastSyncDate) : '';
$builds = json_decode(commonModel::http($url . "&page={$page}&limit=100" . $param, null, array(), $apiRoot->header));
if(!is_array($builds)) break;
if(!empty($builds))
{
$queueIDList = array();
foreach($builds as &$build)
{
$build->id = $build->number;
$queueIDList[] = $build->id;
}
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->in($queueIDList)->fetchPairs();
foreach($builds as $build)
{
if(isset($compilePairs[$build->id])) continue;
$this->compileTao->createByBuildInfo($job->name, $job->id, $build, 'gitfox');
}
}
if(count($builds) < 100) break;
}
return !dao::isError();
}
/**
+5 -5
View File
@@ -71,14 +71,14 @@ class compileTao extends compileModel
$data->status = $build->result == 'SUCCESS' ? 'success' : 'failure';
$data->createdDate = date('Y-m-d H:i:s', (int)($build->timestamp / 1000));
}
elseif($buildType == 'gitlab')
else
{
$data->queue = $build->id;
$data->status = $build->status;
$data->createdDate = date('Y-m-d H:i:s', strtotime($build->created_at));
$data->queue = !empty($build->number) ? $build->number : $build->id;
$data->status = $build->status == 'success' ? 'success' : 'failure';
$data->createdDate = date('Y-m-d H:i:s', $buildType == 'gitfox' ? $build->created : strtotime($build->created_at));
}
$data->createdBy = 'guest';
$data->createdBy = $this->app->user ? $this->app->user->account : 'guest';
$data->updateDate = $data->createdDate ?? date('Y-m-d H:i:s');
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
+59
View File
@@ -579,4 +579,63 @@ class gitfoxModel extends model
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE'), $apiRoot->header));
}
/**
* 通过api获取一个流水线。
* Get single pipline by api.
*
* @param int $gitfoxID
* @param int $projectID
* @param string $pipelineID
* @param int $executionID
* @access public
* @return object|array|null
*/
public function apiGetSinglePipeline(int $gitfoxID, int $projectID, string $pipelineID, int $executionID): object|array|null
{
$apiRoot = $this->getApiRoot($gitfoxID, false);
$url = sprintf($apiRoot->url, "/repos/{$projectID}/pipelines/{$pipelineID}/executions/{$executionID}");
return json_decode(commonModel::http($url, null, array(), $apiRoot->header));
}
/**
* 通过api获取一个流水线日志。
* Get single pipline logs by api.
*
* @param int $gitfoxID
* @param int $projectID
* @param object $pipeline
* @access public
* @return string
*/
public function apiGetPipelineLogs(int $gitfoxID, int $projectID, object $pipeline): string
{
if(empty($pipeline->stages)) return '';
$apiRoot = $this->getApiRoot($gitfoxID, false);
$url = sprintf($apiRoot->url, "/repos/{$projectID}/pipelines/{$pipeline->name}/executions/{$pipeline->number}/logs");
$log = '';
$jobUrl = isset($pipeline->params->DRONE_BUILD_LINK) ? $pipeline->params->DRONE_BUILD_LINK : '';
foreach($pipeline->stages as $stage)
{
$duration = ($stage->stopped - $stage->started) / 1000;
if(empty($stage->stopped) || $stage->started == '') $duration = '-';
$log .= "<font style='font-weight:bold'>&gt;&gt;&gt; Job: {$stage->name}, Status: {$stage->status}, Duration: $duration Sec\r\n </font>";
$log .= "Job URL: <a href=\"{$jobUrl}\" target='_blank'>{$jobUrl}</a> \r\n";
foreach($stage->steps as $step)
{
$duration = ($stage->stopped - $stage->started) / 1000;
if(empty($stage->stopped) || $stage->started == '') $duration = '-';
$log .= "<font style='font-weight:bold'>&gt;&gt;&gt; Step: {$step->name}, Status: {$step->status}, Duration: $duration Sec\r\n </font>";
$logs = json_decode(common::http("{$url}/{$stage->number}/{$step->number}", null, array(), $apiRoot->header));
if(!is_array($logs)) continue;
foreach($logs as $row) $log .= $row->out;
}
}
return $log;
}
}
+2 -2
View File
@@ -22,6 +22,7 @@ class jobTao extends jobModel
*/
protected function getServerAndPipeline(object &$job, object $repo): bool
{
$project = zget($repo, 'serviceProject', '');
if($job->engine == 'jenkins')
{
$job->server = (int)zget($job, 'jkServer', 0);
@@ -30,11 +31,10 @@ class jobTao extends jobModel
elseif($job->engine == 'gitfox')
{
$job->server = (int)zget($repo, 'serviceHost', 0);
$job->pipeline = json_encode(array('project' => $job->gitfoxpipeline, 'reference' => $job->reference));
$job->pipeline = json_encode(array('project' => $project, 'name' => $job->gitfoxpipeline, 'reference' => $job->reference));
}
elseif($job->engine == 'gitlab')
{
$project = zget($repo, 'project');
if($job->repo && !empty($repo))
{
$pipeline = $this->loadModel('gitlab')->apiGetPipeline($repo->serviceHost, $repo->serviceProject, '');
+1
View File
@@ -28,6 +28,7 @@ $repo = $repo ? $repo : new stdclass();
if(strtolower($job->engine) == 'gitlab') $job->pipeline = $this->loadModel('gitlab')->getProjectName($job->server, json_decode($job->pipeline)->project);
if(!$job->pipeline) $job->pipeline = '';
if($repo->SCM == 'GitFox') $job->pipeline = $repo->name;
if($compile and $compile->status)
{