diff --git a/db/update16.1.sql b/db/update16.1.sql
new file mode 100644
index 0000000000..6644596c3b
--- /dev/null
+++ b/db/update16.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `zt_job` ADD `sonarqubeServer` mediumint(8) unsigned NOT NULL AFTER `triggerType`;
+ALTER TABLE `zt_job` ADD `projectKey` varchar(255) NOT NULL AFTER `sonarqubeServer`;
diff --git a/module/action/lang/en.php b/module/action/lang/en.php
index 93f9ddca4d..b739065286 100755
--- a/module/action/lang/en.php
+++ b/module/action/lang/en.php
@@ -329,6 +329,7 @@ $lang->action->label->finishedbychild = 'finished';
$lang->action->label->closedbychild = 'closed';
$lang->action->label->activatedbychild = 'activated';
$lang->action->label->createchild = 'activated';
+$lang->action->label->executed = 'executed';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php
index 13e034b34c..851e8f58f4 100755
--- a/module/action/lang/zh-cn.php
+++ b/module/action/lang/zh-cn.php
@@ -329,6 +329,7 @@ $lang->action->label->finishedbychild = '完成了';
$lang->action->label->closedbychild = '关闭了';
$lang->action->label->activatedbychild = '激活了';
$lang->action->label->createchild = '激活了';
+$lang->action->label->executed = '执行了';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php
index fe60b7c8c3..4918fb2d72 100644
--- a/module/group/lang/resource.php
+++ b/module/group/lang/resource.php
@@ -1384,15 +1384,19 @@ $lang->gitlab->methodOrder[145] = 'deleteTagPriv';
/* SonarQube. */
$lang->resource->sonarqube = new stdclass();
-$lang->resource->sonarqube->browse = 'browse';
-$lang->resource->sonarqube->create = 'create';
-$lang->resource->sonarqube->edit = 'edit';
-$lang->resource->sonarqube->delete = 'delete';
+$lang->resource->sonarqube->browse = 'browse';
+$lang->resource->sonarqube->create = 'create';
+$lang->resource->sonarqube->edit = 'edit';
+$lang->resource->sonarqube->delete = 'delete';
+$lang->resource->sonarqube->browseProject = 'browseProject';
+$lang->resource->sonarqube->execJob = 'execJob';
-$lang->sonarqube->methodOrder[5] = 'browse';
-$lang->sonarqube->methodOrder[10] = 'create';
-$lang->sonarqube->methodOrder[15] = 'edit';
-$lang->sonarqube->methodOrder[20] = 'delete';
+$lang->sonarqube->methodOrder[5] = 'browse';
+$lang->sonarqube->methodOrder[10] = 'create';
+$lang->sonarqube->methodOrder[15] = 'edit';
+$lang->sonarqube->methodOrder[20] = 'delete';
+$lang->sonarqube->methodOrder[25] = 'browseProject';
+$lang->sonarqube->methodOrder[30] = 'execJob';
/* merge request. */
$lang->resource->mr = new stdclass();
@@ -1738,12 +1742,12 @@ $lang->backup->methodOrder[25] = 'setting';
$lang->backup->methodOrder[30] = 'rmPHPHeader';
$lang->resource->cron = new stdclass();
-$lang->resource->cron->index = 'index';
-$lang->resource->cron->turnon = 'turnon';
-$lang->resource->cron->create = 'createAction';
-$lang->resource->cron->edit = 'edit';
-$lang->resource->cron->toggle = 'toggle';
-$lang->resource->cron->delete = 'delete';
+$lang->resource->cron->index = 'index';
+$lang->resource->cron->turnon = 'turnon';
+$lang->resource->cron->create = 'createAction';
+$lang->resource->cron->edit = 'edit';
+$lang->resource->cron->toggle = 'toggle';
+$lang->resource->cron->delete = 'delete';
$lang->resource->cron->openProcess = 'restart';
$lang->cron->methodOrder[5] = 'index';
diff --git a/module/job/control.php b/module/job/control.php
index a3f8553d47..d3ed975c64 100644
--- a/module/job/control.php
+++ b/module/job/control.php
@@ -325,6 +325,7 @@ class job extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->app->loadLang('compile');
+ $this->loadModel('action')->create('job', $id, 'executed');
return $this->send(array('result' => 'success', 'message' => sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status))));
}
diff --git a/module/repo/control.php b/module/repo/control.php
index e1d3e0c407..5d7cdff573 100644
--- a/module/repo/control.php
+++ b/module/repo/control.php
@@ -83,7 +83,8 @@ class repo extends control
$repoID = $this->repo->saveState(0, $objectID);
if($this->viewType !== 'json') $this->commonAction($repoID, $objectID);
- $repoList = $this->repo->getList(0, '', $orderBy);
+ $repoList = $this->repo->getList(0, '', $orderBy);
+ $sonarRepoList = $this->loadModel('sonarqube')->getSonarqubeByRepo(array_keys($repoList));
/* Pager. */
$this->app->loadClass('pager', $static = true);
@@ -95,11 +96,12 @@ class repo extends control
$this->view->position[] = $this->lang->repo->common;
$this->view->position[] = $this->lang->repo->browse;
- $this->view->orderBy = $orderBy;
- $this->view->objectID = $objectID;
- $this->view->pager = $pager;
- $this->view->repoList = empty($repoList) ? $repoList: $repoList[$pageID - 1];;
- $this->view->products = $this->loadModel('product')->getPairs();
+ $this->view->orderBy = $orderBy;
+ $this->view->objectID = $objectID;
+ $this->view->pager = $pager;
+ $this->view->repoList = empty($repoList) ? $repoList: $repoList[$pageID - 1];;
+ $this->view->products = $this->loadModel('product')->getPairs();
+ $this->view->sonarRepoList = $sonarRepoList;
$this->display();
}
diff --git a/module/repo/model.php b/module/repo/model.php
index d1302ee9a2..4a3245d85c 100644
--- a/module/repo/model.php
+++ b/module/repo/model.php
@@ -424,7 +424,7 @@ class repoModel extends model
/* Convert to id by url. */
$this->loadModel('gitlab');
- $url = strtolower($url);
+ $url = str_replace('https://', 'http://', strtolower($url));
$matches = array();
foreach($gitlabs as $gitlabID => $gitlab)
{
@@ -435,7 +435,8 @@ class repoModel extends model
$projects = $this->gitlab->apiGetProjects($gitlabID);
foreach($projects as $project)
{
- if((!$isSSH and strtolower($project->http_url_to_repo) == $url) or ($isSSH and strtolower($project->ssh_url_to_repo) == $url))
+ $urlToRepo = str_replace('https://', 'http://', strtolower($project->http_url_to_repo));
+ if((!$isSSH and $urlToRepo == $url) or ($isSSH and strtolower($project->ssh_url_to_repo) == $url))
{
$matched->gitlab = $gitlabID;
$matched->project = $project->id;
diff --git a/module/repo/view/maintain.html.php b/module/repo/view/maintain.html.php
index f4f083953d..33ea5cdc56 100644
--- a/module/repo/view/maintain.html.php
+++ b/module/repo/view/maintain.html.php
@@ -27,7 +27,7 @@
repo->name); ?> |
repo->product); ?> |
repo->path; ?> |
- actions; ?> |
+ actions; ?> |
@@ -59,6 +59,11 @@
common::printIcon('gitlab', 'createWebhook', "repoID=$repo->id", '', 'list', 'change', 'hiddenwin');
common::printIcon('gitlab', 'importIssue', "repo={$repo->id}", '', 'list', 'link');
}
+ if(isset($sonarRepoList[$repo->id]))
+ {
+ $jobID = $sonarRepoList[$repo->id]->id;
+ common::printIcon('sonarqube', 'execJob', "jobID=$jobID", '', 'list', 'sonarqube', 'hiddenwin');
+ }
common::printIcon('repo', 'delete', "repoID=$repo->id&objectID=$objectID", '', 'list', 'trash', 'hiddenwin');
?>
diff --git a/module/sonarqube/config.php b/module/sonarqube/config.php
new file mode 100644
index 0000000000..32f0451daf
--- /dev/null
+++ b/module/sonarqube/config.php
@@ -0,0 +1,5 @@
+sonarqube = new stdclass();
+
+$config->sonarqube->create = new stdclass();
+$config->sonarqube->create->requiredFields = 'name,url,account,password';
diff --git a/module/sonarqube/control.php b/module/sonarqube/control.php
index c8b4cc6a84..dec4397ee5 100644
--- a/module/sonarqube/control.php
+++ b/module/sonarqube/control.php
@@ -53,4 +53,63 @@ class sonarqube extends control
}
echo html::select('projectKey', $projectPairs, '', "class='form-control chosen' required");
}
+
+ /**
+ * create a sonarqube.
+ *
+ * @access public
+ * @return void
+ */
+ public function create()
+ {
+ if($_POST)
+ {
+ $this->checkToken();
+ $sonarqubeID = $this->loadModel('pipeline')->create('sonarqube');
+
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+ $actionID = $this->loadModel('action')->create('sonarqube', $sonarqubeID, 'created');
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
+ }
+
+ $this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->createServer;
+
+ $this->display();
+ }
+
+ /**
+ * Check post info.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function checkToken()
+ {
+ $sonarqube = fixer::input('post')->get();
+ $this->dao->update('sonarqube')->data($sonarqube)->batchCheck($this->config->sonarqube->create->requiredFields, 'notempty');
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+ if(strpos($sonarqube->url, 'http') !== 0) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->sonarqube->hostError))));
+
+ /* Check name and url unique. */
+ $isExist = $this->dao->select('*')->from(TABLE_PIPELINE)->where("name='{$sonarqube->name}' or url='{$sonarqube->url}'")->fetch();
+ if($isExist) return $this->send(array('result' => 'fail', 'message' => $this->lang->sonarqube->repeatError));
+
+ $token = base64_encode("{$sonarqube->account}:{$sonarqube->password}");
+ $result = $this->sonarqube->apiValidate($sonarqube->url, $token);
+
+ if(!isset($result->valid) or !$result->valid) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->sonarqube->validError))));
+ $this->post->set('token', $token);
+ }
+
+ /**
+ * Exec job.
+ *
+ * @param int $jobID
+ * @access public
+ * @return void
+ */
+ public function execJob($jobID)
+ {
+ echo $this->fetch('job', 'exec', "jobID=$jobID");
+ }
}
diff --git a/module/sonarqube/css/create.css b/module/sonarqube/css/create.css
new file mode 100644
index 0000000000..f30cf17aeb
--- /dev/null
+++ b/module/sonarqube/css/create.css
@@ -0,0 +1 @@
+.table-form .c-name {width: 130px;}
diff --git a/module/sonarqube/lang/en.php b/module/sonarqube/lang/en.php
index 5ac24fa38a..c562bdbdb1 100644
--- a/module/sonarqube/lang/en.php
+++ b/module/sonarqube/lang/en.php
@@ -8,3 +8,26 @@ $lang->sonarqube->edit = 'Edit SonarQube';
$lang->sonarqube->delete = 'Delete SonarQube';
$lang->sonarqube->confirmDelete = 'Do you want to delete this SonarQube server?';
$lang->sonarqube->serverFail = 'Connect to SonarQube server failed, please check the SonarQube server.';
+$lang->sonarqube->browseProject = "SonarQube Project List";
+$lang->sonarqube->execJob = "Exec SonarQube Job";
+
+$lang->sonarqube->id = 'ID';
+$lang->sonarqube->name = "{$lang->sonarqube->common} Name";
+$lang->sonarqube->url = 'URL';
+$lang->sonarqube->account = 'Username';
+$lang->sonarqube->password = 'Password';
+$lang->sonarqube->token = 'Token';
+$lang->sonarqube->defaultProject = 'Default Project';
+$lang->sonarqube->private = 'MD5 Verify';
+
+$lang->sonarqube->createServer = 'Create SonarQube Server';
+$lang->sonarqube->desc = 'Description';
+$lang->sonarqube->createSuccess = 'Create success';
+
+$lang->sonarqube->placeholder = new stdclass;
+$lang->sonarqube->placeholder->name = '';
+$lang->sonarqube->placeholder->url = "Please fill in the access address of the SonarQube Server homepage, as: https://sonarqube.zentao.net.";
+
+$lang->sonarqube->repeatError = 'Server name or server address already exists!';
+$lang->sonarqube->validError = 'Sonarqube user authority authentication failed!';
+$lang->sonarqube->hostError = "Invalid SonarQube service address.";
diff --git a/module/sonarqube/lang/zh-cn.php b/module/sonarqube/lang/zh-cn.php
index 215e9b4502..306938acfc 100644
--- a/module/sonarqube/lang/zh-cn.php
+++ b/module/sonarqube/lang/zh-cn.php
@@ -8,3 +8,26 @@ $lang->sonarqube->edit = '编辑SonarQube';
$lang->sonarqube->delete = '删除SonarQube';
$lang->sonarqube->confirmDelete = '确认删除该SonarQube吗?';
$lang->sonarqube->serverFail = '连接SonarQube服务器异常,请检查SonarQube服务器。';
+$lang->sonarqube->browseProject = "SonarQube项目列表";
+$lang->sonarqube->execJob = "执行SonarQube任务";
+
+$lang->sonarqube->id = 'ID';
+$lang->sonarqube->name = "{$lang->sonarqube->common}名称";
+$lang->sonarqube->url = '服务地址';
+$lang->sonarqube->account = '用户名';
+$lang->sonarqube->password = '密码';
+$lang->sonarqube->token = 'Token';
+$lang->sonarqube->defaultProject = '默认项目';
+$lang->sonarqube->private = 'MD5验证';
+
+$lang->sonarqube->createServer = '添加SonarQube服务器';
+$lang->sonarqube->desc = '描述';
+$lang->sonarqube->createSuccess = "创建成功";
+
+$lang->sonarqube->placeholder = new stdclass;
+$lang->sonarqube->placeholder->name = '';
+$lang->sonarqube->placeholder->url = "请填写SonarQube Server首页的访问地址,如:https://sonarqube.zentao.net。";
+
+$lang->sonarqube->repeatError = "服务器名称或服务器地址已存在!";
+$lang->sonarqube->validError = "SonarQube 用户权限认证失败!";
+$lang->sonarqube->hostError = "无效的SonarQube服务地址。";
diff --git a/module/sonarqube/model.php b/module/sonarqube/model.php
index 9c546dda95..13a6ecccc5 100644
--- a/module/sonarqube/model.php
+++ b/module/sonarqube/model.php
@@ -38,4 +38,37 @@ class sonarqubeModel extends model
{
return $this->loadModel('pipeline')->getPairs('sonarqube');
}
+
+ /**
+ * Get sonarqube api base url and header by id.
+ *
+ * @param int $id
+ * @access public
+ * @return array
+ */
+ public function getApiBase($id)
+ {
+ $sonarqube = $this->loadModel('pipeline')->getByID($id);
+ if(!$sonarqube) return '';
+
+ $url = rtrim($sonarqube->url, '/') . '/api/%s';
+ $header[] = 'Authorization: Basic ' . $sonarqube->token;
+
+ return array($url, $header);
+ }
+
+ /**
+ * check sonarqube valid
+ *
+ * @param string $host
+ * @param string $token
+ * @access public
+ * @return array
+ */
+ public function apiValidate($host, $token)
+ {
+ $url = rtrim($host, '/') . "/api/authentication/validate";
+ $header = 'Authorization: Basic ' . $token;
+ return json_decode(commonModel::http($url, null, array(), $header));
+ }
}
diff --git a/module/sonarqube/view/create.html.php b/module/sonarqube/view/create.html.php
new file mode 100644
index 0000000000..15253bb19e
--- /dev/null
+++ b/module/sonarqube/view/create.html.php
@@ -0,0 +1,51 @@
+
+ * @package sonarqube
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+
sonarqube->createServer;?>
+
+
+
+
+
+