diff --git a/db/zentao.sql b/db/zentao.sql index 4ccd0bf73f..953bff1a88 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -546,11 +546,13 @@ CREATE TABLE IF NOT EXISTS `zt_module` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_mr`; CREATE TABLE `zt_mr` ( - `id` mediumint(8) unsigned NOT NULL auto_increment, - `repoID` mediumint(8) unsigned NOT NULL, + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `gitlabID` mediumint(8) unsigned NOT NULL, - `projectID` mediumint(8) unsigned NOT NULL, - `mrID` mediumint(8) unsigned NOT NULL, + `sourceProject` int unsigned NOT NULL, + `sourceBranch` varchar(100) NOT NULL, + `targetProject` int unsigned NOT NULL, + `targetBranch` varchar(100) NOT NULL, + `mriid` int unsigned NOT NULL, `title` varchar(255) NOT NULL, `description` text NOT NULL, `assignee` varchar(255) NOT NULL, @@ -560,6 +562,8 @@ CREATE TABLE `zt_mr` ( `editedBy` varchar(30) NOT NULL, `editedDate` datetime NOT NULL, `deleted` tinyint(1) NOT NULL, + `status` char(30) NOT NULL, + `mergeStatus` char(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_notify`; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index b6337eee94..f9f3ecb4cb 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -524,6 +524,7 @@ $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'; diff --git a/module/mr/config.php b/module/mr/config.php index b0535585c1..952787e0e9 100644 --- a/module/mr/config.php +++ b/module/mr/config.php @@ -1,8 +1,6 @@ MR = new stdclass(); $config->MR->create = new stdclass(); -$config->MR->create->requiredFields = 'gitlabID,projectID,mrID,title'; -$config->MR->create->skippedFields = 'sourceProject,sourceBranch,targetProject,targetBranch'; +$config->MR->create->requiredFields = 'gitlabID,sourceProject,sourceBranch,targetProject,targetBranch,title'; +$config->MR->create->skippedFields = 'projectID'; -$config->MR->edit = new stdclass(); -$config->MR->edit->requiredFields = 'title'; diff --git a/module/mr/control.php b/module/mr/control.php index ae41cf7adb..bf978e5fd7 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -35,11 +35,8 @@ class mr extends control { if($_POST) { - $rawMR = $this->mr->create(); - if(isset($rawMR->message)) return $this->send(array('result' => 'fail', 'message' => $rawMR->message)); - - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + $result = $this->mr->create(); + return $this->send($result); } $this->view->title = $this->lang->mr->create; @@ -57,9 +54,8 @@ class mr extends control { if($_POST) { - $this->mr->edit($MRID); - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + $result = $this->mr->edit($MRID); + return $result; } $MR = $this->mr->getByID($MRID); @@ -89,6 +85,24 @@ class mr extends control die(js::locate(inlink('browse'), 'parent')); } + /** + * View a MR. + * + * @access public + * @return void + */ + public function view($id) + { + $MR = $this->mr->getByID($id); + if(isset($MR->gitlabID)) $rawMR = $this->mr->apiGetSingleMR($MR->gitlabID, $MR->projectID, $MR->mrID); + + $this->view->title = $this->lang->mr->view; + $this->view->MR = $MR; + $this->view->rawMR = isset($rawMR) ? $rawMR : false; + + $this->display(); + } + /** * AJAX: Get MR target projects. * diff --git a/module/mr/lang/zh-cn.php b/module/mr/lang/zh-cn.php index 5258ef68b9..229fd39fa4 100644 --- a/module/mr/lang/zh-cn.php +++ b/module/mr/lang/zh-cn.php @@ -5,28 +5,29 @@ $lang->mr->browse = "浏览{$lang->mr->common}"; $lang->mr->list = $lang->mr->browse; $lang->mr->edit = "编辑{$lang->mr->common}"; $lang->mr->delete = "删除{$lang->mr->common}"; -$lang->mr->view = "详情"; +$lang->mr->view = "{$lang->mr->common}详情"; $lang->mr->source = '源项目分支'; $lang->mr->target = '目标项目分支'; -$lang->mr->id = 'ID'; -$lang->mr->iid = "MR原始ID"; -$lang->mr->name = '名称'; -$lang->mr->status = '状态'; -$lang->mr->author = '创建人'; -$lang->mr->assignee = '指派给'; -$lang->mr->reviewer = '评审人'; -$lang->mr->link = 'GitLab链接'; -$lang->mr->canMerge = '是否可合并'; +$lang->mr->id = 'ID'; +$lang->mr->mriid = "MR原始ID"; +$lang->mr->name = '名称'; +$lang->mr->status = '状态'; +$lang->mr->author = '创建人'; +$lang->mr->assignee = '指派给'; +$lang->mr->reviewer = '评审人'; +$lang->mr->link = 'GitLab链接'; +$lang->mr->mergeStatus = '是否可合并'; $lang->mr->statusList = array(); $lang->mr->statusList['opened'] = '开放中'; $lang->mr->statusList['closed'] = '已关闭'; $lang->mr->statusList['merged'] = '已合并'; -$lang->mr->canMergeStatusList = array(); -$lang->mr->canMergeStatusList['can_be_merged'] = '可合并'; -$lang->mr->canMergeStatusList['cannot_be_merged'] = '不可合并'; +$lang->mr->mergeStatusList = array(); +$lang->mr->mergeStatusList['checking'] = '检查中'; +$lang->mr->mergeStatusList['can_be_merged'] = '可合并'; +$lang->mr->mergeStatusList['cannot_be_merged'] = '不可合并'; $lang->mr->description = '描述'; $lang->mr->confirmDelete = '确认删除该merge request吗?'; @@ -36,3 +37,10 @@ $lang->mr->targetProject = '目标项目'; $lang->mr->targetBranch = '目标分支'; $lang->mr->usersTips = '提示:如果无法选择指派人和评审人,请先前往GitLab页面绑定用户。'; +$lang->mr->notFound = "此{$lang->mr->common}不存在。"; + +$lang->mr->createFailedFromAPI = "创建合并请求失败。"; +$lang->mr->accessGitlabFailed = "当前无法连接到GitLab服务器。"; + +$lang->mr->description = "描述"; + diff --git a/module/mr/model.php b/module/mr/model.php index f603124236..9924df8966 100644 --- a/module/mr/model.php +++ b/module/mr/model.php @@ -27,15 +27,12 @@ class mrModel extends model * Get a MR by id. * * @param int $id - * @param bool $process * @access public * @return object */ - public function getByID($id, $process = true) + public function getByID($id) { - $MR = $this->dao->select('*')->from(TABLE_MR)->where('id')->eq($id)->fetch(); - - if($process) return $this->processMR($MR); + $MR = $this->dao->select('*')->from(TABLE_MR)->where('id')->eq($id)->fetch(); return $MR; } @@ -56,8 +53,6 @@ class mrModel extends model ->page($pager) ->fetchAll('id'); - foreach($MRList as $MR) $MR = $this->processMR($MR); - return $MRList; } @@ -70,6 +65,8 @@ class mrModel extends model */ public function processMR($MR) { + if(!isset($MR->gitlabID)) return $MR; + $rawMR = $this->apiGetSingleMR($MR->gitlabID, $MR->projectID, $MR->mrID); $MR->name = $rawMR->title; @@ -77,7 +74,7 @@ class mrModel extends model $MR->sourceBranch = $rawMR->source_branch; $MR->targetProject = $rawMR->target_project_id; $MR->targetBranch = $rawMR->target_branch; - $MR->canMerge = $rawMR->merge_status; + $MR->mergeStatus = $rawMR->merge_status; $MR->status = $rawMR->state; return $MR; } @@ -106,45 +103,56 @@ class mrModel extends model */ public function create() { - $gitlabID = $this->post->gitlabID; - $projectID = $this->post->sourceProject; - - $MR = new stdclass; - $MR->target_project_id = $this->post->targetProject; - $MR->source_branch = $this->post->sourceBranch; - $MR->target_branch = $this->post->targetBranch; - $MR->title = $this->post->title; - $MR->description = $this->post->description; - $MR->assignee_ids = $this->post->assignee; - $MR->reviewer_ids = $this->post->reviewer; - - $rawMR = $this->apiCreateMR($gitlabID, $projectID, $MR); - - /* Another open merge request already exists for this source branch. */ - if(isset($rawMR->message) and !isset($rawMR->iid)) return $rawMR; - - /* Create MR failed. */ - if(!isset($rawMR->iid)) return false; - $MR = fixer::input('post') - ->add('repoID', 0) - ->add('gitlabID', $gitlabID) - ->add('projectID', $rawMR->project_id) /* sourceProject can be not project of the created MR. */ - ->add('mrID', $rawMR->iid) ->add('createdBy', $this->app->user->account) ->add('createdDate', helper::now()) ->get(); - /* Remove extra fields before inserting db table. */ - foreach(explode(',', $this->config->MR->create->skippedFields) as $field) unset($MR->$field); - - $this->dao->insert(TABLE_MR)->data($MR) + $this->dao->insert(TABLE_MR)->data($MR, $this->config->MR->create->skippedFields) ->batchCheck($this->config->MR->create->requiredFields, 'notempty') ->autoCheck() ->exec(); - if(dao::isError()) return false; + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); - return $this->dao->lastInsertId(); + $MRID = $this->dao->lastInsertId(); + + $MRObject = new stdclass; + $MRObject->target_project_id = $MR->targetProject; + $MRObject->source_branch = $MR->sourceBranch; + $MRObject->target_branch = $MR->targetBranch; + $MRObject->title = $MR->title; + $MRObject->description = $MR->description; + $MRObject->assignee_ids = $MR->assignee; + $MRObject->reviewer_ids = $MR->reviewer; + + $rawMR = $this->apiCreateMR($this->post->gitlabID, $this->post->sourceProject, $MRObject); + + /* Another open merge request already exists for this source branch. */ + if(isset($rawMR->message) and !isset($rawMR->iid)) + { + $this->dao->delete()->from(TABLE_MR)->where('id')->eq($MRID)->exec(); + return array('result' => 'fail', 'message' => $rawMR->message); + } + + /* Create MR failed. */ + if(!isset($rawMR->iid)) + { + $this->dao->delete()->from(TABLE_MR)->where('id')->eq($MRID)->exec(); + return array('result' => 'fail', 'message' => $this->lang->mr->createFailedFromAPI); + } + + $MR = new stdclass; + $MR->mriid = $rawMR->iid; + $MR->status = $rawMR->state; + $MR->mergeStatus = $rawMR->merge_status; + + /* Update MR in Zentao database. */ + $this->dao->update(TABLE_MR)->data($MR) + ->where('id')->eq($MRID) + ->autoCheck() + ->exec(); + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); + return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'browse')); } /** @@ -155,12 +163,10 @@ class mrModel extends model */ public function edit($MRID) { - /* Get MR in zentao database and do not append extra attributes in GitLab. */ - $MR = $this->getByID($MRID, $process = false); - $MR->title = $this->post->title; - $MR->description = $this->post->description; - $MR->assignee = $this->post->assignee; - $MR->reviewer = $this->post->reviewer; + $MR = fixer::input('post') + ->setDefault('editedBy', $this->app->user->account) + ->setDefault('editedDate', helper::now()) + ->get(); /* Update MR in GitLab. */ $newMR = new stdclass; @@ -168,15 +174,19 @@ class mrModel extends model $newMR->description = $MR->description; $newMR->assignee = $MR->assignee; $newMR->reviewer = $MR->reviewer; - $newMR->targetBranch = $this->post->targetBranch; - $this->apiUpdateMR($MR->gitlabID, $MR->projectID, $MR->mrID, $newMR); + $newMR->targetBranch = $MR->targetBranch; + + $oldMR = $this->getByID($MRID); + $this->apiUpdateMR($oldMR->gitlabID, $oldMR->sourceProject, $oldMR->mriid, $newMR); /* Update MR in Zentao database. */ $this->dao->update(TABLE_MR)->data($MR) - ->batchCheck($this->config->MR->edit->requiredFields, 'notempty') + ->where('id')->eq($MRID) ->autoCheck() ->exec(); - if(dao::isError()) return false; + + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); + return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'browse')); } /** diff --git a/module/mr/view/browse.html.php b/module/mr/view/browse.html.php index 63a2c33f3c..7fb8423902 100644 --- a/module/mr/view/browse.html.php +++ b/module/mr/view/browse.html.php @@ -27,7 +27,7 @@ mr->targetProject); ?> mr->targetBranch); ?> mr->status); ?> - mr->canMerge); ?> + mr->mergeStatus); ?> actions; ?> @@ -35,16 +35,16 @@ id; ?> - name; ?> + title; ?> loadModel('gitlab')->apiGetSingleProject($mr->gitlabID, $mr->sourceProject)->name_with_namespace; ?> sourceBranch;?> loadModel('gitlab')->apiGetSingleProject($mr->gitlabID, $mr->targetProject)->name_with_namespace; ?> targetBranch;?> mr->statusList, $mr->status);?> - mr->canMergeStatusList, $mr->canMerge);?> + mr->mergeStatusList, $mr->mergeStatus);?> id}", '', '', "title='{$lang->mr->list}' class='btn btn-info'"); + common::printLink('mr', 'view', "mr={$mr->id}", '', '', "title='{$lang->mr->list}' class='btn btn-info'"); common::printLink('mr', 'edit', "mrID=$mr->id", '', '', "title='{$lang->mr->edit}' class='btn btn-info'"); if(common::hasPriv('mr', 'delete')) echo html::a($this->createLink('mr', 'delete', "id=$mr->id"), '', 'hiddenwin', "title='{$lang->mr->delete}' class='btn'"); ?> diff --git a/module/mr/view/edit.html.php b/module/mr/view/edit.html.php index 63a18d337a..0df56316f7 100644 --- a/module/mr/view/edit.html.php +++ b/module/mr/view/edit.html.php @@ -43,7 +43,7 @@ mr->name;?> - name, "class='form-control'"); ?> + title, "class='form-control'"); ?> mr->description; ?>