diff --git a/config/zentaopms.php b/config/zentaopms.php
index b7b187ba3a..50a3eaf890 100644
--- a/config/zentaopms.php
+++ b/config/zentaopms.php
@@ -292,6 +292,9 @@ $config->objectTables['kanbanlane'] = TABLE_KANBANLANE;
$config->objectTables['kanbanorder'] = TABLE_KANBANORDER;
$config->objectTables['kanbangroup'] = TABLE_KANBANGROUP;
$config->objectTables['kanbancard'] = TABLE_KANBANCARD;
+$config->objectTables['sonarqube'] = TABLE_PIPELINE;
+$config->objectTables['gitlab'] = TABLE_PIPELINE;
+$config->objectTables['jebkins'] = TABLE_PIPELINE;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme');
diff --git a/db/update16.2.sql b/db/update16.2.sql
index 120a2d3779..75c4536ef7 100644
--- a/db/update16.2.sql
+++ b/db/update16.2.sql
@@ -1,3 +1,6 @@
ALTER TABLE `zt_kanbanspace` ADD `type` varchar(50) NOT NULL AFTER `name`;
UPDATE `zt_kanbanspace` SET `type` = 'cooperation';
ALTER TABLE `zt_kanban` ADD `performable` enum ('0', '1') NOT NULL DEFAULT '0' AFTER `archived`;
+
+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`;
\ No newline at end of file
diff --git a/module/action/config.php b/module/action/config.php
index c40a551519..940dbfaf97 100755
--- a/module/action/config.php
+++ b/module/action/config.php
@@ -40,6 +40,7 @@ $config->action->objectNameFields['kanbanspace'] = 'name';
$config->action->objectNameFields['kanbanregion'] = 'name';
$config->action->objectNameFields['kanban'] = 'name';
$config->action->objectNameFields['kanbancard'] = 'name';
+$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->commonImgSize = 870;
@@ -55,4 +56,4 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
-$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,';
+$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,';
diff --git a/module/action/lang/en.php b/module/action/lang/en.php
index 93f9ddca4d..bde1c19b3d 100755
--- a/module/action/lang/en.php
+++ b/module/action/lang/en.php
@@ -134,6 +134,8 @@ $lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
$lang->action->objectTypes['kanbanlane'] = 'Kanban Lane';
$lang->action->objectTypes['kanbancolumn'] = 'Kanban Column';
$lang->action->objectTypes['kanbancard'] = 'Kanban Card';
+$lang->action->objectTypes['sonarqube'] = 'SonarQube Server';
+$lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project';
/* Used to describe operation history. */
$lang->action->desc = new stdclass();
@@ -329,6 +331,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;
@@ -568,6 +571,22 @@ $lang->action->dynamicAction->user['loginxuanxuan'] = 'Login Desktop';
$lang->action->dynamicAction->entry['created'] = 'Add Application';
$lang->action->dynamicAction->entry['edited'] = 'Edit Application';
+$lang->action->dynamicAction->job['created'] = 'Create Job';
+$lang->action->dynamicAction->job['edited'] = 'Edit Job';
+$lang->action->dynamicAction->job['executed'] = 'Execute Job';
+$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
+$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
+
+$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
+$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
+$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
+
+$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
+
+$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
+$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
+$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
+
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
$lang->action->label->productplan = 'Plan|productplan|view|productID=%s';
diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php
index 13e034b34c..98679d3045 100755
--- a/module/action/lang/zh-cn.php
+++ b/module/action/lang/zh-cn.php
@@ -134,6 +134,8 @@ $lang->action->objectTypes['kanbanregion'] = '看板区域';
$lang->action->objectTypes['kanbanlane'] = '看板泳道';
$lang->action->objectTypes['kanbancolumn'] = '看板列';
$lang->action->objectTypes['kanbancard'] = '看板卡片';
+$lang->action->objectTypes['sonarqube'] = 'SonarQube服务器';
+$lang->action->objectTypes['sonarqubeproject'] = 'SonarQube项目';
/* 用来描述操作历史记录。*/
$lang->action->desc = new stdclass();
@@ -329,6 +331,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();
@@ -568,6 +571,22 @@ $lang->action->dynamicAction->user['loginxuanxuan'] = '登录客户端';
$lang->action->dynamicAction->entry['created'] = '添加应用';
$lang->action->dynamicAction->entry['edited'] = '编辑应用';
+$lang->action->dynamicAction->job['created'] = '创建构建任务';
+$lang->action->dynamicAction->job['edited'] = '编辑构建任务';
+$lang->action->dynamicAction->job['executed'] = '执行构建任务';
+$lang->action->dynamicAction->job['deleted'] = '删除构建任务';
+$lang->action->dynamicAction->job['undeleted'] = '还原构建任务';
+
+$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
+$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
+$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
+
+$lang->action->dynamicAction->sonarqubeproject['deleted'] = '删除SonarQube项目';
+
+$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
+$lang->action->dynamicAction->gitlab['edited'] = '设置GitLab服务器';
+$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
+
/* 用来生成相应对象的链接。*/
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
$lang->action->label->productplan = "计划|productplan|view|productID=%s";
diff --git a/module/block/view/dynamic.html.php b/module/block/view/dynamic.html.php
index 215bb804d3..51f529e8fe 100644
--- a/module/block/view/dynamic.html.php
+++ b/module/block/view/dynamic.html.php
@@ -13,6 +13,7 @@
{
$user = zget($users, $action->actor);
if($action->action == 'login' or $action->action == 'logout') $action->objectName = $action->objectLabel = '';
+ if($action->objectType == 'sonarqubeproject') $action->objectName = $action->extra;
$class = $action->major ? "class='active'" : '';
echo "
";
if($action->objectLink) printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName, $action->objectName);
diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php
index 547d96b935..fedc8779b1 100644
--- a/module/common/lang/menu.php
+++ b/module/common/lang/menu.php
@@ -386,22 +386,24 @@ $lang->qa->menuOrder[45] = 'automation';
$lang->qa->dividerMenu = ',bug,testtask,caselib,';
/* DevOps menu. */
-$lang->devops->menu = new stdclass();
-$lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|browse|repoID=%s", 'alias' => 'diff,view,revision,log,blame,showsynccommit');
-$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse", 'subModule' => 'compile,job');
-$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse");
-$lang->devops->menu->gitlab = array('link' => "GitLab|gitlab|browse", 'alias' => 'create,edit');
-$lang->devops->menu->jenkins = array('link' => "Jenkins|jenkins|browse", 'alias' => 'create,edit');
-$lang->devops->menu->maintain = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
-$lang->devops->menu->rules = array('link' => "{$lang->devops->rules}|repo|setrules");
+$lang->devops->menu = new stdclass();
+$lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|browse|repoID=%s", 'alias' => 'diff,view,revision,log,blame,showsynccommit');
+$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse", 'subModule' => 'compile,job');
+$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse");
+$lang->devops->menu->gitlab = array('link' => "GitLab|gitlab|browse", 'alias' => 'create,edit');
+$lang->devops->menu->sonarqube = array('link' => "SonarQube|sonarqube|browse");
+$lang->devops->menu->jenkins = array('link' => "Jenkins|jenkins|browse", 'alias' => 'create,edit');
+$lang->devops->menu->maintain = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
+$lang->devops->menu->rules = array('link' => "{$lang->devops->rules}|repo|setrules");
$lang->devops->menuOrder[5] = 'code';
$lang->devops->menuOrder[10] = 'compile';
$lang->devops->menuOrder[15] = 'mr';
$lang->devops->menuOrder[20] = 'gitlab';
-$lang->devops->menuOrder[25] = 'jenkins';
-$lang->devops->menuOrder[30] = 'maintain';
-$lang->devops->menuOrder[35] = 'rules';
+$lang->devops->menuOrder[25] = 'sonarqube';
+$lang->devops->menuOrder[30] = 'jenkins';
+$lang->devops->menuOrder[35] = 'maintain';
+$lang->devops->menuOrder[40] = 'rules';
/* Kanban menu. */
$lang->kanban->menu = new stdclass();
@@ -618,16 +620,18 @@ $lang->navGroup->testtask = 'qa';
$lang->navGroup->testsuite = 'qa';
$lang->navGroup->caselib = 'qa';
-$lang->navGroup->devops = 'devops';
-$lang->navGroup->repo = 'devops';
-$lang->navGroup->job = 'devops';
-$lang->navGroup->jenkins = 'devops';
-$lang->navGroup->mr = 'devops';
-$lang->navGroup->gitlab = 'devops';
-$lang->navGroup->compile = 'devops';
-$lang->navGroup->ci = 'devops';
-$lang->navGroup->svn = 'devops';
-$lang->navGroup->git = 'devops';
+$lang->navGroup->devops = 'devops';
+$lang->navGroup->repo = 'devops';
+$lang->navGroup->job = 'devops';
+$lang->navGroup->jenkins = 'devops';
+$lang->navGroup->mr = 'devops';
+$lang->navGroup->gitlab = 'devops';
+$lang->navGroup->sonarqube = 'devops';
+$lang->navGroup->sonarqubeproject = 'devops';
+$lang->navGroup->compile = 'devops';
+$lang->navGroup->ci = 'devops';
+$lang->navGroup->svn = 'devops';
+$lang->navGroup->git = 'devops';
$lang->navGroup->company = 'system';
diff --git a/module/company/view/dynamic.html.php b/module/company/view/dynamic.html.php
index ab820eed0b..d07b63407d 100644
--- a/module/company/view/dynamic.html.php
+++ b/module/company/view/dynamic.html.php
@@ -66,10 +66,14 @@
objectType == 'meeting') $tab = $action->project ? "data-app='project'" : "data-app='my'";?>
objectName))
+ if(empty($action->objectName) and $action->objectID)
{
echo '#' . $action->objectID;
}
+ elseif(empty($action->objectID) and $action->extra)
+ {
+ echo $action->extra;
+ }
elseif(empty($action->objectLink))
{
echo $action->objectName;
@@ -79,8 +83,10 @@
echo html::a($action->objectLink, $action->objectName, '', $tab);
}
?>
+ objectID):?>
objectID;?>
+
diff --git a/module/gitlab/view/browse.html.php b/module/gitlab/view/browse.html.php
index b682227146..137e6d80b0 100644
--- a/module/gitlab/view/browse.html.php
+++ b/module/gitlab/view/browse.html.php
@@ -32,7 +32,7 @@
recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
- | gitlab->id);?> |
+ gitlab->id);?> |
gitlab->name);?> |
gitlab->url);?> |
actions;?> |
diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php
index c28fbfb220..0a0706d26a 100644
--- a/module/group/lang/resource.php
+++ b/module/group/lang/resource.php
@@ -1384,6 +1384,24 @@ $lang->gitlab->methodOrder[135] = 'browseTag';
$lang->gitlab->methodOrder[140] = 'browseTagPriv';
$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->browseProject = 'browseProject';
+$lang->resource->sonarqube->deleteProject = 'deleteProject';
+$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[25] = 'browseProject';
+$lang->sonarqube->methodOrder[35] = 'deleteProject';
+$lang->sonarqube->methodOrder[40] = 'execJob';
+
/* merge request. */
$lang->resource->mr = new stdclass();
$lang->resource->mr->create = 'create';
@@ -1728,12 +1746,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 961f71c525..332b0a695a 100644
--- a/module/job/control.php
+++ b/module/job/control.php
@@ -88,6 +88,8 @@ class job extends control
}
return $this->send(array('result' => 'fail', 'message' => $errors));
}
+
+ $this->loadModel('action')->create('job', $jobID, 'created');
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $jobID));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
@@ -120,7 +122,8 @@ class job extends control
$this->view->repoTypes = $repoTypes;
$this->view->products = array(0 => '') + $this->loadModel('product')->getProductPairsByProject($this->projectID);
- $this->view->jenkinsServerList = array('' => '') + $this->loadModel('jenkins')->getPairs();
+ $this->view->jenkinsServerList = array('' => '') + $this->loadModel('jenkins')->getPairs();
+ $this->view->sonarqubeServerList = array('') + $this->loadModel('pipeline')->getPairs('sonarqube');
$this->display();
}
@@ -162,6 +165,8 @@ class job extends control
}
return $this->send(array('result' => 'fail', 'message' => $errors));
}
+
+ $this->loadModel('action')->create('job', $id, 'edited');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
@@ -189,17 +194,18 @@ class job extends control
if($jobProduct and $jobProduct->deleted == 0) $products += array($job->product => $jobProduct->name);
}
- $this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->edit;
- $this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
- $this->view->position[] = $this->lang->job->edit;
- $this->view->repoPairs = $repoPairs;
- $this->view->gitlabRepos = $gitlabRepos;
- $this->view->repoTypes = $repoTypes;
- $this->view->repoType = zget($repoTypes, $job->repo, 'Git');
- $this->view->job = $job;
- $this->view->products = array(0 => '') + $products;
- $this->view->jenkinsServerList = $this->loadModel('jenkins')->getPairs();
- $this->view->pipelines = $this->jenkins->getTasks($job->server);
+ $this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->edit;
+ $this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
+ $this->view->position[] = $this->lang->job->edit;
+ $this->view->repoPairs = $repoPairs;
+ $this->view->gitlabRepos = $gitlabRepos;
+ $this->view->repoTypes = $repoTypes;
+ $this->view->repoType = zget($repoTypes, $job->repo, 'Git');
+ $this->view->job = $job;
+ $this->view->products = array('') + $products;
+ $this->view->jenkinsServerList = $this->loadModel('jenkins')->getPairs();
+ $this->view->sonarqubeServerList = array('') + $this->loadModel('pipeline')->getPairs('sonarqube');
+ $this->view->pipelines = $this->jenkins->getTasks($job->server);
$this->display();
}
@@ -323,6 +329,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))));
}
@@ -414,4 +421,21 @@ class job extends control
$this->send(array('result' => 'success', 'type' => strtolower($repo->SCM)));
}
+ /**
+ * Ajax check SonarQube linked by repoID.
+ *
+ * @param int $repoID
+ * @access public
+ * @return void
+ */
+ public function ajaxCheckSonarqubeLink($repoID, $jobID = 0)
+ {
+ $repo = $this->loadModel('job')->getSonarqubeByRepo(array($repoID), $jobID, true);
+ if(!empty($repo))
+ {
+ $message = $repo[$repoID]->deleted ? $this->lang->job->jobIsDeleted : sprintf($this->lang->job->repoExists, $repo[$repoID]->id . '-' . $repo[$repoID]->name);
+ $this->send(array('result' => 'fail', 'message' => $message));
+ }
+ $this->send(array('result' => 'success', 'message' => ''));
+ }
}
diff --git a/module/job/js/create.js b/module/job/js/create.js
index 635ce8abc2..cd188907e9 100644
--- a/module/job/js/create.js
+++ b/module/job/js/create.js
@@ -1,5 +1,51 @@
$(document).ready(function()
{
+ /*
+ * Get frame select.
+ * param string engine eg. jenkins|gitlab
+ */
+ function getFrameSelect(engine)
+ {
+ $('#frameBox .input-group').empty();
+ $('#frameBox .input-group').append("");
+ var html = "';
+
+ $('#frameBox .loading').remove();
+ $('#frameBox .input-group').append(html);
+ $('#frameBox #frame').chosen();
+
+ $('#frame').change();
+ }
+ getFrameSelect('');
+
+ /*
+ * Check sonarqube linked.
+ */
+ function checkSonarquebLink()
+ {
+ var repoID = $('#repo').val();
+ var frame = $('#frame').val();
+
+ if(frame != 'sonarqube' || repoID == 0) return false;
+
+ $.getJSON(createLink('job', 'ajaxCheckSonarqubeLink', 'repoID=' + repoID), function(result)
+ {
+ if(result.result != 'success')
+ {
+ alert(result.message);
+ $('#repo').val(0).trigger('chosen:updated');
+ $('#reference').val('').trigger('chosen:updated');
+ $('.reference').hide();
+ return false;
+ }
+ })
+ }
+
$(document).on('change', '#repo', function()
{
var repoID = $(this).val();
@@ -63,6 +109,9 @@ $(document).ready(function()
$('#triggerggerType option[value=tag]').html(data.type == 'gitlab' ? buildTag : dirChange).trigger('chosen:updated');
}
});
+
+ /* Check exists sonarqube data. */
+ checkSonarquebLink();
});
$(document).on('change', '[name^=svnDir]', function()
@@ -139,6 +188,42 @@ $(document).ready(function()
$('#jenkinsServerTR #jkTask').chosen({drop_direction: 'auto'});
})
+
+ /* There has been a problem with handling the prompt label. */
+ $('#jkTaskLabel').remove();
+ })
+
+ $(document).on('change', '#frame', function()
+ {
+ var frame = $(this).val();
+ if(frame == 'sonarqube')
+ {
+ $('tr.sonarqube').removeClass('hide');
+
+ /* Check exists sonarqube data. */
+ checkSonarquebLink();
+ }
+ else
+ {
+ $('tr.sonarqube').addClass('hide');
+ }
+ })
+
+ $(document).on('change', '#sonarqubeServer', function()
+ {
+ var sonarqubeID = $(this).val();
+ $('#sonarProject #projectKey').remove();
+ $('#sonarProject #projectKey_chosen').remove();
+ $('#sonarProject .input-group').append("");
+ $.get(createLink('sonarqube', 'ajaxGetProjectList', 'sonarqubeID=' + sonarqubeID), function(html)
+ {
+ $('#sonarProject .loading').remove();
+ $('#sonarProject .input-group').append(html);
+ $('#sonarProject #projectKey').chosen({drop_direction: 'auto'});
+ })
+
+ /* There has been a problem with handling the prompt label. */
+ $('#projectKeyLabel').remove();
})
var scheduleOption = "";
@@ -161,9 +246,10 @@ $(document).ready(function()
$('tr.gitlabRepo').hide();
$('tr.commonRepo').show();
}
+
+ getFrameSelect(engine);
});
$('#engine').change();
-
$('#triggerType').change();
});
diff --git a/module/job/js/edit.js b/module/job/js/edit.js
index f91c2aef1b..66066ae271 100644
--- a/module/job/js/edit.js
+++ b/module/job/js/edit.js
@@ -1,5 +1,52 @@
$(document).ready(function()
{
+ /*
+ * Get frame select.
+ * param string engine eg. jenkins|gitlab
+ */
+ function getFrameSelect()
+ {
+ $('#frameBox .input-group').empty();
+ $('#frameBox .input-group').append("");
+ var html = "';
+
+ $('#frameBox .loading').remove();
+ $('#frameBox .input-group').append(html);
+ $('#frameBox #frame').chosen();
+ }
+ getFrameSelect();
+
+ /* Check sonarqube linked. */
+ function checkSonarquebLink()
+ {
+ var repoID = $('#repo').val();
+ var frame = $('#frame').val();
+
+ if(frame != 'sonarqube' || repoID == 0) return false;
+
+ $.getJSON(createLink('job', 'ajaxCheckSonarqubeLink', 'repoID=' + repoID + '&jobID=' + job.id), function(result)
+ {
+ if(result.result != 'success')
+ {
+ alert(result.message);
+ $('#repo').val(0).trigger('chosen:updated');
+ $('#reference').val('').trigger('chosen:updated');
+ $('.reference').hide();
+ return false;
+ }
+ })
+ }
+
$('#gitlabRepo').change(function()
{
$('#repo').val($(this).val()).change();
@@ -45,6 +92,9 @@ $(document).ready(function()
$('#svnDirBox #svnDir').chosen();
})
}
+
+ /* Check exists sonarqube data. */
+ checkSonarquebLink();
})
$(document).on('change', '[name^=svnDir]', function()
@@ -124,6 +174,43 @@ $(document).ready(function()
$('#jenkinsServerTR #jkTask').val(jkTask).chosen();
})
+
+ /* There has been a problem with handling the prompt label. */
+ $('#jkTaskLabel').remove();
+ })
+
+ $(document).on('change', '#frame', function()
+ {
+ var frame = $(this).val();
+ if(frame == 'sonarqube')
+ {
+ $('tr.sonarqube').removeClass('hide');
+
+ /* Check exists sonarqube data. */
+ checkSonarquebLink();
+ }
+ else
+ {
+ $('tr.sonarqube').addClass('hide');
+ }
+ })
+
+ $(document).on('change', '#sonarqubeServer', function()
+ {
+ var sonarqubeID = $(this).val();
+ var projectKey = sonarqubeID == job.sonarqubeServer ? job.projectKey.replace(/-/g, '*') : '';
+ $('#sonarProject #projectKey').remove();
+ $('#sonarProject #projectKey_chosen').remove();
+ $('#sonarProject .input-group').append("");
+ $.get(createLink('sonarqube', 'ajaxGetProjectList', 'sonarqubeID=' + sonarqubeID + '&projectKey=' + projectKey), function(html)
+ {
+ $('#sonarProject .loading').remove();
+ $('#sonarProject .input-group').append(html);
+ $('#sonarProject #projectKey').chosen({drop_direction: 'auto'});
+ })
+
+ /* There has been a problem with handling the prompt label. */
+ $('#projectKeyLabel').remove();
})
var scheduleOption = "";
@@ -169,6 +256,7 @@ $(document).ready(function()
$('#engine').change();
$('#jkServer').change();
-
+ $('#frame').change();
+ $('#sonarqubeServer').change();
$('#triggerType').change();
});
diff --git a/module/job/lang/en.php b/module/job/lang/en.php
index f2353087d6..e8b58344a5 100644
--- a/module/job/lang/en.php
+++ b/module/job/lang/en.php
@@ -14,46 +14,52 @@ $lang->job->execSuccess = 'Build success';
$lang->job->browseAction = 'Job List';
-$lang->job->id = 'ID';
-$lang->job->name = 'Name';
-$lang->job->repo = 'Repo';
-$lang->job->product = $lang->productCommon;
-$lang->job->svnDir = 'SVN Tag Watch Path';
-$lang->job->jenkins = 'Jenkins';
-$lang->job->jkHost = 'Jenkins Server';
-$lang->job->jkJob = 'Jenkins Task';
-$lang->job->buildSpec = 'Build Target'; // 'pipeline@server'
-$lang->job->engine = 'Engine';
-$lang->job->server = 'Server';
-$lang->job->pipeline = 'Pipeline';
-$lang->job->buildType = 'Build Type';
-$lang->job->frame = 'Frame';
-$lang->job->triggerType = 'Trigger';
-$lang->job->atDay = 'Custom Days';
-$lang->job->atTime = 'At Time';
-$lang->job->lastStatus = 'Last Status';
-$lang->job->lastExec = 'Last Executed';
-$lang->job->comment = 'Match Keywords';
-$lang->job->customParam = 'Custom build parameters';
-$lang->job->paramName = 'Name';
-$lang->job->paramValue = 'Value';
-$lang->job->custom = 'Custom';
-$lang->job->createdBy = 'Created By';
-$lang->job->createdDate = 'Created Date';
-$lang->job->editedBy = 'Edited By';
-$lang->job->editedDate = 'Edited Date';
-$lang->job->lastTag = 'Last Tag';
-$lang->job->deleted = 'Deleted';
-$lang->job->repoServer = 'Repo Server';
+$lang->job->id = 'ID';
+$lang->job->name = 'Name';
+$lang->job->repo = 'Repo';
+$lang->job->product = $lang->productCommon;
+$lang->job->svnDir = 'SVN Tag Watch Path';
+$lang->job->jenkins = 'Jenkins';
+$lang->job->jkHost = 'Jenkins Server';
+$lang->job->jkJob = 'Jenkins Task';
+$lang->job->buildSpec = 'Build Target'; // 'pipeline@server'
+$lang->job->engine = 'Engine';
+$lang->job->server = 'Server';
+$lang->job->pipeline = 'Pipeline';
+$lang->job->buildType = 'Build Type';
+$lang->job->frame = 'Frame';
+$lang->job->triggerType = 'Trigger';
+$lang->job->atDay = 'Custom Days';
+$lang->job->atTime = 'At Time';
+$lang->job->lastStatus = 'Last Status';
+$lang->job->lastExec = 'Last Executed';
+$lang->job->comment = 'Match Keywords';
+$lang->job->customParam = 'Custom build parameters';
+$lang->job->paramName = 'Name';
+$lang->job->paramValue = 'Value';
+$lang->job->custom = 'Custom';
+$lang->job->createdBy = 'Created By';
+$lang->job->createdDate = 'Created Date';
+$lang->job->editedBy = 'Edited By';
+$lang->job->editedDate = 'Edited Date';
+$lang->job->lastTag = 'Last Tag';
+$lang->job->deleted = 'Deleted';
+$lang->job->repoServer = 'Repo Server';
+$lang->job->sonarqubeServer = 'SonarQube Server';
+$lang->job->projectKey = 'SonarQube Project';
$lang->job->lblBasic = 'Basic Info';
-$lang->job->example = 'e.g.';
-$lang->job->commitEx = "Used to match the keywords used to create a compile. Multiple keywords are separated by ','";
-$lang->job->cronSample = 'e.g. 0 0 2 * * 2-6/1 means 2:00 a.m. every weekday.';
-$lang->job->sendExec = 'Send execute request success.';
-$lang->job->inputName = 'Please enter parameter name.';
-$lang->job->invalidName = 'The parameter name should be letters, numbers or underlines.';
+$lang->job->example = 'e.g.';
+$lang->job->commitEx = "Used to match the keywords used to create a compile. Multiple keywords are separated by ','";
+$lang->job->cronSample = 'e.g. 0 0 2 * * 2-6/1 means 2:00 a.m. every weekday.';
+$lang->job->sendExec = 'Send execute request success.';
+$lang->job->inputName = 'Please enter parameter name.';
+$lang->job->invalidName = 'The parameter name should be letters, numbers or underlines.';
+$lang->job->repoExists = 'This repository has a build task associated with it『%s』';
+$lang->job->projectExists = 'This SonarQube Project has a build task associated with it『%s』';
+$lang->job->mustUseJenkins = 'SonarQube frame is only used if the build engine is JenKins.';
+$lang->job->jobIsDeleted = 'This repository is associated with a build task, please view the data from the recycle bin';
$lang->job->buildTypeList['build'] = 'Only Build';
$lang->job->buildTypeList['buildAndDeploy'] = 'Build And Deploy';
@@ -63,15 +69,16 @@ $lang->job->triggerTypeList['tag'] = 'Tag';
$lang->job->triggerTypeList['commit'] = 'Code Commit';
$lang->job->triggerTypeList['schedule'] = 'Schedule';
-$lang->job->frameList[''] = '';
-$lang->job->frameList['junit'] = 'JUnit';
-$lang->job->frameList['testng'] = 'TestNG';
-$lang->job->frameList['phpunit'] = 'PHPUnit';
-$lang->job->frameList['pytest'] = 'Pytest';
-$lang->job->frameList['jtest'] = 'JTest';
-$lang->job->frameList['cppunit'] = 'CppUnit';
-$lang->job->frameList['gtest'] = 'GTest';
-$lang->job->frameList['qtest'] = 'QTest';
+$lang->job->frameList[''] = '';
+$lang->job->frameList['junit'] = 'JUnit';
+$lang->job->frameList['testng'] = 'TestNG';
+$lang->job->frameList['phpunit'] = 'PHPUnit';
+$lang->job->frameList['pytest'] = 'Pytest';
+$lang->job->frameList['jtest'] = 'JTest';
+$lang->job->frameList['cppunit'] = 'CppUnit';
+$lang->job->frameList['gtest'] = 'GTest';
+$lang->job->frameList['qtest'] = 'QTest';
+$lang->job->frameList['sonarqube'] = 'SonarQube';
$lang->job->paramValueList[''] = '';
$lang->job->paramValueList['$zentao_version'] = 'Current version';
diff --git a/module/job/lang/zh-cn.php b/module/job/lang/zh-cn.php
index 780ec84159..5f7bb63f04 100644
--- a/module/job/lang/zh-cn.php
+++ b/module/job/lang/zh-cn.php
@@ -14,46 +14,52 @@ $lang->job->execSuccess = '执行成功';
$lang->job->browseAction = '构建任务列表';
-$lang->job->id = 'ID';
-$lang->job->name = '名称';
-$lang->job->repo = '代码库';
-$lang->job->product = '关联' . $lang->productCommon;
-$lang->job->svnDir = 'SVN监控路径';
-$lang->job->jenkins = 'Jenkins';
-$lang->job->jkHost = 'Jenkins服务器';
-$lang->job->jkJob = 'Jenkins任务';
-$lang->job->buildSpec = '构建对象'; // 'pipeline@server'
-$lang->job->engine = '构建引擎';
-$lang->job->server = '服务器';
-$lang->job->pipeline = '流水线';
-$lang->job->buildType = '构建类型';
-$lang->job->frame = '工具/框架';
-$lang->job->triggerType = '触发方式';
-$lang->job->atDay = '自定义日期';
-$lang->job->atTime = '执行时间';
-$lang->job->lastStatus = '最后执行状态';
-$lang->job->lastExec = '最后执行时间';
-$lang->job->comment = '匹配关键字';
-$lang->job->customParam = '自定义构建参数';
-$lang->job->paramName = '名称';
-$lang->job->paramValue = '值';
-$lang->job->custom = '自定义';
-$lang->job->createdBy = '由谁创建';
-$lang->job->createdDate = '创建日期';
-$lang->job->editedBy = '由谁编辑';
-$lang->job->editedDate = '编辑日期';
-$lang->job->lastTag = '最后标签';
-$lang->job->deleted = '已删除';
-$lang->job->repoServer = '版本库服务器';
+$lang->job->id = 'ID';
+$lang->job->name = '名称';
+$lang->job->repo = '代码库';
+$lang->job->product = '关联' . $lang->productCommon;
+$lang->job->svnDir = 'SVN监控路径';
+$lang->job->jenkins = 'Jenkins';
+$lang->job->jkHost = 'Jenkins服务器';
+$lang->job->jkJob = 'Jenkins任务';
+$lang->job->buildSpec = '构建对象'; // 'pipeline@server'
+$lang->job->engine = '构建引擎';
+$lang->job->server = '服务器';
+$lang->job->pipeline = '流水线';
+$lang->job->buildType = '构建类型';
+$lang->job->frame = '工具/框架';
+$lang->job->triggerType = '触发方式';
+$lang->job->atDay = '自定义日期';
+$lang->job->atTime = '执行时间';
+$lang->job->lastStatus = '最后执行状态';
+$lang->job->lastExec = '最后执行时间';
+$lang->job->comment = '匹配关键字';
+$lang->job->customParam = '自定义构建参数';
+$lang->job->paramName = '名称';
+$lang->job->paramValue = '值';
+$lang->job->custom = '自定义';
+$lang->job->createdBy = '由谁创建';
+$lang->job->createdDate = '创建日期';
+$lang->job->editedBy = '由谁编辑';
+$lang->job->editedDate = '编辑日期';
+$lang->job->lastTag = '最后标签';
+$lang->job->deleted = '已删除';
+$lang->job->repoServer = '版本库服务器';
+$lang->job->sonarqubeServer = 'SonarQube服务器';
+$lang->job->projectKey = 'SonarQube项目';
$lang->job->lblBasic = '基本信息';
-$lang->job->example = '举例';
-$lang->job->commitEx = "用于匹配创建构建任务的关键字,多个关键字用','分割";
-$lang->job->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点';
-$lang->job->sendExec = '发送执行请求成功!执行结果:%s';
-$lang->job->inputName = '请输入参数名称。';
-$lang->job->invalidName = '参数名称应该是英文字母、数字或下划线的组合。';
+$lang->job->example = '举例';
+$lang->job->commitEx = "用于匹配创建构建任务的关键字,多个关键字用','分割";
+$lang->job->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点';
+$lang->job->sendExec = '发送执行请求成功!执行结果:%s';
+$lang->job->inputName = '请输入参数名称。';
+$lang->job->invalidName = '参数名称应该是英文字母、数字或下划线的组合。';
+$lang->job->repoExists = '此版本库已关联构建任务『%s』';
+$lang->job->projectExists = '此SonarQube项目已关联构建任务『%s』';
+$lang->job->mustUseJenkins = 'SonarQube工具/框架仅在构建引擎为JenKins的情况下使用';
+$lang->job->jobIsDeleted = '此版本库已关联构建任务,请从回收站查看数据';
$lang->job->buildTypeList['build'] = '仅构建';
$lang->job->buildTypeList['buildAndDeploy'] = '构建部署';
@@ -63,15 +69,16 @@ $lang->job->triggerTypeList['tag'] = '打标签';
$lang->job->triggerTypeList['commit'] = '提交注释包含关键字';
$lang->job->triggerTypeList['schedule'] = '定时计划';
-$lang->job->frameList[''] = '';
-$lang->job->frameList['junit'] = 'JUnit';
-$lang->job->frameList['testng'] = 'TestNG';
-$lang->job->frameList['phpunit'] = 'PHPUnit';
-$lang->job->frameList['pytest'] = 'Pytest';
-$lang->job->frameList['jtest'] = 'JTest';
-$lang->job->frameList['cppunit'] = 'CppUnit';
-$lang->job->frameList['gtest'] = 'GTest';
-$lang->job->frameList['qtest'] = 'QTest';
+$lang->job->frameList[''] = '';
+$lang->job->frameList['junit'] = 'JUnit';
+$lang->job->frameList['testng'] = 'TestNG';
+$lang->job->frameList['phpunit'] = 'PHPUnit';
+$lang->job->frameList['pytest'] = 'Pytest';
+$lang->job->frameList['jtest'] = 'JTest';
+$lang->job->frameList['cppunit'] = 'CppUnit';
+$lang->job->frameList['gtest'] = 'GTest';
+$lang->job->frameList['qtest'] = 'QTest';
+$lang->job->frameList['sonarqube'] = 'SonarQube';
$lang->job->paramValueList[''] = '';
$lang->job->paramValueList['$zentao_version'] = '当前版本号';
diff --git a/module/job/model.php b/module/job/model.php
index 97673d40cc..d9b60f64b5 100644
--- a/module/job/model.php
+++ b/module/job/model.php
@@ -156,7 +156,8 @@ class jobModel extends model
public function create()
{
$job = fixer::input('post')
- ->setDefault('atDay', '')
+ ->setDefault('atDay,projectKey', '')
+ ->setDefault('sonarqubeServer', 0)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->remove('repoType,reference')
@@ -181,6 +182,35 @@ class jobModel extends model
unset($job->jkTask);
unset($job->gitlabRepo);
+ /* SonarQube tool is only used if the engine is JenKins. */
+ if($job->engine != 'jenkins' and $job->frame == 'sonarqube')
+ {
+ dao::$errors[]['frame'] = $this->lang->job->mustUseJenkins;
+ return false;
+ }
+
+ if($job->repo > 0 and $job->frame == 'sonarqube')
+ {
+ $sonarqubeJob = $this->getSonarqubeByRepo(array($job->repo));
+ if(!empty($sonarqubeJob))
+ {
+ $message = sprintf($this->lang->job->repoExists, $sonarqubeJob[$job->repo]->id . '-' . $sonarqubeJob[$job->repo]->name);
+ dao::$errors[]['repo'] = $message;
+ return false;
+ }
+ }
+
+ if(!empty($job->projectKey) and $job->frame == 'sonarqube')
+ {
+ $projectList = $this->getJobBySonarqubeProject($job->sonarqubeServer, array($job->projectKey));
+ if(!empty($projectList))
+ {
+ $message = sprintf($this->lang->job->projectExists, $projectList[$job->projectKey]->id);
+ dao::$errors[]['projectKey'] = $message;
+ return false;
+ }
+ }
+
if($job->triggerType == 'schedule') $job->atDay = empty($_POST['atDay']) ? '' : join(',', $this->post->atDay);
$job->svnDir = '';
@@ -219,6 +249,7 @@ class jobModel extends model
->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty')
->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty')
->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty')
+ ->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty')
->autoCheck()
->exec();
if(dao::isError()) return false;
@@ -268,6 +299,35 @@ class jobModel extends model
unset($job->jkTask);
unset($job->gitlabRepo);
+ /* SonarQube tool is only used if the engine is JenKins. */
+ if($job->engine != 'jenkins' and $job->frame == 'sonarqube')
+ {
+ dao::$errors[] = $this->lang->job->mustUseJenkins;
+ return false;
+ }
+
+ if($job->repo > 0 and $job->frame == 'sonarqube')
+ {
+ $sonarqubeJob = $this->getSonarqubeByRepo(array($job->repo), $id);
+ if(!empty($sonarqubeJob))
+ {
+ $message = sprintf($this->lang->job->repoExists, $sonarqubeJob[$job->repo]->id . '-' . $sonarqubeJob[$job->repo]->name);
+ dao::$errors[]['repo'] = $message;
+ return false;
+ }
+ }
+
+ if(!empty($job->projectKey) and $job->frame == 'sonarqube')
+ {
+ $projectList = $this->getJobBySonarqubeProject($job->sonarqubeServer, array($job->projectKey));
+ if(!empty($projectList) && $projectList[$job->projectKey]->id != $id)
+ {
+ $message = sprintf($this->lang->job->projectExists, $projectList[$job->projectKey]->id);
+ dao::$errors[]['projectKey'] = $message;
+ return false;
+ }
+ }
+
if($job->triggerType == 'schedule') $job->atDay = empty($_POST['atDay']) ? '' : join(',', $this->post->atDay);
$job->svnDir = '';
@@ -304,11 +364,10 @@ class jobModel extends model
$this->dao->update(TABLE_JOB)->data($job)
->batchCheck($this->config->job->edit->requiredFields, 'notempty')
-
->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty')
->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty')
->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty')
-
+ ->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty')
->autoCheck()
->where('id')->eq($id)
->exec();
@@ -539,4 +598,43 @@ class jobModel extends model
return '';
}
+
+ /**
+ * Get sonarqube by RepoID.
+ *
+ * @param array $repoIDList
+ * @param int $jobID
+ * @param bool $showDeleted
+ * @access public
+ * @return array
+ */
+ public function getSonarqubeByRepo($repoIDList, $jobID = 0, $showDeleted = false)
+ {
+ return $this->dao->select('id,name,repo,deleted')->from(TABLE_JOB)
+ ->where('frame')->eq('sonarqube')
+ ->andWhere('repo')->in($repoIDList)
+ ->beginIF(!$showDeleted)->andWhere('deleted')->eq('0')->fi()
+ ->beginIF($jobID > 0)->andWhere('id')->ne($jobID)->fi()
+ ->fetchAll('repo');
+ }
+
+ /**
+ * Get job pairs by sonarqube projectkeys.
+ *
+ * @param int $sonarqubeID
+ * @param array $projectKeys
+ * @param bool $emptyShowAll
+ * @param bool $showDeleted
+ * @access public
+ * @return array
+ */
+ public function getJobBySonarqubeProject($sonarqubeID, $projectKeys = array(), $emptyShowAll = false, $showDeleted = false)
+ {
+ return $this->dao->select('projectKey,id')->from(TABLE_JOB)
+ ->where('frame')->eq('sonarqube')
+ ->andWhere('sonarqubeServer')->eq($sonarqubeID)
+ ->beginIF(!$showDeleted)->andWhere('deleted')->eq('0')->fi()
+ ->beginIF(!empty($projectKeys) or !$emptyShowAll)->andWhere('projectKey')->in($projectKeys)->fi()
+ ->fetchPairs();
+ }
}
diff --git a/module/job/view/create.html.php b/module/job/view/create.html.php
index ac885915c0..9a3f95cdde 100644
--- a/module/job/view/create.html.php
+++ b/module/job/view/create.html.php
@@ -16,6 +16,7 @@
job->dirChange);?>
job->buildTag);?>
+job->frameList);?>