Files
EasySoft-ZenTaoPMS/module/ci/model.php
aaronchen2k 165fb141d1 remove
2020-01-22 14:10:50 +08:00

387 lines
14 KiB
PHP

<?php
/**
* The model file of ci module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chenqi <chenqi@cnezsoft.com>
* @package product
* @version $Id: $
* @link http://www.zentao.net
*/
class ciModel extends model
{
/**
* Get ci task list.
*
* @param string $orderBy
* @param object $pager
* @param bool $decode
* @access public
* @return array
*/
public function listJob($orderBy = 'id_desc', $pager = null, $decode = true)
{
$list = $this->dao->
select('t1.*, t2.name repoName, t3.name as jenkinsName')->from(TABLE_CI_TASK)->alias('t1')
->leftJoin(TABLE_REPO)->alias('t2')->on('t1.repo=t2.id')
->leftJoin(TABLE_JENKINS)->alias('t3')->on('t1.jenkins=t3.id')
->where('t1.deleted')->eq('0')
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
return $list;
}
/**
* Get a ci task by id.
*
* @param int $id
* @access public
* @return object
*/
public function getJobByID($id)
{
$jenkins = $this->dao->select('*')->from(TABLE_CI_TASK)->where('id')->eq($id)->fetch();
return $jenkins;
}
/**
* Create a ci task.
*
* @access public
* @return bool
*/
public function createJob()
{
$task = fixer::input('post')
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->get();
$this->dao->insert(TABLE_CI_TASK)->data($task)
->batchCheck($this->config->citask->requiredFields, 'notempty')
->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'cron', "cronExpression", 'notempty')
->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'custom', "scheduleDay,scheduleTime,scheduleInterval", 'notempty')
->autoCheck()
->exec();
if ($task->triggerType === 'schedule') {
$taskId = $this->dao->lastInsertID();
if ($task->scheduleType == 'custom') {
$arr = explode(":", $task->scheduleTime);
$hour = $arr[0];
$min = $arr[1];
if ($task->scheduleDay == 'everyDay') {
$days = '1-7';
} else if ($task->scheduleDay == 'workDay') {
$days = '1-5';
}
$cron = (object)array('m' => $min, 'h' => $hour, 'dom' => '*', 'mon' => '*',
'dow' => $days . '/' . $task->scheduleInterval, 'command' => 'moduleName=citask&methodName=exe&parm=' . $taskId,
'remark' => ($this->lang->citask->extTask . $taskId), 'type' => 'zentao',
'buildin' => '-1', 'status' => 'normal', 'lastTime' => '0000-00-00 00:00:00');
$this->dao->insert(TABLE_CRON)->data($cron)->exec();
} else if ($task->scheduleType == 'cron') {
$arr = explode(' ', $task->cronExpression);
if (count($arr) >= 6) {
$cron = (object)array('m' => $arr[1], 'h' => $arr[2], 'dom' => $arr[3], 'mon' => $arr[4],
'dow' => $arr[5], 'command' => 'moduleName=citask&methodName=exe&parm=' . $taskId,
'remark' => ($this->lang->citask->extTask . $taskId), 'type' => 'zentao',
'buildin' => '-1', 'status' => 'normal', 'lastTime' => '0000-00-00 00:00:00');
$this->dao->insert(TABLE_CRON)->data($cron)->exec();
}
}
}
return true;
}
/**
* Update a ci task.
*
* @param int $id
* @access public
* @return bool
*/
public function updateJob($id)
{
$task = fixer::input('post')
->add('editedBy', $this->app->user->account)
->add('editedDate', helper::now())
->get();
$this->dao->update(TABLE_CI_TASK)->data($task)
->batchCheck($this->config->citask->requiredFields, 'notempty')
->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'cron', "cronExpression", 'notempty')
->batchCheckIF($task->triggerType === 'schedule' && $task->scheduleType == 'custom', "scheduleDay,scheduleTime,scheduleInterval", 'notempty')
->autoCheck()
->where('id')->eq($id)
->exec();
if ($task->triggerType === 'schedule') {
$command = 'moduleName=citask&methodName=exe&parm=' . $id;
if ($task->scheduleType == 'custom') {
$arr = explode(":", $task->scheduleTime);
$hour = $arr[0];
$min = $arr[1];
$taskId = $this->dao->lastInsertID();
if ($task->scheduleDay == 'everyDay') {
$days = '1-7';
} else if ($task->scheduleDay == 'workDay') {
$days = '2-6';
}
$this->dao->update(TABLE_CRON)
->set('m')->eq($min)
->set('h')->eq($hour)
->set('dom')->eq('*')
->set('mon')->eq('*')
->set('dow')->eq($days . '/' . $task->scheduleInterval)
->set('lastTime')->eq('0000-00-00 00:00:00')
->where('command')->eq($command)->exec();
} else if ($task->scheduleType == 'cron') {
$arr = explode(' ', $task->cronExpression);
if (count($arr) >= 6) {
$this->dao->update(TABLE_CRON)
->set('m')->eq($arr[1])
->set('h')->eq($arr[2])
->set('dom')->eq($arr[3])
->set('mon')->eq($arr[4])
->set('dow')->eq($arr[5])
->set('lastTime')->eq('0000-00-00 00:00:00')
->where('command')->eq($command)->exec();
}
}
}
return true;
}
/**
* Execute ci task.
*
* @param int $id
* @access public
* @return bool
*/
public function exeJob($taskID)
{
$po = $this->dao->select('task.id taskId, task.name taskName, task.repo, task.jenkinsTask, jenkins.name jenkinsName,jenkins.serviceUrl,jenkins.credentials')
->from(TABLE_CI_TASK)->alias('task')
->leftJoin(TABLE_JENKINS)->alias('jenkins')->on('task.jenkins=jenkins.id')
->where('task.id')->eq($taskID)
->fetch();
$credentials = $this->loadModel('cicredentials')->getByID($po->credentials); // jenkins must use a token or account credentials
if ($credentials->type === 'token') {
$jenkinsTokenOrPassword = $credentials->token;
} else if ($credentials->type === 'account') {
$jenkinsTokenOrPassword = $credentials->password;
}
$jenkinsUser = $credentials->username;
$jenkinsServer = $po->serviceUrl;
$r = '://' . $jenkinsUser . ':' . $jenkinsTokenOrPassword . '@';
$jenkinsServer = str_replace('://', $r, $jenkinsServer);
$buildUrl = sprintf('%s/job/%s/build/api/json', $jenkinsServer, $po->jenkinsTask);
$po->queueItem = $this->sendBuildRequest($buildUrl);
$this->saveCibuild($po);
return !dao::isError();
}
/**
* Get jenkins build list.
*
* @param int $taskID
* @param string $orderBy
* @param object $pager
* @param bool $decode
* @access public
* @return array
*/
public function listBuild($taskID, $orderBy = 'id_desc', $pager = null, $decode = true)
{
$list = $this->dao->
select('id, name, status, createdDate')->from(TABLE_CI_BUILD)
->where('deleted')->eq('0')
->andWhere('citask')->eq($taskID)
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
return $list;
}
/**
* Get jenkins build logs.
*
* @param int $buildID
* @access public
* @return array
*/
public function getBuildByID($buildID)
{
$build = $this->dao->select('*')->from(TABLE_CI_BUILD)->where('id')->eq($buildID)->fetch();
return $build;
}
/**
* Save build to db.
*
* @param object $task
* @access public
* @return bool
*/
public function saveBuild($task)
{
$build = new stdClass();
$build->citask = $task->taskId;
$build->name = $task->taskName;
$build->queueItem = $task->queueItem;
$build->status = 'created';
$build->createdBy = $this->app->user->account;
$build->createdDate = helper::now();
$this->dao->insert(TABLE_CI_BUILD)->data($build)->exec();
}
/**
* Update ci build status.
*
* @param object $task
* @access public
* @return bool
*/
public function updateBuildStatus($build, $status)
{
$this->dao->update(TABLE_CI_BUILD)->set('status')->eq($status)->where('id')->eq($build->id)->exec();
$this->dao->update(TABLE_CI_TASK)
->set('lastExec')->eq(helper::now())
->set('lastStatus')->eq($status)
->where('id')->eq($build->citask)->exec();
}
/**
* Send a request to jenkins to check build status.
*
* @access public
* @return bool
*/
public function checkBuildStatus()
{
$pos = $this->dao->select('build.*, task.jenkinsTask, jenkins.name jenkinsName,jenkins.serviceUrl,jenkins.credentials')
->from(TABLE_CI_BUILD)->alias('build')
->leftJoin(TABLE_CI_TASK)->alias('task')->on('build.citask=task.id')
->leftJoin(TABLE_JENKINS)->alias('jenkins')->on('task.jenkins=jenkins.id')
->where('build.status')->ne('success')
->andWhere('build.status')->ne('fail')
->fetchAll();
foreach($pos as $po) {
$credentials = $this->loadModel('cicredentials')->getByID($po->credentials); // jenkins must use a token or account credentials
if ($credentials->type === 'token') {
$jenkinsTokenOrPassword = $credentials->token;
} else if ($credentials->type === 'account') {
$jenkinsTokenOrPassword = $credentials->password;
}
$jenkinsUser = $credentials->username;
$jenkinsServer = $po->serviceUrl;
$r = '://' . $jenkinsUser . ':' . $jenkinsTokenOrPassword . '@';
$jenkinsServer = str_replace('://', $r, $jenkinsServer);
$queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $po->queueItem);
$response = common::http($queueUrl);
if (strripos($response,"404") > -1) { // queue已过期
$infoUrl = sprintf('%s/job/%s/%s/api/json', $jenkinsServer, $po->jenkinsTask, $po->queueItem);
$response = common::http($infoUrl);
$buildInfo = json_decode($response);
$result = strtolower($buildInfo->result);
$this->updateCibuildStatus($po, $result);
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $po->jenkinsTask, $po->queueItem);
$response = common::http($logUrl);
$logs = json_decode($response);
$this->dao->update(TABLE_CI_BUILD)->set('logs')->eq($response)->where('id')->eq($po->id)->exec();
} else {
$queueInfo = json_decode($response);
if (!empty($queueInfo->executable)) {
$buildUrl = $queueInfo->executable->url . 'api/json?pretty=true';
$buildUrl = str_replace('://', $r, $buildUrl);
$response = common::http($buildUrl);
$buildInfo = json_decode($response);
if ($buildInfo->building) {
$this->updateCibuildStatus($po, 'building');
} else {
$result = strtolower($buildInfo->result);
$this->updateCibuildStatus($po, $result);
$logUrl = $buildInfo->url . 'logText/progressiveText/api/json';
$logUrl = str_replace('://', $r, $logUrl);
$response = common::http($logUrl);
$logs = json_decode($response);
$this->dao->update(TABLE_CI_BUILD)->set('logs')->eq($response)->where('id')->eq($po->id)->exec();
}
}
}
}
}
public function sendBuildRequest($url)
{
if(!extension_loaded('curl')) return json_encode(array('result' => 'fail', 'message' => $lang->error->noCurlExt));
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($curl, CURLOPT_USERAGENT, 'Sae T OAuth2 v0.1');
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_ENCODING, "");
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl, CURLOPT_HEADER, FALSE);
$headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR'];
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE);
//
curl_setopt ($curl , CURLOPT_HEADER, 1 );
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, new stdClass());
$response = curl_exec($curl);
$errors = curl_error($curl);
curl_close($curl);
if ( preg_match ( "!Location: .*item/(.*)/!", $response , $matches ) ) {
return $matches[1];
}
return '';
}
}