* add commit result interface.

This commit is contained in:
wangyidong
2020-04-01 13:35:58 +08:00
parent 7749555f92
commit 990e33afcc
13 changed files with 319 additions and 51 deletions
+5
View File
@@ -1,2 +1,7 @@
ALTER TABLE `zt_job` ADD `frame` varchar(20) COLLATE 'utf8_general_ci' NOT NULL AFTER `repo`;
ALTER TABLE `zt_compile` ADD `testtask` mediumint unsigned NULL AFTER `atTime`;
ALTER TABLE `zt_case` ADD `auto` varchar(10) COLLATE 'utf8_general_ci' NOT NULL DEFAULT 'no' AFTER `type`;
ALTER TABLE `zt_case` ADD `frame` varchar(10) COLLATE 'utf8_general_ci' NOT NULL AFTER `auto`;
ALTER TABLE `zt_testresult` ADD `job` mediumint unsigned NOT NULL AFTER `version`;
ALTER TABLE `zt_testresult` ADD `compile` mediumint unsigned NOT NULL AFTER `job`;
ALTER TABLE `zt_job` ADD `product` mediumint(8) unsigned NOT NULL AFTER `repo`;
+80
View File
@@ -76,4 +76,84 @@ class ci extends control
echo 'success';
}
}
/**
* Commit result from ztf or unit.
*
* @access public
* @return void
*/
public function commitResult()
{
$post = file_get_contents('php://input');
$post = json_decode($post);
$testType = $post->TestType;
$productID = $post->ProductId;
$taskID = $post->TaskId;
$zentaoData = $post->ZentaoData;
parse_str($zentaoData, $params);
$this->loadModel('testtask');
$compileID = zget($params, 'compile', 0);
$jobID = 0;
if($compileID)
{
$compile = $this->dao->select('t1.*, t2.jkJob,t2,product,t2.frame,t3.name as jenkinsName,t3.url,t3.account,t3.token,t3.password')->from(TABLE_COMPILE)->alias('t1')
->leftJoin(TABLE_JOB)->alias('t2')->on('t1.job=t2.id')
->leftJoin(TABLE_JENKINS)->alias('t3')->on('t2.jkHost=t3.id')
->where('t1.id')->eq($compileID)
->fetch();
$jobID = $compile->job;
if(empty($productID)) $productID = $compile->product;
if($compile->status != 'success' and $compile->status != 'fail' and $compile->status != 'create_fail' and $compile->status != 'timeout')
{
$this->loadModel('compile')->checkStatus($compile);
}
$this->dao->update(TABLE_COMPILE)->set('testtask')->eq($taskID)->where('id')->eq($compile->id)->exec();
}
if(!empty($taskID))
{
$testtask = $this->testtask->getById($taskID);
$productID = $testtask->product;
}
else
{
$lastProject = $this->dao->select('t1.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.product')->eq($productID)
->andWhere('t2.deleted')->eq(0)
->orderBy('project desc')
->limit(1)
->fetch('project');
$testtask = new stdclass();
$testtask->product = $productID;
$testtask->name = sprintf($this->lang->testtask->unitTitleTemplate, date('Y-m-d H:i:s'));
$testtask->owner = $this->app->user->account;
$testtask->project = $lastProject;
$testtask->build = 'trunk';
$testtask->begin = date('Y-m-d');
$testtask->end = date('Y-m-d', time() + 24 * 3600);
$testtask->status = 'done';
$this->dao->insert(TABLE_TESTTASK)->data($testtask)->exec();
$taskID = $this->dao->lastInsertId();
$this->loadModel('action')->create('testtask', $taskID, 'opened');
}
if($testType == 'unit')
{
$data = $this->testtask->buildDataFromUnit($post->UnitCaseResults, $productID, $jobID, $compileID);
}
elseif($testType == 'ztf')
{
$data = $this->testtask->buildDataFromZtf($post->ZtfCaseResults, $productID, $jobID, $compileID);
}
$taskID = $this->testtask->saveUnit($taskID, $data['suites'], $data['cases'], $data['results'], $data['suiteNames'], $data['caseTitles']);
}
}
+54 -45
View File
@@ -42,60 +42,69 @@ class ciModel extends model
->andWhere('t1.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
->fetchAll();
foreach($compiles as $compile)
foreach($compiles as $compile) $this->checkStatus($compile);
}
/**
* Check status.
*
* @param object $compile
* @access public
* @return void
*/
public function checkStatus($compile)
{
$jenkinsServer = $compile->url;
$jenkinsUser = $compile->account;
$jenkinsPassword = $compile->token ? $compile->token : base64_decode($compile->password);
$jenkinsAuth = '://' . $jenkinsUser . ':' . $jenkinsPassword . '@';
$jenkinsServer = str_replace('://', $jenkinsAuth, $jenkinsServer);
$queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $compile->queue);
$response = common::http($queueUrl);
if(strripos($response, "404") > -1)
{
$jenkinsServer = $compile->url;
$jenkinsUser = $compile->account;
$jenkinsPassword = $compile->token ? $compile->token : base64_decode($compile->password);
$jenkinsAuth = '://' . $jenkinsUser . ':' . $jenkinsPassword . '@';
$jenkinsServer = str_replace('://', $jenkinsAuth, $jenkinsServer);
$queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $compile->queue);
$response = common::http($queueUrl);
if(strripos($response, "404") > -1)
$infoUrl = sprintf("%s/job/%s/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=%s]", $jenkinsServer, $compile->jkJob, $compile->queue);
$response = common::http($infoUrl);
if($response)
{
$infoUrl = sprintf("%s/job/%s/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=%s]", $jenkinsServer, $compile->jkJob, $compile->queue);
$response = common::http($infoUrl);
if($response)
$buildInfo = simplexml_load_string($response);
$buildNumber = strtolower($buildInfo->number);
$result = strtolower($buildInfo->result);
$this->updateBuildStatus($compile, $result);
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $compile->jkJob, $buildNumber);
$response = common::http($logUrl);
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
}
}
else
{
$queueInfo = json_decode($response);
if(!empty($queueInfo->executable))
{
$buildUrl = $queueInfo->executable->url . 'api/json?pretty=true';
$buildUrl = str_replace('://', $jenkinsAuth, $buildUrl);
$response = common::http($buildUrl);
$buildInfo = json_decode($response);
if($buildInfo->building)
{
$buildInfo = simplexml_load_string($response);
$buildNumber = strtolower($buildInfo->number);
$result = strtolower($buildInfo->result);
$this->updateBuildStatus($compile, 'building');
}
else
{
$result = strtolower($buildInfo->result);
$this->updateBuildStatus($compile, $result);
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $compile->jkJob, $buildNumber);
$logUrl = $buildInfo->url . 'logText/progressiveText/api/json';
$logUrl = str_replace('://', $jenkinsAuth, $logUrl);
$response = common::http($logUrl);
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
}
}
else
{
$queueInfo = json_decode($response);
if(!empty($queueInfo->executable))
{
$buildUrl = $queueInfo->executable->url . 'api/json?pretty=true';
$buildUrl = str_replace('://', $jenkinsAuth, $buildUrl);
$response = common::http($buildUrl);
$buildInfo = json_decode($response);
if($buildInfo->building)
{
$this->updateBuildStatus($compile, 'building');
}
else
{
$result = strtolower($buildInfo->result);
$this->updateBuildStatus($compile, $result);
$logUrl = $buildInfo->url . 'logText/progressiveText/api/json';
$logUrl = str_replace('://', $jenkinsAuth, $logUrl);
$response = common::http($logUrl);
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
}
}
}
}
}
+1
View File
@@ -162,6 +162,7 @@ class commonModel extends model
if($module == 'sso' and $method == 'gettodolist') return true;
if($module == 'block' and $method == 'main' and isset($_GET['hash'])) return true;
if($module == 'file' and $method == 'read') return true;
if($module == 'ci' and $method == 'commitresult') return true;
if($this->loadModel('user')->isLogon() or ($this->app->company->guest and $this->app->user->account == 'guest'))
{
+1
View File
@@ -118,6 +118,7 @@ class compileModel extends model
$tagData = new stdclass();
$tagData->PARAM_TAG = $compile->tag;
$tagData->PARAM_ZENTAODATA = "compile={$compile->id}";
$buildUrl = $this->getBuildUrl($job);
$build = new stdclass();
+2
View File
@@ -84,6 +84,7 @@ class job extends control
}
$this->view->repoPairs = $repoPairs;
$this->view->repoTypes = $repoTypes;
$this->view->products = array(0 => '') + $this->loadModel('product')->getPairs();
$this->view->jkHostList = $this->loadModel('jenkins')->getPairs();
$this->display();
@@ -127,6 +128,7 @@ class job extends control
$this->view->repoTypes = $repoTypes;
$this->view->repoType = zget($repoTypes, $job->repo, 'Git');
$this->view->job = $job;
$this->view->products = array(0 => '') + $this->loadModel('product')->getPairs();
$this->view->jkHostList = $this->loadModel('jenkins')->getPairs();
$this->view->jkJobs = $this->jenkins->getTasks($job->jkHost);
+1
View File
@@ -12,6 +12,7 @@ $lang->job->buildTag = '打标签';
$lang->job->id = 'ID';
$lang->job->name = '名称';
$lang->job->repo = '代码库';
$lang->job->product = '关联产品';
$lang->job->svnDir = 'SVN监控路径';
$lang->job->jenkins = 'Jenkins';
$lang->job->jkHost = 'Jenkins服务器';
+9 -3
View File
@@ -265,13 +265,19 @@ class jobModel extends model
$build->atTime = $job->atTime;
}
$build->queue = $this->loadModel('ci')->sendRequest($buildUrl, $data);
$build->status = $build->queue ? 'created' : 'create_fail';
$build->createdBy = $this->app->user->account;
$build->createdDate = $now;
$build->updateDate = $now;
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
$this->dao->update(TABLE_JOB)->set('lastExec')->eq($now)->set('lastStatus')->eq($build->status)->where('id')->eq($job->id)->exec();
$compileID = $this->dao->lastInsertId();
$data->PARAM_ZENTAODATA = "compile={$compileID}";
$compile = new stdclass();
$compile->queue = $this->loadModel('ci')->sendRequest($buildUrl, $data);
$compile->status = $compile->queue ? 'created' : 'create_fail';
$this->dao->update(TABLE_COMPILE)->data($compile)->where('id')->eq($compileID)->exec();
$this->dao->update(TABLE_JOB)->set('lastExec')->eq($now)->set('lastStatus')->eq($compile->status)->where('id')->eq($job->id)->exec();
return $build->status;
}
+4
View File
@@ -34,6 +34,10 @@
<th><?php echo $lang->job->repo; ?></th>
<td><?php echo html::select('repo', $repoPairs, '', "class='form-control chosen'"); ?></td>
</tr>
<tr>
<th><?php echo $lang->job->product; ?></th>
<td><?php echo html::select('product', $products, '', "class='form-control chosen'"); ?></td>
</tr>
<tr>
<th><?php echo $lang->job->frame; ?></th>
<td><?php echo html::select('frame', $lang->job->frameList, '', "class='form-control chosen'"); ?></td>
+4
View File
@@ -36,6 +36,10 @@
<td><?php echo html::select('repo', $repoPairs, $job->repo, "class='form-control chosen'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->job->product; ?></th>
<td><?php echo html::select('product', $products, $job->product, "class='form-control chosen'"); ?></td>
</tr>
<tr>
<th><?php echo $lang->job->frame; ?></th>
<td><?php echo html::select('frame', $lang->job->frameList, $job->frame, "class='form-control chosen'"); ?></td>
+1
View File
@@ -118,6 +118,7 @@ $lang->testtask->noTesttask = '暂时没有测试单';
$lang->testtask->checkLinked = '请检查测试单的产品是否与项目相关联';
$lang->testtask->noImportData = '导入的XML没有解析出数据。';
$lang->testtask->unitXMLFormat = '请选择Junit XML 格式的文件。';
$lang->testtask->unitTitleTemplate = "%s 单元测试";
$lang->testtask->assignedToMe = '指派给我';
$lang->testtask->allCases = '所有用例';
+156 -2
View File
@@ -1570,6 +1570,8 @@ class testtaskModel extends model
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
$case->auto = 'unit';
$case->frame = 'junit';
$attributes = $matchNode->attributes();
foreach($nameFields as $field)
@@ -1606,7 +1608,7 @@ class testtaskModel extends model
$case->lastRunDate = $now;
$case->lastRunResult = $result->caseResult;
$titles[$suiteIndex][] = $case->title;
$caseTitles[$suiteIndex][] = $case->title;
$cases[$suiteIndex][$caseIndex] = $case;
$results[$suiteIndex][$caseIndex] = $result;
}
@@ -1617,6 +1619,23 @@ class testtaskModel extends model
unlink($fileName);
if(dao::isError()) return false;
return $this->saveUnit($testtaskID, $suites, $cases, $results, $suiteNames, $caseTitles);
}
/**
* Save unit.
*
* @param int $testtaskID
* @param array $suites
* @param array $cases
* @param array $results
* @param array $suiteNames
* @param array $caseTitles
* @access public
* @return int
*/
public function saveUnit($testtaskID, $suites, $cases, $results, $suiteNames = array(), $caseTitles = array())
{
/* Import cases and link task and insert result. */
$this->loadModel('action');
$existSuites = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('name')->in($suiteNames)->andWhere('product')->eq($productID)->andWhere('type')->eq('unit')->andWhere('deleted')->eq(0)->fetchPairs('name', 'id');
@@ -1654,7 +1673,12 @@ class testtaskModel extends model
foreach($cases[$suiteIndex] as $i => $case)
{
if(!isset($existCases[$case->title]))
if(isset($case->id))
{
$caseID = $case->id;
$this->dao->update(TABLE_CASE)->data($case)->where('id')->eq($caseID)->exec();
}
elseif(!isset($existCases[$case->title]))
{
$this->dao->insert(TABLE_CASE)->data($case)->exec();
$caseID = $this->dao->lastInsertID();
@@ -1696,4 +1720,134 @@ class testtaskModel extends model
return $testtaskID;
}
public function buildDataFromUnit($caseResults, $productID, $jobID, $compileID)
{
$now = helper::now();
$cases = array();
$results = array();
$suites = array();
$caseTitles = array();
$suiteNames = array();
$suiteIndex = 0;
foreach($caseResults as $caseIndex => $caseResult)
{
$suite = '';
if(isset($caseResult->TestSuite) and !isset($suiteNames[$suite->name]))
{
$suite = new stdclass();
$suite->product = $productID;
$suite->name = $caseResult->TestSuite;
$suite->type = 'unit';
$suite->addedBy = $this->app->user->account;
$suite->addedDate = $now;
$suiteNames[$suite->name] = $suite->name;
$suiteIndex ++;
}
if(!isset($suites[$suiteIndex])) $suites[$suiteIndex] = $suite;
$case = new stdclass();
$case->product = $productID;
$case->title = $caseResult->TestSuite . ' ' . $caseResult->Title;
$case->pri = 3;
$case->type = 'unit';
$case->stage = 'unittest';
$case->status = 'normal';
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
$case->auto = 'unit';
$case->frame = $caseResult->TestFrame;
$result = new stdclass();
$result->case = 0;
$result->version = 1;
$result->caseResult = 'pass';
$result->lastRunner = $this->app->user->account;
$result->job = $jobID;
$result->compile = $compileID;
$result->date = $now;
$result->stepResults[0]['result'] = 'pass';
$result->stepResults[0]['real'] = '';
if(!empty($caseResult->Failure))
{
$result->caseResult = 'fail';
$result->stepResults[0]['result'] = 'fail';
$result->stepResults[0]['real'] = $caseResult->Failure->Desc;
}
$result->stepResults = serialize($result->stepResults);
$case->lastRunner = $this->app->user->account;
$case->lastRunDate = $now;
$case->lastRunResult = $result->caseResult;
$caseTitles[$suiteIndex][] = $case->title;
$cases[$suiteIndex][$caseIndex] = $case;
$results[$suiteIndex][$caseIndex] = $result;
}
return array('suites' => $suites, 'cases' => $cases, 'results' => $results, 'suiteNames' => $suiteNames, 'caseTitles' => $caseTitles);
}
public function buildDataFromZtf($caseResults, $productID, $jobID, $compileID)
{
$now = helper::now();
$cases = array();
$results = array();
$suites = array();
$caseTitles = array();
$suiteNames = array();
$suiteIndex = 0;
foreach($caseResults as $caseIndex => $caseResult)
{
$suite = '';
if(!isset($suites[$suiteIndex])) $suites[$suiteIndex] = $suite;
$case = new stdclass();
$case->product = $productID;
$case->title = $caseResult->Title;
$case->pri = 3;
$case->type = 'unit';
$case->stage = 'unittest';
$case->status = 'normal';
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
$case->auto = 'ztf';
$case->frame = $caseResult->TestFrame;
$result = new stdclass();
$result->case = 0;
$result->version = 1;
$result->caseResult = 'pass';
$result->lastRunner = $this->app->user->account;
$result->job = $jobID;
$result->compile = $compileID;
$result->date = $now;
$result->stepResults[0]['result'] = 'pass';
$result->stepResults[0]['real'] = '';
if(!empty($caseResult->Steps))
{
$result->stepResults = array();
$stepStatus = 'pass';
foreach($caseResult->Steps as $i => $step)
{
$result->stepResults[$i]['result'] = $step->Status ? 'pass' : 'fail';
$result->stepResults[$i]['real'] = $step->Status ? '' : $step->CheckPoints[0]->Actual;
if(!$step->Status) $stepStatus = 'fail';
}
$result->caseResult = $stepStatus;
}
$result->stepResults = serialize($result->stepResults);
$case->lastRunner = $this->app->user->account;
$case->lastRunDate = $now;
$case->lastRunResult = $result->caseResult;
$caseTitles[$suiteIndex][] = $case->title;
$cases[$suiteIndex][$caseIndex] = $case;
$results[$suiteIndex][$caseIndex] = $result;
}
return array('suites' => $suites, 'cases' => $cases, 'results' => $results, 'suiteNames' => $suiteNames, 'caseTitles' => $caseTitles);
}
}
+1 -1
View File
@@ -71,7 +71,7 @@
</tr>
<tr>
<th><?php echo $lang->testtask->name;?></th>
<td colspan='2'><?php echo html::input('name', '', "class='form-control'");?></td>
<td colspan='2'><?php echo html::input('name', sprintf($lang->testtask->unitTitleTemplate, date('Y-m-d H:i:s')), "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->testtask->desc;?></th>