Merge branch 'jihuMR'
This commit is contained in:
@@ -60,6 +60,7 @@ $filter->git = new stdclass();
|
||||
$filter->svn = new stdclass();
|
||||
$filter->search = new stdclass();
|
||||
$filter->gitlab = new stdclass();
|
||||
$filter->mr = new stdclass();
|
||||
$filter->ci = new stdclass();
|
||||
|
||||
$filter->block->default = new stdclass();
|
||||
@@ -140,6 +141,7 @@ $filter->repo->ajaxsynccommit = new stdclass();
|
||||
$filter->search->index = new stdclass();
|
||||
$filter->gitlab->webhook = new stdclass();
|
||||
$filter->gitlab->importissue = new stdclass();
|
||||
$filter->mr->diff = new stdclass();
|
||||
$filter->ci->checkCompileStatus = new stdclass();
|
||||
$filter->execution->export = new stdclass();
|
||||
|
||||
@@ -356,4 +358,6 @@ $filter->gitlab->importissue->get['product'] = 'string';
|
||||
$filter->gitlab->importissue->get['project'] = 'int';
|
||||
$filter->gitlab->importissue->get['repo'] = 'int';
|
||||
|
||||
$filter->mr->diff->cookie['arrange'] = 'reg::word';
|
||||
|
||||
$filter->ci->checkCompileStatus->get['gitlabOnly'] = 'string';
|
||||
|
||||
@@ -212,9 +212,10 @@ define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
|
||||
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');
|
||||
define('TABLE_NOTIFY', '`' . $config->db->prefix . 'notify`');
|
||||
define('TABLE_OAUTH', '`' . $config->db->prefix . 'oauth`');
|
||||
define('TABLE_PIPELINE', '`' . $config->db->prefix . 'pipeline`');
|
||||
define('TABLE_PIPELINE', '`' . $config->db->prefix . 'pipeline`');
|
||||
define('TABLE_JOB', '`' . $config->db->prefix . 'job`');
|
||||
define('TABLE_COMPILE', '`' . $config->db->prefix . 'compile`');
|
||||
define('TABLE_MR', '`' . $config->db->prefix . 'mr`');
|
||||
|
||||
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
|
||||
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
|
||||
@@ -257,6 +258,7 @@ $config->objectTables['stakeholder'] = TABLE_STAKEHOLDER;
|
||||
$config->objectTables['job'] = TABLE_JOB;
|
||||
$config->objectTables['team'] = TABLE_TEAM;
|
||||
$config->objectTables['pipeline'] = TABLE_PIPELINE;
|
||||
$config->objectTables['mr'] = TABLE_MR;
|
||||
|
||||
/* Program privs.*/
|
||||
$config->programPriv = new stdclass();
|
||||
|
||||
@@ -2,3 +2,6 @@ ALTER TABLE `zt_testtask` ADD `realFinishedDate` datetime NOT NULL AFTER `end`;
|
||||
ALTER TABLE `zt_doc` ADD `draft` longtext NOT NULL AFTER `views`;
|
||||
ALTER TABLE `zt_release` ADD `mailto` text AFTER `desc`;
|
||||
ALTER TABLE `zt_release` ADD `notify` varchar(255) AFTER `mailto`;
|
||||
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=mr&methodName=syncMR', '定时同步GitLab合并数据到禅道数据库', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
|
||||
@@ -2,3 +2,25 @@ UPDATE `zt_action` SET `action` = 'reviewpassed' WHERE `action` = 'passreviewed'
|
||||
UPDATE `zt_action` SET `action` = 'reviewrejected' WHERE `action` = 'reviewclosed';
|
||||
UPDATE `zt_action` SET `action` = 'reviewclarified' WHERE `action` = 'clarifyreviewed';
|
||||
DELETE FROM `zt_score` WHERE `module` = 'tutorial' AND `method` = 'finish';
|
||||
CREATE TABLE `zt_mr` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`gitlabID` 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,
|
||||
`reviewer` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`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;
|
||||
|
||||
|
||||
@@ -545,6 +545,28 @@ CREATE TABLE IF NOT EXISTS `zt_module` (
|
||||
KEY `type` (`type`),
|
||||
KEY `path` (`path`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_mr`;
|
||||
CREATE TABLE `zt_mr` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`gitlabID` 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,
|
||||
`reviewer` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`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`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_notify` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
|
||||
@@ -278,13 +278,15 @@ class gitlab
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function diff($path, $fromRevision, $toRevision)
|
||||
public function diff($path, $fromRevision, $toRevision, $fromProject = '')
|
||||
{
|
||||
if(!scm::checkRevision($fromRevision)) return array();
|
||||
if(!scm::checkRevision($toRevision)) return array();
|
||||
|
||||
$api = "compare";
|
||||
$params = array('from' => $fromRevision, 'to' => $toRevision, 'straight' => 1);
|
||||
$api = "compare";
|
||||
$params = array('from' => $fromRevision, 'to' => $toRevision);
|
||||
if($fromProject) $params['from_project_id'] = $fromProject;
|
||||
|
||||
if($toRevision == 'HEAD' and $this->branch) $params['to'] = $this->branch;
|
||||
$results = $this->fetch($api, $params);
|
||||
foreach($results->diffs as $key => $diff)
|
||||
@@ -303,7 +305,6 @@ class gitlab
|
||||
foreach($diffLines as $diffLine) $lines[] = $diffLine;
|
||||
}
|
||||
return $lines;
|
||||
//return $results->diffs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+64
-63
@@ -5,8 +5,8 @@ class scm
|
||||
|
||||
/**
|
||||
* Set engine.
|
||||
*
|
||||
* @param object $repo
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -19,10 +19,10 @@ class scm
|
||||
}
|
||||
|
||||
/**
|
||||
* List files.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* List files.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -34,10 +34,10 @@ class scm
|
||||
|
||||
/**
|
||||
* Get tags.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @param bool $onlyDir
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @param bool $onlyDir
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -49,7 +49,7 @@ class scm
|
||||
|
||||
/**
|
||||
* Get branch.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -60,11 +60,11 @@ class scm
|
||||
|
||||
/**
|
||||
* Get log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param int $count
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -78,9 +78,9 @@ class scm
|
||||
|
||||
/**
|
||||
* Blame file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -92,9 +92,9 @@ class scm
|
||||
|
||||
/**
|
||||
* Get last log.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $count
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $count
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -105,20 +105,21 @@ class scm
|
||||
|
||||
/**
|
||||
* Diff file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param string $parse
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $fromRevision
|
||||
* @param string $toRevision
|
||||
* @param string $parse
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function diff($path, $fromRevision = 0, $toRevision = 'HEAD', $parse = 'yes')
|
||||
public function diff($path, $fromRevision = 0, $toRevision = 'HEAD', $parse = 'yes', $extra = '')
|
||||
{
|
||||
if(!scm::checkRevision($fromRevision)) return array();
|
||||
if(!scm::checkRevision($toRevision)) return array();
|
||||
|
||||
$diffs = $this->engine->diff($path, $fromRevision, $toRevision);
|
||||
if(!$extra) $diffs = $this->engine->diff($path, $fromRevision, $toRevision);
|
||||
if($extra) $diffs = $this->engine->diff($path, $fromRevision, $toRevision, $extra);
|
||||
|
||||
if($parse != 'yes') return implode("\n", $diffs);
|
||||
return $this->engine->parseDiff($diffs);
|
||||
@@ -126,23 +127,23 @@ class scm
|
||||
|
||||
/**
|
||||
* Cat file.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function cat($entry, $revision = 'HEAD')
|
||||
{
|
||||
if(!scm::checkRevision($revision)) return false;
|
||||
return $this->engine->cat($entry, $revision);
|
||||
return $this->engine->cat($entry, $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info.
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
*
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
@@ -154,8 +155,8 @@ class scm
|
||||
|
||||
/**
|
||||
* Exec scm cmd.
|
||||
*
|
||||
* @param string $cmd
|
||||
*
|
||||
* @param string $cmd
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -165,47 +166,47 @@ class scm
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commit count
|
||||
*
|
||||
* @param int $commits
|
||||
* @param string $lastVersion
|
||||
* Get commit count
|
||||
*
|
||||
* @param int $commits
|
||||
* @param string $lastVersion
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getCommitCount($commits = 0, $lastVersion = 0)
|
||||
{
|
||||
if(!scm::checkRevision($lastVersion)) return false;
|
||||
return $this->engine->getCommitCount($commits, $lastVersion);
|
||||
return $this->engine->getCommitCount($commits, $lastVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest revision.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getLatestRevision()
|
||||
{
|
||||
return $this->engine->getLatestRevision();
|
||||
return $this->engine->getLatestRevision();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first revision.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstRevision()
|
||||
{
|
||||
return $this->engine->getFirstRevision();
|
||||
return $this->engine->getFirstRevision();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commits.
|
||||
*
|
||||
* @param string $version
|
||||
* @param int $count
|
||||
* @param string $branch
|
||||
*
|
||||
* @param string $version
|
||||
* @param int $count
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -216,9 +217,9 @@ class scm
|
||||
}
|
||||
|
||||
/**
|
||||
* Check revision
|
||||
*
|
||||
* @param int|string $revision
|
||||
* Check revision
|
||||
*
|
||||
* @param int|string $revision
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
@@ -231,9 +232,9 @@ class scm
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* Escape command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -246,12 +247,12 @@ function escapeCmd($cmd)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @param string $return
|
||||
* @param int $result
|
||||
* @param string $type
|
||||
* Execute command.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @param string $return
|
||||
* @param int $result
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return array|string
|
||||
*/
|
||||
|
||||
@@ -242,6 +242,7 @@ $lang->testcase->testsuite = 'Test Suite';
|
||||
$lang->testcase->caselib = 'Case Library';
|
||||
|
||||
$lang->devops->compile = 'Compile';
|
||||
$lang->devops->mr = 'Merge Request';
|
||||
$lang->devops->repo = 'Repo';
|
||||
$lang->devops->rules = 'Rule';
|
||||
|
||||
|
||||
@@ -238,6 +238,7 @@ $lang->scrum->menu->settings['subMenu']->whitelist = array('link' => "{$lang->
|
||||
$lang->scrum->menu->settings['subMenu']->stakeholder = array('link' => "{$lang->stakeholder->common}|stakeholder|browse|project=%s", 'subModule' => 'stakeholder');
|
||||
$lang->scrum->menu->settings['subMenu']->group = array('link' => "{$lang->priv}|project|group|project=%s", 'alias' => 'group,manageview,managepriv');
|
||||
|
||||
|
||||
/* Execution menu. */
|
||||
$lang->execution->homeMenu = new stdclass();
|
||||
$lang->execution->homeMenu->all = array('link' => "{$lang->execution->all}|execution|all|", 'alias' => 'batchedit');
|
||||
@@ -333,6 +334,7 @@ $lang->qa->dividerMenu = ',bug,testtask,caselib,';
|
||||
$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');
|
||||
@@ -340,11 +342,11 @@ $lang->devops->menu->rules = array('link' => "{$lang->devops->rules}|repo|set
|
||||
|
||||
$lang->devops->menuOrder[5] = 'code';
|
||||
$lang->devops->menuOrder[10] = 'compile';
|
||||
$lang->devops->menuOrder[15] = 'gitlab';
|
||||
$lang->devops->menuOrder[20] = 'jenkins';
|
||||
$lang->devops->menuOrder[25] = 'maintain';
|
||||
$lang->devops->menuOrder[30] = 'rules';
|
||||
|
||||
$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';
|
||||
/* Doc menu. */
|
||||
$lang->doc->menu = new stdclass();
|
||||
$lang->doc->menu->dashboard = array('link' => "{$lang->dashboard}|doc|index");
|
||||
@@ -538,6 +540,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';
|
||||
|
||||
@@ -241,9 +241,11 @@ $lang->testcase->case = '用例';
|
||||
$lang->testcase->testsuite = '套件';
|
||||
$lang->testcase->caselib = '用例库';
|
||||
|
||||
$lang->devops->compile = '构建';
|
||||
$lang->devops->repo = '版本库';
|
||||
$lang->devops->rules = '指令';
|
||||
$lang->devops->compile = '构建';
|
||||
$lang->devops->mr = '合并请求';
|
||||
$lang->devops->repo = '版本库';
|
||||
$lang->devops->rules = '指令';
|
||||
$lang->devops->settings = '合并请求设置';
|
||||
|
||||
$lang->admin->system = '系统';
|
||||
$lang->admin->entry = '应用';
|
||||
|
||||
+23
-10
@@ -129,17 +129,30 @@ class compileModel extends model
|
||||
|
||||
if(!$job) return false;
|
||||
|
||||
$data = new stdclass();
|
||||
$data->PARAM_TAG = $compile->tag;
|
||||
$data->ZENTAO_DATA = "compile={$compile->id}";
|
||||
$compileID = $compile->id;
|
||||
$repo = $this->loadModel('repo')->getRepoById($job->repo);
|
||||
|
||||
$url = $this->getBuildUrl($job);
|
||||
$build = new stdclass();
|
||||
$build->queue = $this->loadModel('ci')->sendRequest($url->url, $data, $url->userPWD);
|
||||
$build->status = $build->queue ? 'created' : 'create_fail';
|
||||
$build->updateDate = helper::now();
|
||||
$this->dao->update(TABLE_COMPILE)->data($build)->where('id')->eq($compile->id)->exec();
|
||||
$this->dao->update(TABLE_JOB)->set('lastStatus')->eq($build->status)->set('lastExec')->eq($build->updateDate)->where('id')->eq($compile->job)->exec();
|
||||
if($job->triggerType == 'tag')
|
||||
{
|
||||
$lastTag = $this->getLastTagByRepo($repo);
|
||||
if($lastTag)
|
||||
{
|
||||
$job->lastTag = $lastTag;
|
||||
$this->dao->update(TABLE_JOB)->set('lastTag')->eq($lastTag)->where('id')->eq($job->id)->exec();
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->set('tag')->eq($lastTag)->where('id')->eq($compile->id)->exec();
|
||||
}
|
||||
|
||||
if($job->engine == 'gitlab') $compile = $this->loadModel('job')->execGitlabPipeline($job, $compileID);
|
||||
if($job->engine == 'jenkins') $compile = $this->job->execJenkinsPipeline($job, $repo, $compile->id);
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->data($compile)->where('id')->eq($compileID)->exec();
|
||||
$this->dao->update(TABLE_JOB)
|
||||
->set('lastStatus')->eq($build->status)
|
||||
->set('lastExec')->eq($build->updateDate)
|
||||
->where('id')->eq($job->id)
|
||||
->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ class gitlab extends control
|
||||
$gitlabID = $this->gitlab->create();
|
||||
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->loadModel('action');
|
||||
$actionID = $this->action->create('gitlab', $gitlabID, 'create');
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
@@ -66,6 +68,24 @@ class gitlab extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* view a gitlab.
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view($id)
|
||||
{
|
||||
$gitlab = $this->gitlab->getByID($id);
|
||||
|
||||
$this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->view;
|
||||
$this->view->gitlab = $gitlab;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
|
||||
$this->view->actions = $this->loadModel('action')->getList('gitlab', $id);
|
||||
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('pipeline', $id);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a gitlab.
|
||||
*
|
||||
@@ -75,17 +95,24 @@ class gitlab extends control
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$gitlab = $this->gitlab->getByID($id);
|
||||
$oldGitLab = $this->gitlab->getByID($id);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$this->checkToken();
|
||||
$this->gitlab->update($id);
|
||||
$gitLab = $this->gitlab->getByID($id);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$this->loadModel('action');
|
||||
$actionID = $this->action->create('gitlab', $id, 'edit');
|
||||
$changes = common::createChanges($oldGitLab, $gitLab);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->edit;
|
||||
$this->view->gitlab = $gitlab;
|
||||
$this->view->gitlab = $oldGitLab;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
@@ -178,7 +205,14 @@ class gitlab extends control
|
||||
{
|
||||
if($confim != 'yes') die(js::confirm($this->lang->gitlab->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
|
||||
|
||||
$oldGitLab = $this->gitlab->getByID($id);
|
||||
$this->loadModel('action');
|
||||
$this->gitlab->delete(TABLE_PIPELINE, $id);
|
||||
|
||||
$gitLab = $this->gitlab->getByID($id);
|
||||
$actionID = $this->action->create('gitlab', $id, 'delete');
|
||||
$changes = common::createChanges($oldGitLab, $gitLab);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
|
||||
@@ -367,4 +401,54 @@ class gitlab extends control
|
||||
}
|
||||
return $this->send($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Get project branches.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetProjectBranches($gitlabID, $projectID)
|
||||
{
|
||||
if(!$gitlabID or !$projectID) return $this->send(array('message' => array()));
|
||||
|
||||
$branches = $this->gitlab->apiGetBranches($gitlabID, $projectID);
|
||||
$options = "<option value=''></option>";
|
||||
foreach($branches as $branch)
|
||||
{
|
||||
$options .= "<option value='{$branch->name}'>{$branch->name}</option>";
|
||||
}
|
||||
$this->send($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Get MR user pairs to select assignee_ids and reviewer_ids.
|
||||
* Attention: The user must be a member of the GitLab project.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetMRUserPairs($gitlabID, $projectID)
|
||||
{
|
||||
if(!$gitlabID) return $this->send(array('message' => array()));
|
||||
|
||||
$bindedUsers = $this->gitlab->getUserIdRealnamePairs($gitlabID);
|
||||
$rawProjectUsers = $this->gitlab->apiGetProjectUsers($gitlabID, $projectID);
|
||||
$users = array();
|
||||
foreach($rawProjectUsers as $rawProjectUser)
|
||||
{
|
||||
if(!empty($bindedUsers[$rawProjectUser->id])) $users[$rawProjectUser->id] = $bindedUsers[$rawProjectUser->id];
|
||||
}
|
||||
|
||||
$options = "<option value=''></option>";
|
||||
foreach($users as $index => $user)
|
||||
{
|
||||
$options .= "<option value='{$index}'>{$user}</option>";
|
||||
}
|
||||
$this->send($options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ $lang->gitlab->common = 'GitLab';
|
||||
$lang->gitlab->browse = '浏览GitLab';
|
||||
$lang->gitlab->create = '添加GitLab';
|
||||
$lang->gitlab->edit = '编辑GitLab';
|
||||
$lang->gitlab->view = '查看GitLab';
|
||||
$lang->gitlab->bindUser = '绑定用户';
|
||||
$lang->gitlab->webhook = 'webhook';
|
||||
$lang->gitlab->bindProduct = '关联产品';
|
||||
|
||||
+178
-35
@@ -34,12 +34,15 @@ class gitlabModel extends model
|
||||
*/
|
||||
public function getList($orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
return $this->loadModel('pipeline')->getList('gitlab', $orderBy, $pager);
|
||||
$gitlabList = $this->loadModel('pipeline')->getList('gitlab', $orderBy, $pager);
|
||||
|
||||
return $gitlabList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gitlab pairs.
|
||||
*
|
||||
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -63,7 +66,25 @@ class gitlabModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gitlab user id zentao account pairs of one gitlab.
|
||||
* Get gitlab user id and realname pairs of one gitlab.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getUserIdRealnamePairs($gitlabID)
|
||||
{
|
||||
return $this->dao->select('oauth.openID as openID,user.realname as realname')
|
||||
->from(TABLE_OAUTH)->alias('oauth')
|
||||
->leftJoin(TABLE_USER)->alias('user')
|
||||
->on("oauth.account = user.account")
|
||||
->where('providerType')->eq('gitlab')
|
||||
->andWhere('providerID')->eq($gitlabID)
|
||||
->fetchPairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gitlab user id and zentao account pairs of one gitlab.
|
||||
*
|
||||
* @param int $gitlab
|
||||
* @access public
|
||||
@@ -255,42 +276,60 @@ class gitlabModel extends model
|
||||
/**
|
||||
* Get gitlab project name of one gitlab project.
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return string|false
|
||||
*/
|
||||
public function getObjectNameForJob($gitlabID, $projectID)
|
||||
public function getProjectName($gitlabID, $projectID)
|
||||
{
|
||||
$project = $this->apiGetSingleProject($gitlabID, $projectID);
|
||||
if(isset($project->name)) return $project->name;
|
||||
if(is_object($project) and isset($project->name)) return $project->name;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ref option menus.
|
||||
* Get reference option menus.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getRefOptions($gitlabID, $projectID)
|
||||
public function getReferenceOptions($gitlabID, $projectID)
|
||||
{
|
||||
$refList = array();
|
||||
$branches = $this->loadModel('gitlab')->apiGetBranches($gitlabID, $projectID);
|
||||
$tags = $this->loadModel('gitlab')->apiGetTags($gitlabID, $projectID);
|
||||
$refList = array();
|
||||
|
||||
/* fix bug 14612*/
|
||||
if(isset($branches->message)) return array();
|
||||
$branches = $this->apiGetBranches($gitlabID, $projectID);
|
||||
foreach($branches as $branch) $refList[$branch->name] = "Branch::" . $branch->name;
|
||||
|
||||
if(isset($branches->error)) return array();
|
||||
$tags = $this->apiGetTags($gitlabID, $projectID);
|
||||
foreach($tags as $tag) $refList[$tag->name] = "Tag::" . $tag->name;
|
||||
|
||||
foreach($branches as $branch) $refList[] = "Branch::" . $branch->name;
|
||||
foreach($tags as $tag) $refList[] = "Tag::" . $tag->name;
|
||||
return $refList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branches.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBranches($gitlabID, $projectID)
|
||||
{
|
||||
$rawBranches = $this->apiGetBranches($gitlabID, $projectID);
|
||||
|
||||
$branches = array();
|
||||
foreach($rawBranches as $branch)
|
||||
{
|
||||
$branches[] = $branch->name;
|
||||
}
|
||||
return $branches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gitlab.
|
||||
*
|
||||
@@ -352,6 +391,23 @@ class gitlabModel extends model
|
||||
return json_decode(commonModel::http($url, $data, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of to-do items.
|
||||
*
|
||||
* @see https://docs.gitlab.com/ee/api/todos.html
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiTodoList($gitlabID, $projectID)
|
||||
{
|
||||
$gitlab = $this->loadModel('gitlab')->getByID($gitlabID);
|
||||
if(!$gitlab) return '';
|
||||
$url = rtrim($gitlab->url, '/')."/api/v4/todos?project_id=$projectID&type=MergeRequest&private_token={$gitlab->token}";
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user.
|
||||
*
|
||||
@@ -413,10 +469,8 @@ class gitlabModel extends model
|
||||
$allResults = array();
|
||||
for($page = 1; true; $page ++)
|
||||
{
|
||||
$results = json_decode(commonModel::http($host . "?private_token={$gitlab->token}&simple=true&membership=true&page={$page}&per_page=100"));
|
||||
if(isset($results->error)) break;
|
||||
$results = json_decode(commonModel::http($host . "?private_token={$gitlab->token}&simple=true&page={$page}&per_page=100"));
|
||||
if(empty($results) or $page > 10) break;
|
||||
|
||||
$allResults = array_merge($allResults, $results);
|
||||
}
|
||||
|
||||
@@ -437,6 +491,94 @@ class gitlabModel extends model
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project users.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetProjectUsers($gitlabID, $projectID)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/users");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project all members(users and users in groups).
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetProjectMembers($gitlabID, $projectID)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/members/all");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the member detail in project.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $userID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetProjectMember($gitlabID, $projectID, $userID)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/members/all/$userID");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single branch by API.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param string $branch
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetSingleBranch($gitlabID, $projectID, $branch)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/repository/branches/$branch");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Forks of a project by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/projects.html#list-forks-of-a-project
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetForks($gitlabID, $projectID)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/forks");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upstream project by API.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function apiGetUpstream($gitlabID,$projectID)
|
||||
{
|
||||
$currentProject = $this->apiGetSingleProject($gitlabID, $projectID);
|
||||
if(isset($currentProject->forked_from_project)) return $currentProject->forked_from_project;
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hooks.
|
||||
*
|
||||
@@ -726,25 +868,26 @@ class gitlabModel extends model
|
||||
/**
|
||||
* Create a new pipeline by api.
|
||||
*
|
||||
* @param integer $gitlabID
|
||||
* @param integer $projectID
|
||||
* @param string $reference
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param object $params
|
||||
* @access public
|
||||
* @return object
|
||||
* @docment https://docs.gitlab.com/ee/api/pipelines.html#create-a-new-pipeline
|
||||
*/
|
||||
public function apiCreatePipeline($gitlabID, $projectID, $reference)
|
||||
public function apiCreatePipeline($gitlabID, $projectID, $params)
|
||||
{
|
||||
if(!is_string($params)) $params = json_encode($params);
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/{$projectID}/pipeline");
|
||||
return json_decode(commonModel::http($url, $reference, null, array("Content-Type: application/json")));
|
||||
return json_decode(commonModel::http($url, $params, null, array("Content-Type: application/json")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single pipline by api.
|
||||
*
|
||||
* @param integer $gitlabID
|
||||
* @param integer $projectID
|
||||
* @param integer $pipelineID
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $pipelineID
|
||||
* @access public
|
||||
* @return object
|
||||
* @docment https://docs.gitlab.com/ee/api/pipelines.html#get-a-single-pipeline
|
||||
@@ -758,9 +901,9 @@ class gitlabModel extends model
|
||||
/**
|
||||
* List pipeline jobs by api.
|
||||
*
|
||||
* @param integer $gitlabID
|
||||
* @param integer $projectID
|
||||
* @param integer $pipelineID
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $pipelineID
|
||||
* @return object
|
||||
* @docment https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-jobs
|
||||
*/
|
||||
@@ -773,9 +916,9 @@ class gitlabModel extends model
|
||||
/**
|
||||
* Get a single job by api.
|
||||
*
|
||||
* @param integer $gitlabID
|
||||
* @param integer $projectID
|
||||
* @param integer $jobID
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $jobID
|
||||
* @return object
|
||||
* @docment https://docs.gitlab.com/ee/api/jobs.html#get-a-single-job
|
||||
*/
|
||||
@@ -788,9 +931,9 @@ class gitlabModel extends model
|
||||
/**
|
||||
* Get a log file by api.
|
||||
*
|
||||
* @param integer $gitlabID
|
||||
* @param integer $projectID
|
||||
* @param integer $jobID
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $jobID
|
||||
* @return string
|
||||
* @docment https://docs.gitlab.com/ee/api/jobs.html#get-a-log-file
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<?php foreach ($gitlabList as $id => $gitlab): ?>
|
||||
<tr class='text' title='<?php if(!$gitlab->isAdminToken) echo $lang->gitlab->tokenLimit;?>'>
|
||||
<td class='text-center'><?php echo $id;?></td>
|
||||
<td class='text c-name' title='<?php echo $gitlab->name;?>'><?php echo $gitlab->name;?></td>
|
||||
<td class='text-c-name' title='<?php echo $gitlab->name;?>'><a class="iframe" data-width="90%" href="<?php echo $this->createLink('gitlab', 'view', "id=$id", '', true); ?>"><?php echo $gitlab->name;?></a></td>
|
||||
<td class='text' title='<?php echo $gitlab->url;?>'><?php echo $gitlab->url;?></td>
|
||||
<td class='c-actions text-left'>
|
||||
<?php
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* The view file of GitLab 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 dave.li <lichengjun@cnezsoft.com>
|
||||
* @package GitLab
|
||||
* @version $Id: view.html.php 4728 2013-05-03 06:14:34Z david18810279601@gmail.com $
|
||||
* @link http://www.zentao.net
|
||||
* */
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php js::set('sysurl', common::getSysUrl());?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class="btn-toolbar pull-left">
|
||||
<div class="page-title">
|
||||
<span class="label label-id"><?php echo $gitlab->id?></span>
|
||||
<span class="text" title="<?php echo $gitlab->name;?>" style='color: #3c4354'><?php echo $gitlab->name;?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mainContent" class="main-row">
|
||||
<div class="main-col col-8">
|
||||
<div class='cell'><?php include '../../common/view/action.html.php';?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -5,8 +5,8 @@ function showPriv(value)
|
||||
|
||||
/**
|
||||
* Control the actions select control for a module.
|
||||
*
|
||||
* @param string $module
|
||||
*
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -63,6 +63,7 @@ $lang->moduleOrder[205] = 'cron';
|
||||
$lang->moduleOrder[210] = 'dev';
|
||||
$lang->moduleOrder[215] = 'message';
|
||||
$lang->moduleOrder[220] = 'gitlab';
|
||||
$lang->moduleOrder[225] = 'mr';
|
||||
|
||||
$lang->resource = new stdclass();
|
||||
|
||||
@@ -1146,6 +1147,7 @@ $lang->resource->gitlab->importIssue = 'importIssue';
|
||||
$lang->resource->gitlab->delete = 'delete';
|
||||
$lang->resource->gitlab->bindUser = 'bindUser';
|
||||
$lang->resource->gitlab->bindProduct = 'bindProduct';
|
||||
|
||||
//$lang->resource->gitlab->webhook = 'webhook';
|
||||
|
||||
$lang->gitlab->methodOrder[5] = 'browse';
|
||||
@@ -1154,9 +1156,22 @@ $lang->gitlab->methodOrder[15] = 'edit';
|
||||
$lang->gitlab->methodOrder[20] = 'importIssue';
|
||||
$lang->gitlab->methodOrder[30] = 'delete';
|
||||
$lang->gitlab->methodOrder[35] = 'bindUser';
|
||||
$lang->gitlab->methodOrder[40] = 'bindProduct';
|
||||
//$lang->gitlab->methodOrder[45] = 'webhook';
|
||||
|
||||
/* merge request. */
|
||||
$lang->resource->mr = new stdclass();
|
||||
$lang->resource->mr->create = 'create';
|
||||
$lang->resource->mr->browse = 'browse';
|
||||
$lang->resource->mr->edit = 'edit';
|
||||
$lang->resource->mr->delete = 'delete';
|
||||
$lang->resource->mr->settings = 'settings';
|
||||
|
||||
$lang->mr->methodOrder[10] = 'create';
|
||||
$lang->mr->methodOrder[15] = 'browse';
|
||||
$lang->mr->methodOrder[20] = 'edit';
|
||||
$lang->mr->methodOrder[25] = 'delete';
|
||||
$lang->mr->methodOrder[35] = 'settings';
|
||||
|
||||
/* Git. */
|
||||
$lang->resource->git = new stdclass();
|
||||
$lang->resource->git->diff = 'diff';
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
<?php
|
||||
include '../../common/view/header.html.php';
|
||||
if($type == 'byGroup') include 'privbygroup.html.php';
|
||||
if($type == 'byModule') include 'privbymodule.html.php';
|
||||
|
||||
@@ -200,6 +200,7 @@ $lang->install->cronList['moduleName=todo&methodName=createCycle'] = '生
|
||||
$lang->install->cronList['moduleName=ci&methodName=initQueue'] = '创建周期性任务';
|
||||
$lang->install->cronList['moduleName=ci&methodName=checkCompileStatus'] = '同步Jenkins任务状态';
|
||||
$lang->install->cronList['moduleName=ci&methodName=exec'] = '执行Jenkins任务';
|
||||
$lang->install->cronList['moduleName=mr&methodName=syncMR'] = '定时同步GitLabMR信息';
|
||||
|
||||
$lang->install->success = "安装成功";
|
||||
$lang->install->login = '登录禅道管理系统';
|
||||
|
||||
+24
-34
@@ -168,6 +168,8 @@ class job extends control
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->repo);
|
||||
$this->view->repo = $this->loadModel('repo')->getRepoByID($job->repo);
|
||||
|
||||
if($repo->SCM == 'Gitlab') $this->view->refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitlab, $repo->project);
|
||||
|
||||
$repoList = $this->repo->getList($this->projectID);
|
||||
$repoPairs = array(0 => '', $repo->id => $repo->name);
|
||||
$gitlabRepos = array(0 => '');
|
||||
@@ -306,49 +308,22 @@ class job extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function exec($id, $showForm = 'no')
|
||||
public function exec($id)
|
||||
{
|
||||
if($showForm == 'yes' or $_POST)
|
||||
$job = $this->job->getByID($id);
|
||||
if(strtolower($job->engine) == 'gitlab')
|
||||
{
|
||||
$job = $this->job->getByID($id);
|
||||
$refList = $this->loadModel('gitlab')->getRefOptions($job->server, $job->pipeline);
|
||||
|
||||
if($_POST)
|
||||
if(!isset($job->reference) or !$job->reference)
|
||||
{
|
||||
$reference = new stdclass;
|
||||
$explodedRefs = explode("::", $refList[$this->post->ref]);
|
||||
$reference->ref = $explodedRefs[1];
|
||||
|
||||
$variables = array();
|
||||
foreach($this->post->keys as $key => $field)
|
||||
{
|
||||
$variable = array();
|
||||
if(!trim($this->post->values[$key])) continue;
|
||||
$variable['key'] = $field;
|
||||
$variable['value'] = $this->post->values[$key];
|
||||
$variable['variable_type'] = "env_var";
|
||||
|
||||
$variables[] = $variable;
|
||||
}
|
||||
|
||||
$reference->variables = $variables;
|
||||
$compile = $this->job->exec($id, json_encode($reference));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->job->execSuccess, 'locate' => $this->createLink('compile', 'logs', "buildID={$compile->id}")));
|
||||
return $this->send(array('result' => 'fail', 'message' => $this->lang->job->setReferenceTips, 'locate' => inlink('edit', "id=$id")));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->job->runPipeline;
|
||||
$this->view->refList = $refList;
|
||||
$this->view->job = $job;
|
||||
$this->view->pipelineTips = $this->lang->job->pipelineTips;
|
||||
return $this->display();
|
||||
}
|
||||
|
||||
$compile = $this->job->exec($id);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$this->app->loadLang('compile');
|
||||
echo js::alert(sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status)));
|
||||
die(js::reload('parent'));
|
||||
return $this->send(array('result' => 'success', 'message' => sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,4 +358,19 @@ class job extends control
|
||||
$productName = $this->loadModel('product')->getByID($repo->product)->name;
|
||||
die(json_encode(array($productName => $repo->product)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get reference list function.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetRefList($repoID)
|
||||
{
|
||||
$repo = $this->loadModel('repo')->getRepoByID($repoID);
|
||||
if($repo->SCM != 'Gitlab') $this->send(array('result' => 'fail'));
|
||||
$refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitlab, $repo->project);
|
||||
$this->send(array('result' => 'success', 'refList' => $refList));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('.icon-job-exec').parent().click(function()
|
||||
{
|
||||
link = $(this).attr('href');
|
||||
$.getJSON(link, function(response)
|
||||
{
|
||||
if(response.result == 'success') bootbox.alert(response.message);
|
||||
if(response.result != 'success') bootbox.alert(response.message, function()
|
||||
{
|
||||
if(typeof(response.locate) == 'string') location.href = response.locate;
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
+20
-2
@@ -129,19 +129,37 @@ $(document).ready(function()
|
||||
|
||||
if($(this).val() == 'gitlab')
|
||||
{
|
||||
$('#triggerType').find('[value=schedule]').remove();
|
||||
$('tr.gitlabRepo').show();
|
||||
$('tr.commonRepo').hide();
|
||||
}
|
||||
else if($('#triggerType').find('[value=schedule]').size() == 0 )
|
||||
{
|
||||
$('#triggerType').append(scheduleOption);
|
||||
$('tr.gitlabRepo').hide();
|
||||
$('tr.commonRepo').show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#engine').change();
|
||||
$('#gitlabRepo').change(function()
|
||||
{
|
||||
$('#reference option').remove();
|
||||
|
||||
var repoID = $(this).val();
|
||||
if(repoID > 0)
|
||||
{
|
||||
$.getJSON(createLink('job', 'ajaxGetRefList', "repoID=" + repoID), function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
$.each(response.refList, function(reference, name)
|
||||
{
|
||||
$('#reference').append("<option value='" + reference + "'>" + name + "</option>");
|
||||
});
|
||||
}
|
||||
$('#reference').trigger('chosen:updated');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#triggerType').change();
|
||||
});
|
||||
|
||||
@@ -146,6 +146,27 @@ $(document).ready(function()
|
||||
}
|
||||
});
|
||||
|
||||
$('#gitlabRepo').change(function()
|
||||
{
|
||||
$('#reference option').remove();
|
||||
|
||||
var repoID = $(this).val();
|
||||
if(repoID > 0)
|
||||
{
|
||||
$.getJSON(createLink('job', 'ajaxGetRefList', "repoID=" + repoID), function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
$.each(response.refList, function(reference, name)
|
||||
{
|
||||
$('#reference').append("<option value='" + reference + "'>" + name + "</option>");
|
||||
});
|
||||
}
|
||||
$('#reference').trigger('chosen:updated');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#engine').change();
|
||||
$('#jkServer').change();
|
||||
|
||||
|
||||
@@ -86,3 +86,4 @@ $lang->job->pipelineVariables = "变量";
|
||||
$lang->job->pipelineVariablesKeyPlaceHolder = "输入变量的名称";
|
||||
$lang->job->pipelineVariablesValuePlaceHolder = "输入变量的值";
|
||||
$lang->job->pipelineVariablesTips = "指定要在此次运行中使用的变量值。CI/CD设置中指定的值将用作默认值。";
|
||||
$lang->job->setReferenceTips = "在执行构建前,请先设置代码库的分支信息。";
|
||||
|
||||
+153
-78
@@ -20,7 +20,14 @@ class jobModel extends model
|
||||
*/
|
||||
public function getByID($id)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_JOB)->where('id')->eq($id)->fetch();
|
||||
$job = $this->dao->select('*')->from(TABLE_JOB)->where('id')->eq($id)->fetch();
|
||||
if(strtolower($job->engine) == 'gitlab')
|
||||
{
|
||||
$pipeline = json_decode($job->pipeline);
|
||||
$job->project = $pipeline->project;
|
||||
$job->reference = $pipeline->reference;
|
||||
}
|
||||
return $job;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +124,7 @@ class jobModel extends model
|
||||
->setDefault('atDay', '')
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->remove('repoType')
|
||||
->remove('repoType,reference')
|
||||
->get();
|
||||
|
||||
if($job->engine == 'jenkins')
|
||||
@@ -128,10 +135,12 @@ class jobModel extends model
|
||||
|
||||
if(strtolower($job->engine) == 'gitlab')
|
||||
{
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->gitlabRepo);
|
||||
$project = zget($repo, 'project');
|
||||
|
||||
$job->repo = $job->gitlabRepo;
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->repo);
|
||||
$job->server = (int)zget($repo, 'gitlab', 0);
|
||||
$job->pipeline = zget($repo, 'project', '');
|
||||
$job->pipeline = json_encode(array('project' => $project, 'reference' => $this->post->reference));
|
||||
}
|
||||
|
||||
unset($job->jkServer);
|
||||
@@ -203,7 +212,7 @@ class jobModel extends model
|
||||
->setIF($this->post->triggerType != 'tag', 'lastTag', '')
|
||||
->add('editedBy', $this->app->user->account)
|
||||
->add('editedDate', helper::now())
|
||||
->remove('repoType')
|
||||
->remove('repoType,reference')
|
||||
->get();
|
||||
|
||||
if($job->engine == 'jenkins')
|
||||
@@ -214,10 +223,12 @@ class jobModel extends model
|
||||
|
||||
if(strtolower($job->engine) == 'gitlab')
|
||||
{
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->gitlabRepo);
|
||||
$project = zget($repo, 'project');
|
||||
|
||||
$job->repo = $job->gitlabRepo;
|
||||
$repo = $this->loadModel('repo')->getRepoByID($job->repo);
|
||||
$job->server = (int)zget($repo, 'gitlab', 0);
|
||||
$job->pipeline = zget($repo, 'project', '');
|
||||
$job->pipeline = json_encode(array('project' => $project, 'reference' => $this->post->reference));
|
||||
}
|
||||
|
||||
unset($job->jkServer);
|
||||
@@ -252,6 +263,7 @@ class jobModel extends model
|
||||
|
||||
if(!empty($paramName)) $customParam[$paramName] = $paramValue;
|
||||
}
|
||||
|
||||
unset($job->paramName);
|
||||
unset($job->paramValue);
|
||||
unset($job->custom);
|
||||
@@ -326,102 +338,165 @@ class jobModel extends model
|
||||
* @access public
|
||||
* @return string|bool
|
||||
*/
|
||||
public function exec($id, $reference = null)
|
||||
public function exec($id)
|
||||
{
|
||||
$job = $this->dao->select('t1.id,t1.name,t1.product,t1.repo,t1.server,t1.pipeline,t1.triggerType,t1.atTime,t1.customParam,t1.engine,t2.name as jenkinsName,t2.url,t2.account,t2.token,t2.password')
|
||||
->from(TABLE_JOB)->alias('t1')
|
||||
->leftJoin(TABLE_PIPELINE)->alias('t2')->on('t1.server=t2.id')
|
||||
->where('t1.id')->eq($id)
|
||||
->fetch();
|
||||
|
||||
if(!$job) return false;
|
||||
|
||||
$build = new stdclass();
|
||||
$build->job = $job->id;
|
||||
$build->name = $job->name;
|
||||
|
||||
$now = helper::now();
|
||||
$data = new stdclass();
|
||||
$repo = $this->loadModel('repo')->getRepoById($job->repo);
|
||||
$data->PARAM_TAG = '';
|
||||
if($job->triggerType == 'tag')
|
||||
{
|
||||
$lastTag = '';
|
||||
if($repo->SCM == 'Subversion')
|
||||
{
|
||||
$dirs = $this->loadModel('svn')->getRepoTags($repo, $job->svnDir);
|
||||
if($dirs)
|
||||
{
|
||||
end($dirs);
|
||||
$lastTag = current($dirs);
|
||||
$lastTag = rtrim($repo->path , '/') . '/' . trim($job->svnDir, '/') . '/' . $lastTag;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tags = $this->loadModel('git')->getRepoTags($repo);
|
||||
if($tags)
|
||||
{
|
||||
end($tags);
|
||||
$lastTag = current($tags);
|
||||
}
|
||||
}
|
||||
|
||||
if($lastTag)
|
||||
{
|
||||
$build->tag = $lastTag;
|
||||
$this->dao->update(TABLE_JOB)->set('lastTag')->eq($lastTag)->where('id')->eq($job->id)->exec();
|
||||
$data->PARAM_TAG = $lastTag;
|
||||
}
|
||||
}
|
||||
elseif($job->triggerType == 'schedule')
|
||||
{
|
||||
$build->atTime = $job->atTime;
|
||||
}
|
||||
$now = helper::now();
|
||||
|
||||
/* Save compile data. */
|
||||
$build = new stdclass();
|
||||
$build->job = $job->id;
|
||||
$build->name = $job->name;
|
||||
$build->createdBy = $this->app->user->account;
|
||||
$build->createdDate = $now;
|
||||
$build->updateDate = $now;
|
||||
|
||||
if($job->triggerType == 'schedule') $build->atTime = $job->atTime;
|
||||
|
||||
if($job->triggerType == 'tag')
|
||||
{
|
||||
$lastTag = $this->getLastTagByRepo($repo);
|
||||
if($lastTag)
|
||||
{
|
||||
$build->tag = $lastTag;
|
||||
$job->lastTag = $lastTag;
|
||||
$this->dao->update(TABLE_JOB)->set('lastTag')->eq($lastTag)->where('id')->eq($job->id)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
|
||||
$compileID = $this->dao->lastInsertId();
|
||||
|
||||
$data->ZENTAO_DATA = "compile={$compileID}";
|
||||
if($job->engine == 'jenkins') $compile = $this->execJenkinsPipeline($job, $repo, $compileID);
|
||||
if($job->engine == 'gitlab') $compile = $this->execGitlabPipeline($job);
|
||||
|
||||
$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 $compile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec jenkins pipeline.
|
||||
*
|
||||
* @param object $job
|
||||
* @param object $repo
|
||||
* @param int $compileID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function execJenkinsPipeline($job, $repo, $compileID)
|
||||
{
|
||||
$pipeline = new stdclass();
|
||||
$pipeline->PARAM_TAG = '';
|
||||
$pipeline->ZENTAO_DATA = "compile={$compileID}";
|
||||
if($job->triggerType == 'tag') $pipeline->PARAM_TAG = $job->lastTag;
|
||||
|
||||
/* Add custom parameters to the data. */
|
||||
foreach(json_decode($job->customParam) as $paramName => $paramValue)
|
||||
{
|
||||
$paramValue = str_replace('$zentao_version', $this->config->version, $paramValue);
|
||||
$paramValue = str_replace('$zentao_account', $this->app->user->account, $paramValue);
|
||||
$paramValue = str_replace('$zentao_product', $job->product, $paramValue);
|
||||
$paramValue = str_replace('$zentao_version', $this->config->version, $paramValue);
|
||||
$paramValue = str_replace('$zentao_account', $this->app->user->account, $paramValue);
|
||||
$paramValue = str_replace('$zentao_product', $job->product, $paramValue);
|
||||
$paramValue = str_replace('$zentao_repopath', $repo->path, $paramValue);
|
||||
$data->$paramName = $paramValue;
|
||||
|
||||
$pipeline->$paramName = $paramValue;
|
||||
}
|
||||
|
||||
$url = $this->loadModel('compile')->getBuildUrl($job);
|
||||
|
||||
$compile = new stdclass();
|
||||
$compile->id = $compileID;
|
||||
|
||||
if($job->engine == 'jenkins')
|
||||
{
|
||||
$url = $this->loadModel('compile')->getBuildUrl($job);
|
||||
$compile->queue = $this->loadModel('ci')->sendRequest($url->url, $data, $url->userPWD);
|
||||
$compile->status = $compile->queue ? 'created' : 'create_fail';
|
||||
}
|
||||
elseif($job->engine == 'gitlab' and $reference)
|
||||
{
|
||||
$pipeline = $this->loadModel('gitlab')->apiCreatePipeline($job->server, $job->pipeline, $reference);
|
||||
if(empty($pipeline->id))
|
||||
{
|
||||
$compile->status = 'create_fail';
|
||||
}
|
||||
else
|
||||
{
|
||||
$compile->queue = $pipeline->id;
|
||||
$compile->status = zget($pipeline, 'status', '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();
|
||||
$compile->id = $compileID;
|
||||
$compile->queue = $this->loadModel('ci')->sendRequest($url->url, $pipeline, $url->userPWD);
|
||||
$compile->status = $compile->queue ? 'created' : 'create_fail';
|
||||
|
||||
return $compile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec gitlab pipeline.
|
||||
*
|
||||
* @param int $job
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function execGitlabPipeline($job)
|
||||
{
|
||||
$pipeline = json_decode($job->pipeline);
|
||||
|
||||
$pipelineParams = new stdclass;
|
||||
$pipelineParams->ref = $pipeline->reference;
|
||||
|
||||
$customParams = json_decode($job->customParam);
|
||||
$variables = array();
|
||||
foreach($customParams as $paramName => $paramValue)
|
||||
{
|
||||
$variable = array();
|
||||
$variable['key'] = $paramName;
|
||||
$variable['value'] = $paramValue;
|
||||
$variable['variable_type'] = "env_var";
|
||||
|
||||
$variables[] = $variable;
|
||||
}
|
||||
|
||||
if(!empty($variables)) $pipelineParams->variables = $variables;
|
||||
|
||||
$compile = new stdclass;
|
||||
|
||||
$pipeline = $this->loadModel('gitlab')->apiCreatePipeline($job->server, $pipeline->project, $pipelineParams);
|
||||
if(empty($pipeline->id)) $compile->status = 'create_fail';
|
||||
|
||||
if(!empty($pipeline->id))
|
||||
{
|
||||
$compile->queue = $pipeline->id;
|
||||
$compile->status = zget($pipeline, 'status', 'create_fail');
|
||||
}
|
||||
|
||||
return $compile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last tag of one repo.
|
||||
*
|
||||
* @param object $repo
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getLastTagByRepo($repo)
|
||||
{
|
||||
if($repo->SCM == 'Subversion')
|
||||
{
|
||||
$dirs = $this->loadModel('svn')->getRepoTags($repo, $job->svnDir);
|
||||
if($dirs)
|
||||
{
|
||||
end($dirs);
|
||||
$lastTag = current($dirs);
|
||||
return rtrim($repo->path , '/') . '/' . trim($job->svnDir, '/') . '/' . $lastTag;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tags = $this->loadModel('git')->getRepoTags($repo);
|
||||
if($tags)
|
||||
{
|
||||
end($tags);
|
||||
return current($tags);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,13 +50,20 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($jobList as $id => $job):?>
|
||||
I <?php
|
||||
if(strtolower($job->engine) == 'gitlab')
|
||||
{
|
||||
$pipeline = json_decode($job->pipeline);
|
||||
if(is_numeric($job->pipeline)) $job->pipeline = $this->loadModel('gitlab')->getProjectName($job->server, $job->pipeline);
|
||||
if(isset($pipeline->reference)) $job->pipeline = $this->loadModel('gitlab')->getProjectName($job->server, $pipeline->project);
|
||||
}
|
||||
?>
|
||||
<tr class='text-left'>
|
||||
<td class='text-center'><?php echo $id;?></td>
|
||||
<td class='text-left c-name' title='<?php echo $job->name;?>'><?php echo common::hasPriv('job', 'view') ? html::a($this->createLink('job', 'view', "jobID={$job->id}", 'html', true), $job->name, '', "class='iframe' data-width='90%'") : $job->name;?></td>
|
||||
<td title='<?php echo $job->repoName;?>'><?php echo $job->repoName;?></td>
|
||||
<td><?php echo zget($lang->job->engineList, $job->engine);?></td>
|
||||
<td><?php echo zget($lang->job->frameList, $job->frame);?></td>
|
||||
<?php if(strtolower($job->engine) == 'gitlab') $job->pipeline = $this->loadModel('gitlab')->getObjectNameForJob($job->server, $job->pipeline);?>
|
||||
<?php $jenkins = urldecode($job->pipeline) . '@' . $job->jenkinsName;?>
|
||||
<td class='c-name' title='<?php echo $jenkins;?>'><?php echo $jenkins;?></td>
|
||||
<?php $triggerConfig = $this->job->getTriggerConfig($job);?>
|
||||
@@ -67,8 +74,7 @@
|
||||
<?php
|
||||
common::printIcon('compile', 'browse', "jobID=$id", '', 'list', 'history');
|
||||
common::printIcon('job', 'edit', "jobID=$id", '', 'list', 'edit');
|
||||
if(strtolower($job->engine) == 'jenkins') common::printIcon('job', 'exec', "jobID=$id", '', 'list', 'play', 'hiddenwin');
|
||||
if(strtolower($job->engine) == 'gitlab') common::printIcon('job', 'exec', "jobID=$id&showForm=yes", '', 'list', 'play', '', '', false, "data-toggle='modal' data-type='ajax'");
|
||||
common::printIcon('job', 'exec', "jobID=$id", '', 'list', 'play');
|
||||
if(common::hasPriv('job', 'delete')) echo html::a($this->createLink('job', 'delete', "jobID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->job->delete}' class='btn'");
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
</tr>
|
||||
<tr class='gitlabRepo hide'>
|
||||
<th><?php echo $lang->job->repo; ?></th>
|
||||
<td><?php echo html::select('gitlabRepo', $gitlabRepos, '', "class='form-control'"); ?></td>
|
||||
<td> <?php echo html::select('gitlabRepo', $gitlabRepos, '', "class='chosen form-control'");?> </td>
|
||||
<td> <?php echo html::select('reference', array(), '', "class='chosen form-control'");?> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->job->product; ?></th>
|
||||
@@ -95,7 +96,7 @@
|
||||
<div class='table-col'><?php echo html::select('jkServer', $jenkinsServerList, '', "class='form-control chosen'"); ?></div>
|
||||
<div class='table-col'>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon'><?php echo $lang->job->pipeline; ?></span>
|
||||
<span class='input-group-addon'><?php echo $lang->job->pipeline;?></span>
|
||||
<?php echo html::select('jkTask', array('' => ''), '', "class='form-control chosen'"); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
|
||||
<?php js::set('repoTypes', $repoTypes)?>
|
||||
<?php js::set('repoTypes', $repoTypes);?>
|
||||
<?php js::set('triggerType', $job->triggerType);?>
|
||||
<?php js::set('pipeline', $job->pipeline);?>
|
||||
<?php js::set('dirChange', $lang->job->dirChange);?>
|
||||
@@ -43,7 +43,8 @@
|
||||
</tr>
|
||||
<tr class='gitlabRepo hide'>
|
||||
<th><?php echo $lang->job->repo; ?></th>
|
||||
<td><?php echo html::select('gitlabRepo', $gitlabRepos, $job->repo, "class='form-control'"); ?></td>
|
||||
<td> <?php echo html::select('gitlabRepo', $gitlabRepos, $job->repo, "class='chosen form-control'");?> </td>
|
||||
<td> <?php echo html::select('reference', $refList, $job->reference, "class='chosen form-control'");?> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->job->product;?></th>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->job->server;?></th>
|
||||
<?php if(strtolower($job->engine) == 'gitlab') $job->pipeline = $this->loadModel('gitlab')->getObjectNameForJob($job->server, $job->pipeline);?>
|
||||
<?php if(strtolower($job->engine) == 'gitlab') $job->pipeline = $this->loadModel('gitlab')->getProjectName($job->server, $job->pipeline);?>
|
||||
<td><?php echo urldecode($job->pipeline) . '@' . $jenkins->name;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
$config->MR = new stdclass();
|
||||
$config->MR->create = new stdclass();
|
||||
$config->MR->create->requiredFields = 'gitlabID,sourceProject,sourceBranch,targetProject,targetBranch,title';
|
||||
$config->MR->create->skippedFields = 'projectID';
|
||||
|
||||
$config->MR->maps = new stdclass;
|
||||
$config->MR->maps->sync = array();
|
||||
$config->MR->maps->sync['title'] = 'title|field|';
|
||||
$config->MR->maps->sync['description'] = 'description|field|';
|
||||
$config->MR->maps->sync['assignee'] = 'assignees|userPairs|id';
|
||||
$config->MR->maps->sync['reviewer'] = 'reviewers|userPairs|id';
|
||||
$config->MR->maps->sync['targetBranch'] = 'target_branch|field|';
|
||||
$config->MR->maps->sync['sourceBranch'] = 'source_branch|field|';
|
||||
$config->MR->maps->sync['sourceProject'] = 'source_project_id|field|';
|
||||
$config->MR->maps->sync['targetProject'] = 'target_project_id|field|';
|
||||
$config->MR->maps->sync['status'] = 'state|field|';
|
||||
$config->MR->maps->sync['mergeStatus'] = 'merge_status|field|';
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
class mr extends control
|
||||
{
|
||||
/**
|
||||
* Browse mr.
|
||||
*
|
||||
* @param int $objectID
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($objectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$MRList = $this->mr->getList($orderBy, $pager);
|
||||
|
||||
/* Save current URI to session. */
|
||||
$this->session->set('mrList', $this->app->getURI(true), 'repo');
|
||||
|
||||
/* Sync GitLab MR to ZenTao Database. */
|
||||
$MRList = $this->mr->batchSyncMR($MRList);
|
||||
|
||||
$this->view->title = $this->lang->mr->common . $this->lang->colon . $this->lang->mr->browse;
|
||||
$this->view->MRList = $MRList;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->objectID = $objectID;
|
||||
$this->view->pager = $pager;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create MR function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$result = $this->mr->create();
|
||||
return $this->send($result);
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->mr->create;
|
||||
$this->view->gitlabHosts = $this->loadModel('gitlab')->getPairs();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit MR function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit($MRID)
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$result = $this->mr->update($MRID);
|
||||
return $this->send($result);
|
||||
}
|
||||
|
||||
$MR = $this->mr->getByID($MRID);
|
||||
|
||||
$branchList = $this->loadModel('gitlab')->getBranches($MR->gitlabID, $MR->targetProject);
|
||||
$targetBranchList = array();
|
||||
foreach($branchList as $branch) $targetBranchList[$branch] = $branch;
|
||||
|
||||
/* Fetch user list both in Zentao and current GitLab project. */
|
||||
$bindedUsers = $this->gitlab->getUserIdRealnamePairs($MR->gitlabID);
|
||||
$rawProjectUsers = $this->gitlab->apiGetProjectUsers($MR->gitlabID, $MR->targetProject);
|
||||
$users = array();
|
||||
foreach($rawProjectUsers as $rawProjectUser)
|
||||
{
|
||||
if(!empty($bindedUsers[$rawProjectUser->id])) $users[$rawProjectUser->id] = $bindedUsers[$rawProjectUser->id];
|
||||
}
|
||||
|
||||
$gitlabUsers = $this->gitlab->getUserAccountIdPairs($MR->gitlabID);
|
||||
|
||||
$this->view->title = $this->lang->mr->edit;
|
||||
$this->view->MR = $MR;
|
||||
$this->view->targetBranchList = $targetBranchList;
|
||||
$this->view->users = array("" => "") + $users;
|
||||
$this->view->assignee = zget($gitlabUsers, $MR->assignee, '');
|
||||
$this->view->reviewer = zget($gitlabUsers, $MR->reviewer, '');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a MR.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id, $confim = 'no')
|
||||
{
|
||||
if($confim != 'yes') die(js::confirm($this->lang->gitlab->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
|
||||
|
||||
$MR = $this->mr->getByID($id);
|
||||
|
||||
$this->dao->delete()->from(TABLE_MR)->where('id')->eq($id)->exec();
|
||||
$this->mr->apiDeleteMR($MR->gitlabID, $MR->sourceProject, $MR->mriid);
|
||||
|
||||
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->targetProject, $MR->mriid);
|
||||
|
||||
$this->view->title = $this->lang->mr->view;
|
||||
$this->view->MR = $MR;
|
||||
$this->view->rawMR = isset($rawMR) ? $rawMR : false;
|
||||
|
||||
$this->loadModel('gitlab');
|
||||
$sourceProject = $this->gitlab->apiGetSingleProject($MR->gitlabID, $MR->sourceProject);
|
||||
$targetProject = $this->gitlab->apiGetSingleProject($MR->gitlabID, $MR->targetProject);
|
||||
$sourceBranch = $this->gitlab->apiGetSingleBranch($MR->gitlabID, $MR->sourceProject, $MR->sourceBranch);
|
||||
$targetBranch = $this->gitlab->apiGetSingleBranch($MR->gitlabID, $MR->targetProject, $MR->targetBranch);
|
||||
|
||||
$this->view->sourceProjectName = $sourceProject->name_with_namespace;
|
||||
$this->view->targetProjectName = $targetProject->name_with_namespace;
|
||||
$this->view->sourceProjectURL = $sourceBranch ->web_url;
|
||||
$this->view->targetProjectURL = $targetBranch ->web_url;
|
||||
|
||||
/* Those variables are used to render $lang->mr->commandDocument. */
|
||||
$this->view->httpRepoURL = $sourceProject->http_url_to_repo;
|
||||
$this->view->branchPath = $sourceProject->path_with_namespace . '-' . $rawMR->source_branch;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crontab sync MR from GitLab API to Zentao database, default time 5 minutes to execute once.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function syncMR()
|
||||
{
|
||||
$MRList = $this->mr->getList();
|
||||
$this->mr->batchSyncMR($MRList);
|
||||
|
||||
if(dao::isError())
|
||||
{
|
||||
echo json_encode(dao::getError());
|
||||
return true;
|
||||
}
|
||||
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a MR.
|
||||
*
|
||||
* @param int $MRID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function accept($MRID)
|
||||
{
|
||||
$MR = $this->mr->getByID($MRID);
|
||||
|
||||
/* Accept MR by using the mapped user in GitLab. */
|
||||
$sudoUser = $this->mr->getSudoUsername($MR->gitlabID, $MR->targetProject);
|
||||
|
||||
if(isset($MR->gitlabID))
|
||||
{
|
||||
if(!empty($sudoUser)) $rawMR = $this->mr->apiAcceptMR($MR->gitlabID, $MR->targetProject, $MR->mriid, $sudo = $sudoUser);
|
||||
if(empty($sudoUser)) $rawMR = $this->mr->apiAcceptMR($MR->gitlabID, $MR->targetProject, $MR->mriid);
|
||||
}
|
||||
if(isset($rawMR->state) and $rawMR->state == 'merged')
|
||||
{
|
||||
/* Force reload when locate to the url. */
|
||||
$random = uniqid();
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->mr->mergeSuccess, 'locate' => helper::createLink('mr', 'browse', "random={$random}")));
|
||||
}
|
||||
|
||||
/* The type of variable `$rawMR->message` is string. This is different with apiCreateMR. */
|
||||
if(isset($rawMR->message)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->mr->apiError->sudo, $rawMR->message), 'locate' => helper::createLink('mr', 'view', "mr={$MRID}")));
|
||||
|
||||
return $this->send(array('result' => 'fail', 'message' => $this->lang->mr->mergeFailed, 'locate' => helper::createLink('mr', 'view', "mr={$MRID}")));
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Get MR target projects.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetMRTargetProjects($gitlabID, $projectID)
|
||||
{
|
||||
$this->loadModel('gitlab');
|
||||
|
||||
/* First step: get forks. Only get first level forks(not recursively). */
|
||||
$projects = $this->gitlab->apiGetForks($gitlabID, $projectID);
|
||||
|
||||
/* Second step: get project itself. */
|
||||
$projects[] = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
|
||||
|
||||
/* Last step: find its upstream recursively. */
|
||||
$project = $this->gitlab->apiGetUpstream($gitlabID, $projectID);
|
||||
if(!empty($project)) $projects[] = $project;
|
||||
|
||||
while(!empty($project) and isset($project->id))
|
||||
{
|
||||
$project = $this->gitlab->apiGetUpstream($gitlabID, $project->id);
|
||||
if(empty($project)) break;
|
||||
$projects[] = $project;
|
||||
}
|
||||
|
||||
if(!$projects) return $this->send(array('message' => array()));
|
||||
|
||||
$options = "<option value=''></option>";
|
||||
foreach($projects as $project)
|
||||
{
|
||||
$options .= "<option value='{$project->id}' data-name='{$project->name}'>{$project->name_with_namespace}</option>";
|
||||
}
|
||||
|
||||
$this->send($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* View diff between MR source and target branches.
|
||||
*
|
||||
* @param int $MRID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function diff($MRID)
|
||||
{
|
||||
$MR = $this->mr->getByID($MRID);
|
||||
$diffs = $this->mr->getDiffs($MR);
|
||||
$arrange = $this->cookie->arrange ? $this->cookie->arrange : 'inline';
|
||||
|
||||
if($this->server->request_method == 'POST')
|
||||
{
|
||||
if($this->post->arrange)
|
||||
{
|
||||
$arrange = $this->post->arrange;
|
||||
setcookie('arrange', $arrange);
|
||||
}
|
||||
if($this->post->encoding) $encoding = $this->post->encoding;
|
||||
}
|
||||
|
||||
if($arrange == 'appose')
|
||||
{
|
||||
foreach($diffs as $diffFile)
|
||||
{
|
||||
if(empty($diffFile->contents)) continue;
|
||||
foreach($diffFile->contents as $content)
|
||||
{
|
||||
$old = array();
|
||||
$new = array();
|
||||
foreach($content->lines as $line)
|
||||
{
|
||||
if($line->type != 'new') $old[$line->oldlc] = $line->line;
|
||||
if($line->type != 'old') $new[$line->newlc] = $line->line;
|
||||
}
|
||||
$content->old = $old;
|
||||
$content->new = $new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->mr->viewDiff;
|
||||
$this->view->diffs = $diffs;
|
||||
$this->view->arrange = $arrange;
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
body {padding-bottom: 0px;}
|
||||
.w-code {width: 48%; word-break: break-all;}
|
||||
td.code {color: #484848; padding: 0px 3px; white-space: pre-wrap;}
|
||||
.none {background: #EAF2F5;}
|
||||
table.diff {margin-bottom: 0px;}
|
||||
.diff caption {border: 1px solid #e4e4e4; background: #edf3fe; margin: 0; padding: 6px 2px 6px 10px; text-align: left; font-weight: bold; font-size: 13px;}
|
||||
.diff th, .diff td {border: none;}
|
||||
.diff th {padding-top: 2px; padding-bottom: 2px;}
|
||||
.diff .line-new, .diff .line-new {background: #CFC;}
|
||||
.diff .line-old, .diff .line-old {background: #FCC;}
|
||||
.diff .line-all, .diff .line-all {background: #FFF;}
|
||||
.diff .w-num {width: 25px; border-right: 1px solid #E4E4E4; color: #999; border-left: 1px solid #E4E4E4; color: #999; font-weight: normal;}
|
||||
|
||||
.repoCode .diff tr .comment-btn .icon-wrapper {left: -23px;}
|
||||
.repoCode .diff tr.over td.line-all, .repoCode .diff tr.over td.line-all {background: #f8eec7;}
|
||||
.repoCode .diff tr.over td.line-new, .repoCode .diff tr.over td.line-new {background: #8eff8e;}
|
||||
.repoCode .diff tr.over td.line-old, .repoCode .diff tr.over td.line-old {background: #f6b2b2;}
|
||||
|
||||
.repoCode form > .btn {margin-right: 10px;}
|
||||
.label-exchange {background-color: #566F7C; cursor: pointer;}
|
||||
.label-exchange i {padding: 0;}
|
||||
.btn-download {border-right: none;}
|
||||
@@ -0,0 +1,56 @@
|
||||
$(function()
|
||||
{
|
||||
$('#gitlabID').change(function()
|
||||
{
|
||||
gitlabID = $('#gitlabID').val();
|
||||
if(gitlabID == '') return false;
|
||||
|
||||
url = createLink('repo', 'ajaxgetgitlabprojects', "gitlabID=" + gitlabID);
|
||||
$.get(url, function(response)
|
||||
{
|
||||
$('#sourceProject').html('').append(response);
|
||||
$('#sourceProject').chosen().trigger("chosen:updated");;
|
||||
});
|
||||
});
|
||||
|
||||
$('#sourceProject,#targetProject').change(function()
|
||||
{
|
||||
sourceProject = $(this).val();
|
||||
var branchSelect = $(this).parents('td').find('select[name*=Branch]');
|
||||
branchUrl = createLink('gitlab', 'ajaxgetprojectbranches', "gitlabID=" + gitlabID + "&projectID=" + sourceProject);
|
||||
$.get(branchUrl, function(response)
|
||||
{
|
||||
branchSelect.html('').append(response);
|
||||
branchSelect.chosen().trigger("chosen:updated");;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('#sourceProject').change(function()
|
||||
{
|
||||
sourceProject = $(this).val();
|
||||
projectUrl = createLink('mr', 'ajaxGetMRTargetProjects', "gitlabID=" + gitlabID + "&projectID=" + sourceProject);
|
||||
$.get(projectUrl, function(response)
|
||||
{
|
||||
$('#targetProject').html('').append(response);
|
||||
$('#targetProject').chosen().trigger("chosen:updated");;
|
||||
});
|
||||
});
|
||||
|
||||
$('#targetProject').change(function()
|
||||
{
|
||||
targetProject = $(this).val();
|
||||
var assignee = $("#assignee").parents('td').find('select[name*=assignee]');
|
||||
var reviewer = $("#reviewer").parents('td').find('select[name*=reviewer]');
|
||||
usersUrl = createLink('gitlab', 'ajaxgetmruserpairs', "gitlabID=" + gitlabID + "&projectID=" + targetProject);
|
||||
$.get(usersUrl, function(response)
|
||||
{
|
||||
assignee.html('').append(response);
|
||||
assignee.chosen().trigger("chosen:updated");;
|
||||
reviewer.html('').append(response);
|
||||
reviewer.chosen().trigger("chosen:updated");;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$("#inline").click(function(){$('#arrange').val('inline');this.form.submit();});
|
||||
$("#appose").click(function(){$('#arrange').val('appose');this.form.submit();});
|
||||
$(".label-exchange").click(function(){ $('#exchange').submit();});
|
||||
});
|
||||
|
||||
function changeEncoding(encoding)
|
||||
{
|
||||
$('#encoding').val(encoding);
|
||||
$('#encoding').parents('form').submit();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#mergeButton').click(function()
|
||||
{
|
||||
link = $(this).attr('href');
|
||||
$.getJSON(link, function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
$.zui.messager.success(response.message);
|
||||
setTimeout(function(){ location.href=response.locate }, 2500);
|
||||
}
|
||||
if(response.result == 'fail') $.zui.messager.danger(response.message);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
$lang->mr->common = "Merge Request";
|
||||
$lang->mr->create = "create";
|
||||
$lang->mr->browse = "browse";
|
||||
$lang->mr->list = "list";
|
||||
$lang->mr->edit = "edit";
|
||||
$lang->mr->delete = "delete";
|
||||
$lang->mr->view = "view";
|
||||
$lang->mr->source = 'source';
|
||||
$lang->mr->target = 'target';
|
||||
$lang->mr->viewDiff = 'view diff';
|
||||
$lang->mr->viewInGitlab = 'view in GitLab';
|
||||
|
||||
$lang->mr->id = 'ID';
|
||||
$lang->mr->mriid = "raw MR ID";
|
||||
$lang->mr->name = 'Name';
|
||||
$lang->mr->status = 'Status';
|
||||
$lang->mr->author = 'Author';
|
||||
$lang->mr->assignee = 'Assignee';
|
||||
$lang->mr->reviewer = 'Reviewer';
|
||||
$lang->mr->mergeStatus = 'Merge status';
|
||||
$lang->mr->commits = 'commits';
|
||||
$lang->mr->changes = 'changes';
|
||||
|
||||
$lang->mr->statusList = array();
|
||||
$lang->mr->statusList['opened'] = 'opened';
|
||||
$lang->mr->statusList['closed'] = 'closed';
|
||||
$lang->mr->statusList['merged'] = 'merged';
|
||||
|
||||
$lang->mr->mergeStatusList = array();
|
||||
$lang->mr->mergeStatusList['checking'] = 'checking';
|
||||
$lang->mr->mergeStatusList['can_be_merged'] = 'can be merged';
|
||||
$lang->mr->mergeStatusList['cannot_be_merged'] = 'cannot be merged';
|
||||
|
||||
$lang->mr->description = 'Description';
|
||||
$lang->mr->confirmDelete = 'Are you sure to delete this merge request?';
|
||||
$lang->mr->sourceProject = 'Source project';
|
||||
$lang->mr->sourceBranch = 'Source branch';
|
||||
$lang->mr->targetProject = 'Target project';
|
||||
$lang->mr->targetBranch = 'Target branch';
|
||||
|
||||
$lang->mr->usersTips = 'Tip: If you cannot choose the assignee and reviewer, please go to the GitLab page to bind the user first.';
|
||||
$lang->mr->notFound = "Merge Request does not exist!";
|
||||
|
||||
$lang->mr->apiError = new stdclass;
|
||||
$lang->mr->apiError->createMR = "Failed to create a merge request through API. Reason: %s";
|
||||
$lang->mr->apiError->sudo = "Unable to operate with the GitLab account bound to the current user. Reason: %s";
|
||||
|
||||
$lang->mr->createFailedFromAPI = "Failed to create Merge Request.";
|
||||
$lang->mr->accessGitlabFailed = "Unable to connect to the GitLab server.";
|
||||
|
||||
$lang->mr->from = "from";
|
||||
$lang->mr->to = "to";
|
||||
$lang->mr->at = "at";
|
||||
|
||||
$lang->mr->pipeline = "Pipeline";
|
||||
$lang->mr->pipelineSuccess = "Success";
|
||||
$lang->mr->pipelineFailed = "Failed";
|
||||
$lang->mr->pipelineCancled = "Canceled";
|
||||
$lang->mr->pipelineUnknown = "Unknown";
|
||||
|
||||
$lang->mr->pipelineStatus = array();
|
||||
$lang->mr->pipelineStatus['success'] = "success";
|
||||
$lang->mr->pipelineStatus['failed'] = "failed";
|
||||
$lang->mr->pipelineStatus['canceled'] = "canceled";
|
||||
|
||||
$lang->mr->MRHasConflicts = "Merge Request has a conflict";
|
||||
$lang->mr->hasConflicts = "There are merge conflicts or wait for push";
|
||||
$lang->mr->hasNoConflict = "Can merge";
|
||||
$lang->mr->mergeByManual = "This merge request can be merged manually, please refer to";
|
||||
$lang->mr->commandLine = "Merge Request command";
|
||||
$lang->mr->acceptMR = "Accept Merge request ";
|
||||
$lang->mr->mergeFailed = "Unable to merge request, please check the merge request status";
|
||||
$lang->mr->mergeSuccess = "Merge Request Successfully";
|
||||
|
||||
/**
|
||||
* Merge Command Document.
|
||||
*
|
||||
* %s source_project::http_url_to_repo
|
||||
* %s mr::source_branch
|
||||
* %s source_project::path_with_namespace . '-' . mr::source_branch
|
||||
* %s mr::target_branch
|
||||
* %s source_project::path_with_namespace . '-' . mr::source_branch
|
||||
* %s mr::target_branch
|
||||
*/
|
||||
$lang->mr->commandDocument = <<< EOD
|
||||
<div class='detail-title'>Check out, review and merge locally</div>
|
||||
<div class='detail-content'>
|
||||
<p><strong>Note: This merge request status will be changed after you merge locally and you will need to delete this merge request or submit new code.</strong></p>
|
||||
<p>
|
||||
step 1. Fetch and check out the branch for this merge request
|
||||
<pre>
|
||||
git fetch "%s" %s
|
||||
git checkout -b "%s" FETCH_HEAD</pre>
|
||||
</p>
|
||||
<p>
|
||||
step 2. Review the changes locally
|
||||
</p>
|
||||
<p>
|
||||
step 3. Merge the branch and fix any conflicts that come up
|
||||
<pre>
|
||||
git fetch origin
|
||||
git checkout "%s"
|
||||
git merge --no-ff "%s"</pre>
|
||||
</p>
|
||||
<p>
|
||||
step 4. Push the result of the merge to GitLab
|
||||
<pre> git push origin "%s" </pre>
|
||||
</p>
|
||||
</div>
|
||||
EOD;
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
$lang->mr->common = "合并请求";
|
||||
$lang->mr->create = "创建{$lang->mr->common}";
|
||||
$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->common}详情";
|
||||
$lang->mr->source = '源项目分支';
|
||||
$lang->mr->target = '目标项目分支';
|
||||
$lang->mr->viewDiff = '比对代码';
|
||||
$lang->mr->viewInGitlab = '在GitLab查看';
|
||||
|
||||
$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->mergeStatus = '是否可合并';
|
||||
$lang->mr->commits = '提交数';
|
||||
$lang->mr->changes = '更改数';
|
||||
$lang->mr->settings = '合并代码设置';
|
||||
|
||||
$lang->mr->statusList = array();
|
||||
$lang->mr->statusList['opened'] = '开放中';
|
||||
$lang->mr->statusList['closed'] = '已关闭';
|
||||
$lang->mr->statusList['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 = '确认删除该合并请求吗?';
|
||||
$lang->mr->sourceProject = '源项目';
|
||||
$lang->mr->sourceBranch = '源分支';
|
||||
$lang->mr->targetProject = '目标项目';
|
||||
$lang->mr->targetBranch = '目标分支';
|
||||
|
||||
$lang->mr->usersTips = '提示:如果无法选择指派人和评审人,请先前往GitLab页面绑定用户。';
|
||||
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
|
||||
|
||||
$lang->mr->apiError = new stdclass;
|
||||
$lang->mr->apiError->createMR = "通过API创建合并请求失败,失败原因:%s";
|
||||
$lang->mr->apiError->sudo = "无法以当前用户绑定的GitLab账户进行操作,失败原因:%s";
|
||||
|
||||
$lang->mr->createFailedFromAPI = "创建合并请求失败。";
|
||||
$lang->mr->accessGitlabFailed = "当前无法连接到GitLab服务器。";
|
||||
|
||||
$lang->mr->from = "从";
|
||||
$lang->mr->to = "合并到";
|
||||
$lang->mr->at = "于";
|
||||
|
||||
$lang->mr->pipeline = "流水线";
|
||||
$lang->mr->pipelineSuccess = "已通过";
|
||||
$lang->mr->pipelineFailed = "未通过";
|
||||
$lang->mr->pipelineCancled = "已取消";
|
||||
$lang->mr->pipelineUnknown = "未知";
|
||||
|
||||
$lang->mr->pipelineStatus = array();
|
||||
$lang->mr->pipelineStatus['success'] = "已通过";
|
||||
$lang->mr->pipelineStatus['failed'] = "未通过";
|
||||
$lang->mr->pipelineStatus['canceled'] = "已取消";
|
||||
|
||||
$lang->mr->MRHasConflicts = "是否存在冲突";
|
||||
$lang->mr->hasConflicts = "存在冲突或等待提交";
|
||||
$lang->mr->hasNoConflict = "可以合并";
|
||||
$lang->mr->mergeByManual = "此合并请求可以手动合并,请使用以下";
|
||||
$lang->mr->commandLine = "合并命令";
|
||||
$lang->mr->acceptMR = "合并";
|
||||
$lang->mr->mergeFailed = "无法合并,请核对合并请求状态";
|
||||
$lang->mr->mergeSuccess = "已成功合并";
|
||||
|
||||
/**
|
||||
* Merge Command Document.
|
||||
*
|
||||
* %s source_project::http_url_to_repo
|
||||
* %s mr::source_branch
|
||||
* %s source_project::path_with_namespace . '-' . mr::source_branch
|
||||
* %s mr::target_branch
|
||||
* %s source_project::path_with_namespace . '-' . mr::source_branch
|
||||
* %s mr::target_branch
|
||||
*/
|
||||
$lang->mr->commandDocument = <<< EOD
|
||||
<div class='detail-title'>在本地检出、审核和手动合并</div>
|
||||
<div class='detail-content'>
|
||||
<p><strong>注意:您在本地合并后此合并请求将变为不可合并状态,需要删除此合并请求或者提交新的代码。</strong></p>
|
||||
<p>
|
||||
第 1 步. 获取并查看此合并请求的分支
|
||||
<pre>
|
||||
git fetch "%s" %s
|
||||
git checkout -b "%s" FETCH_HEAD</pre>
|
||||
</p>
|
||||
<p>
|
||||
第 2 步. 在本地查看更改
|
||||
</p>
|
||||
<p>
|
||||
第 3 步. 合并分支并解决出现的任何冲突
|
||||
<pre>
|
||||
git fetch origin
|
||||
git checkout "%s"
|
||||
git merge --no-ff "%s"</pre>
|
||||
</p>
|
||||
<p>
|
||||
第 4 步. 将合并结果推送到GitLab
|
||||
<pre> git push origin "%s" </pre>
|
||||
</p>
|
||||
</div>
|
||||
EOD;
|
||||
@@ -0,0 +1,490 @@
|
||||
<?php
|
||||
/**
|
||||
* The model file of mr module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author dingguodong <dingguodong@easycorp.ltd>
|
||||
* @package mr
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class mrModel extends model
|
||||
{
|
||||
/**
|
||||
* The construct method, to do some auto things.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->loadModel('gitlab');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MR by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getByID($id)
|
||||
{
|
||||
return $this->dao->findByID($id)->from(TABLE_MR)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MR list of gitlab project.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getList($orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
$MRList = $this->dao->select('*')
|
||||
->from(TABLE_MR)
|
||||
->where('deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
return $MRList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gitlab pairs.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getPairs($repoID)
|
||||
{
|
||||
$MR = $this->dao->select('id,title')
|
||||
->from(TABLE_MR)
|
||||
->where('deleted')->eq('0')
|
||||
->AndWhere('repoID')->eq($repoID)
|
||||
->orderBy('id')->fetchPairs('id', 'title');
|
||||
return array('' => '') + $MR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create MR function.
|
||||
*
|
||||
* @access public
|
||||
* @return int|bool|object
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$MR = fixer::input('post')
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->get();
|
||||
|
||||
$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 array('result' => 'fail', 'message' => dao::getError());
|
||||
|
||||
$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.
|
||||
* The type of variable `$rawMR->message` is array.
|
||||
*/
|
||||
if(isset($rawMR->message) and !isset($rawMR->iid))
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_MR)->where('id')->eq($MRID)->exec();
|
||||
return array('result' => 'fail', 'message' => sprintf($this->lang->mr->apiError->createMR, $rawMR->message[0]));
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
$newMR = new stdclass;
|
||||
$newMR->mriid = $rawMR->iid;
|
||||
$newMR->status = $rawMR->state;
|
||||
$newMR->mergeStatus = $rawMR->merge_status;
|
||||
|
||||
/* Change gitlab user ID to zentao account. */
|
||||
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID);
|
||||
$newMR->assignee = zget($gitlabUsers, $MR->assignee, '');
|
||||
$newMR->reviewer = zget($gitlabUsers, $MR->reviewer, '');
|
||||
|
||||
/* Update MR in Zentao database. */
|
||||
$this->dao->update(TABLE_MR)->data($newMR)
|
||||
->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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit MR function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function update($MRID)
|
||||
{
|
||||
$MR = fixer::input('post')
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->setDefault('editedDate', helper::now())
|
||||
->get();
|
||||
|
||||
/* Update MR in GitLab. */
|
||||
$newMR = new stdclass;
|
||||
$newMR->title = $MR->title;
|
||||
$newMR->description = $MR->description;
|
||||
$newMR->assignee_ids = $MR->assignee;
|
||||
$newMR->reviewer_ids = $MR->reviewer;
|
||||
$newMR->target_branch = $MR->targetBranch;
|
||||
|
||||
$oldMR = $this->getByID($MRID);
|
||||
|
||||
/* Known issue: `reviewer_ids` takes no effect. */
|
||||
$rawMR = $this->apiUpdateMR($oldMR->gitlabID, $oldMR->targetProject, $oldMR->mriid, $newMR);
|
||||
|
||||
/* Change gitlab user ID to zentao account. */
|
||||
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($oldMR->gitlabID);
|
||||
$MR->assignee = zget($gitlabUsers, $MR->assignee, '');
|
||||
$MR->reviewer = zget($gitlabUsers, $MR->reviewer, '');
|
||||
|
||||
/* Update MR in Zentao database. */
|
||||
$this->dao->update(TABLE_MR)->data($MR)
|
||||
->where('id')->eq($MRID)
|
||||
->autoCheck()
|
||||
->exec();
|
||||
$MR = $this->getByID($MRID);
|
||||
|
||||
if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
|
||||
return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'browse'));
|
||||
}
|
||||
|
||||
/**
|
||||
* sync MR from GitLab API to Zentao database.
|
||||
*
|
||||
* @param object $MR
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function apiSyncMR($MR)
|
||||
{
|
||||
$rawMR = $this->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid);
|
||||
/* Sync MR in ZenTao database whatever status of MR in GitLab. */
|
||||
if(isset($rawMR->iid))
|
||||
{
|
||||
$map = $this->config->MR->maps->sync;
|
||||
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID);
|
||||
|
||||
$newMR = new stdclass;
|
||||
foreach($map as $syncField => $config)
|
||||
{
|
||||
$value = '';
|
||||
list($field, $optionType, $options) = explode('|', $config);
|
||||
|
||||
if($optionType == 'field') $value = $rawMR->$field;
|
||||
if($optionType == 'userPairs')
|
||||
{
|
||||
$gitlabUserID = '';
|
||||
if(isset($rawMR->$field[0]))
|
||||
{
|
||||
$gitlabUserID = $rawMR->$field[0]->$options;
|
||||
}
|
||||
$value = zget($gitlabUsers, $gitlabUserID, '');
|
||||
}
|
||||
|
||||
if($value) $newMR->$syncField = $value;
|
||||
}
|
||||
|
||||
/* Update MR in Zentao database. */
|
||||
$this->dao->update(TABLE_MR)->data($newMR)
|
||||
->where('id')->eq($MR->id)
|
||||
->exec();
|
||||
}
|
||||
return $this->dao->findByID($MR->id)->from(TABLE_MR)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch Sync GitLab MR Database.
|
||||
*
|
||||
* @param object $MRList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchSyncMR($MRList)
|
||||
{
|
||||
if(!empty($MRList)) foreach($MRList as $key => $MR)
|
||||
{
|
||||
if($MR->status != 'opened') continue;
|
||||
$rawMR = $this->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid);
|
||||
if(isset($rawMR->iid))
|
||||
{
|
||||
/* create gitlab mr todo to zentao todo */
|
||||
$this->batchSyncTodo($MR->gitlabID, $MR->targetProject);
|
||||
|
||||
$map = $this->config->MR->maps->sync;
|
||||
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID);
|
||||
|
||||
$newMR = new stdclass;
|
||||
|
||||
foreach($map as $syncField => $config)
|
||||
{
|
||||
$value = '';
|
||||
list($field, $optionType, $options) = explode('|', $config);
|
||||
|
||||
if($optionType == 'field') $value = $rawMR->$field;
|
||||
if($optionType == 'userPairs')
|
||||
{
|
||||
$gitlabUserID = '';
|
||||
if(isset($rawMR->$field[0]))
|
||||
{
|
||||
$gitlabUserID = $rawMR->$field[0]->$options;
|
||||
}
|
||||
$value = zget($gitlabUsers, $gitlabUserID, '');
|
||||
}
|
||||
|
||||
if($value) $newMR->$syncField = $value;
|
||||
}
|
||||
/* Update MR in Zentao database. */
|
||||
$this->dao->update(TABLE_MR)->data($newMR)
|
||||
->where('id')->eq($MR->id)
|
||||
->exec();
|
||||
|
||||
/* Refetch MR in Zentao database. */
|
||||
$MR = $this->dao->findByID($MR->id)->from(TABLE_MR)->fetch();
|
||||
$MRList[$key] = $MR;
|
||||
}
|
||||
}
|
||||
|
||||
return $MRList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync GitLab Todo to ZenTao Todo.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchSyncTodo($gitlabID, $projectID)
|
||||
{
|
||||
$todoList = $this->loadModel('gitlab')->apiTodoList($gitlabID, $projectID);
|
||||
|
||||
if(!empty($todoList))
|
||||
{
|
||||
foreach($todoList as $do)
|
||||
{
|
||||
$todoDesc = $this->dao->select('*')
|
||||
->from(TABLE_TODO)
|
||||
->where('idvalue')->eq($do->id)
|
||||
->fetch();
|
||||
if(empty($todoDesc))
|
||||
{
|
||||
$todo = new stdClass;
|
||||
$todo->account = $this->app->user->account;
|
||||
$todo->assignedTo = $this->app->user->account;
|
||||
$todo->assignedBy = $this->app->user->account;
|
||||
$todo->date = $do->target->created_at;
|
||||
$todo->assignedDate = $do->target->created_at;
|
||||
$todo->begin = $do->target->created_at;
|
||||
$todo->type = 'mrapprove';
|
||||
$todo->idvalue = $do->id;
|
||||
$todo->pri = 1;
|
||||
$todo->name = $do->target->title;
|
||||
$todo->desc = $do->target->description . "<br>" . '<a href="' . $this->todoDescriptionLink($gitlabID, $projectID) . '"target="_blank">' . $this->todoDescriptionLink($gitlabID, $projectID) .'</a>';
|
||||
$todo->finishedBy = $this->app->user->account;
|
||||
$this->dao->insert(TABLE_TODO)->data($todo)->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of to-do items.
|
||||
*
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function todoDescriptionLink($gitlabID, $projectID)
|
||||
{
|
||||
$gitlab = $this->loadModel('gitlab')->getByID($gitlabID);
|
||||
if(!$gitlab) return '';
|
||||
return rtrim($gitlab->url, '/')."/dashboard/todos?project_id=$projectID&type=MergeRequest";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create MR by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param object $MR
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiCreateMR($gitlabID, $projectID, $MR)
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests");
|
||||
return json_decode(commonModel::http($url, $MR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MR list by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetMRList($gitlabID, $projectID)
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single MR by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID targetProject
|
||||
* @param int $MRID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiGetSingleMR($gitlabID, $projectID, $MRID)
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID");
|
||||
return json_decode(commonModel::http($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update MR by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#update-mr
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $MRID
|
||||
* @param object $MR
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiUpdateMR($gitlabID, $projectID, $MRID, $MR)
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID");
|
||||
return json_decode(commonModel::http($url, $MR, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete MR by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#delete-a-merge-request
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $MRID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiDeleteMR($gitlabID, $projectID, $MRID)
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID");
|
||||
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept MR by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#accept-mr
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @param int $MRID
|
||||
* @param string $sudo
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function apiAcceptMR($gitlabID, $projectID, $MRID, $sudo = "")
|
||||
{
|
||||
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/merge");
|
||||
if($sudo != "") return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT'), $headers = array("sudo: {$sudo}")));
|
||||
return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MR diff versions by API.
|
||||
*
|
||||
* @docs https://docs.gitlab.com/ee/api/merge_requests.html#get-mr-diff-versions
|
||||
* @param object $MR
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getDiffs($MR)
|
||||
{
|
||||
$gitlab = $this->gitlab->getByID($MR->gitlabID);
|
||||
|
||||
$this->loadModel('repo');
|
||||
$repo = new stdclass;
|
||||
$repo->SCM = 'GitLab';
|
||||
$repo->gitlab = $gitlab->id;
|
||||
$repo->project = $MR->targetProject;
|
||||
$repo->path = sprintf($this->config->repo->gitlab->apiPath, $gitlab->url, $MR->targetProject);
|
||||
$repo->client = $gitlab->url;
|
||||
$repo->password = $gitlab->token;
|
||||
|
||||
$scm = $this->app->loadClass('scm');
|
||||
$scm->setEngine($repo);
|
||||
|
||||
$encoding = empty($encoding) ? $repo->encoding : $encoding;
|
||||
$encoding = strtolower(str_replace('_', '-', $encoding));
|
||||
return $scm->diff('', $MR->sourceBranch, $MR->targetBranch, $parse = true, $MR->sourceProject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sudo user ID in both GitLab and Project.
|
||||
* Note: sudo parameter in GitLab API can be user ID or username.
|
||||
* @param int $gitlabID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return int|string
|
||||
*/
|
||||
public function getSudoUsername($gitlabID, $projectID)
|
||||
{
|
||||
$zentaoUser = $this->app->user->account;
|
||||
|
||||
/* Fetch user list both in Zentao and current GitLab project. */
|
||||
$bindedUsers = $this->gitlab->getUserAccountIdPairs($gitlabID);
|
||||
$rawProjectUsers = $this->gitlab->apiGetProjectUsers($gitlabID, $projectID);
|
||||
$users = array();
|
||||
foreach($rawProjectUsers as $rawProjectUser)
|
||||
{
|
||||
if(!empty($bindedUsers[$rawProjectUser->username])) $users[$rawProjectUser->username] = $bindedUsers[$rawProjectUser->username];
|
||||
}
|
||||
if(!empty($users[$zentaoUser])) return $users[$zentaoUser];
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* The view file for browse page of mr module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Guodong Ding
|
||||
* @package mr
|
||||
* @version $Id: create.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class='pull-right'>
|
||||
<?php common::printLink('mr', 'create', '', "<i class='icon icon-plus'></i> " . $lang->mr->create, '', "class='btn btn-primary'");?>
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent'>
|
||||
<?php if(empty($MRList)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p>
|
||||
<span class="text-muted"><?php echo $lang->noData . $lang->mr->common;?></span>
|
||||
<?php if(common::hasPriv('mr', 'create')):?>
|
||||
<?php echo html::a($this->createLink('mr', 'create'), "<i class='icon icon-plus'></i> " . $lang->mr->create, '', "class='btn btn-info'");?>
|
||||
<?php endif;?>
|
||||
</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='gitlabProjectList' class='table has-sort-head table-fixed'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $vars = "objectID=$objectID&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; ?>
|
||||
<th class='w-60px text-left'><?php common::printOrderLink('id', $orderBy, $vars, $lang->mr->id); ?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('title', $orderBy, $vars, $lang->mr->name); ?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('sourceProject', $orderBy, $vars, $lang->mr->sourceProject); ?></th>
|
||||
<th class='w-100px text-left'><?php common::printOrderLink('sourceBranch', $orderBy, $vars, $lang->mr->sourceBranch); ?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('targetProject', $orderBy, $vars, $lang->mr->targetProject); ?></th>
|
||||
<th class='w-100px text-left'><?php common::printOrderLink('targetBranch', $orderBy, $vars, $lang->mr->targetBranch); ?></th>
|
||||
<th class='w-100px text-left'><?php common::printOrderLink('mergeStatus', $orderBy, $vars, $lang->mr->mergeStatus); ?></th>
|
||||
<th class='w-120px c-actions-4'><?php echo $lang->actions; ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($MRList as $MR):?>
|
||||
<tr>
|
||||
<td class='text'><?php echo $MR->id; ?></td>
|
||||
<td class='text'><?php echo $MR->title; ?></td>
|
||||
<td class='text'><?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->sourceProject)->name_with_namespace; ?></td>
|
||||
<td class='text'><?php echo $MR->sourceBranch;?></td>
|
||||
<td class='text'><?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace; ?></td>
|
||||
<td class='text'><?php echo $MR->targetBranch;?></td>
|
||||
<td class='text'><?php echo ($MR->status == 'merged') ? zget($lang->mr->statusList, $MR->status) : zget($lang->mr->mergeStatusList, $MR->mergeStatus); ?></td>
|
||||
<td class='text-left c-actions'>
|
||||
<?php
|
||||
common::printLink('mr', 'view', "mr={$MR->id}", '<i class="icon icon-eye"></i>', '', "title='{$lang->mr->view}' class='btn btn-info'");
|
||||
common::printLink('mr', 'edit', "mr={$MR->id}", '<i class="icon icon-edit"></i>', '', "title='{$lang->mr->edit}' class='btn btn-info'");
|
||||
/* Function diff is not ready yet. so comment it. */
|
||||
//common::printLink('mr', 'diff', "mr={$MR->id}", '<i class="icon icon-review"></i>', '', "title='{$lang->mr->viewDiff}' class='btn btn-info'");
|
||||
common::printLink('mr', 'delete', "mr={$MR->id}", '<i class="icon icon-trash"></i>', '', "title='{$lang->mr->delete}' class='btn btn-info'");
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
</form>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* The create view file of mr module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Guodong
|
||||
* @package mr
|
||||
* @version $Id: create.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->mr->create;?></h2>
|
||||
</div>
|
||||
<form id='mrForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->gitlab->common;?></th>
|
||||
<td class='required'><?php echo html::select('gitlabID', $gitlabHosts, '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->sourceProject;?></th>
|
||||
<td class='required'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select('sourceProject', array(''), '', "class='form-control chosen'");?>
|
||||
<span class='input-group-addon fix-border'><?php echo $lang->mr->sourceBranch ?></span>
|
||||
<?php echo html::select('sourceBranch', array(''), '', "class='form-control chosen'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->targetProject;?></th>
|
||||
<td class='required'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select('targetProject', array(''), '', "class='form-control chosen'");?>
|
||||
<span class='input-group-addon fix-border'><?php echo $lang->mr->targetBranch ?></span>
|
||||
<?php echo html::select('targetBranch', array(''), '', "class='form-control chosen'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->name;?></th>
|
||||
<td class='required'><?php echo html::input('title', '', "class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->description; ?></th>
|
||||
<td colspan='1'><?php echo html::textarea('description', '', "rows='3' class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->assignee;?></th>
|
||||
<td><?php echo html::select('assignee', array(''), '', "class='form-control chosen'")?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->reviewer;?></th>
|
||||
<td><?php echo html::select('reviewer', array(''), '', "class='form-control chosen'")?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td><?php echo $lang->mr->usersTips;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td colspan='2' class='text-left form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/**
|
||||
* The diff view file of repo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Xiying Guan
|
||||
* @package repo
|
||||
* @version $Id: browse.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/form.html.php';?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php
|
||||
$backURI = $this->session->mrView ? $this->session->mrView : $this->session->mrList;
|
||||
if($backURI)
|
||||
{
|
||||
echo html::a($backURI, "<i class='icon icon-back icon-sm'></i> " . $lang->goback, '', "class='btn btn-link' data-app='{$app->openApp}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::backButton("<i class='icon icon-back icon-sm'></i> " . $lang->goback, '', "btn btn-link");
|
||||
}
|
||||
?>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="repo panel">
|
||||
<div class='panel-heading'>
|
||||
<form method='post'>
|
||||
<div class='btn-group pull-right'>
|
||||
<?php echo html::commonButton($lang->repo->viewDiffList['inline'], "id='inline'", $arrange == 'inline' ? 'active btn btn-sm' : 'btn btn-sm')?>
|
||||
<?php echo html::commonButton($lang->repo->viewDiffList['appose'], "id='appose'", $arrange == 'appose' ? 'active btn btn-sm' : 'btn btn-sm')?>
|
||||
</div>
|
||||
<div class='btn-toolbar'>
|
||||
<div class='btn-group'>
|
||||
<div class='btn-group'>
|
||||
<?php echo html::commonButton(zget($lang->repo->encodingList, $encoding, $lang->repo->encoding) . "<span class='caret'></span>", "data-toggle='dropdown'", 'btn dropdown-toggle btn-sm')?>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<?php foreach($lang->repo->encodingList as $key => $val):?>
|
||||
<li><?php echo html::a('javascript:changeEncoding("'. $key . '")', $val)?></li>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo html::hidden('arrange', $arrange) . html::hidden('encoding', $encoding) . html::hidden('revision[]', $newRevision) . html::hidden('revision[]', $oldRevision)?>
|
||||
</form>
|
||||
</div>
|
||||
<?php foreach($diffs as $diffFile):?>
|
||||
<div class='repoCode'>
|
||||
<table class='table diff' id='diff'>
|
||||
<caption><?php echo $diffFile->fileName;?></caption>
|
||||
<?php if(empty($diffFile->contents)) continue;?>
|
||||
<?php foreach($diffFile->contents as $content):?>
|
||||
<?php
|
||||
$oldCurrentLine = $content->oldStartLine;
|
||||
$newCurrentLine = $content->newStartLine;
|
||||
?>
|
||||
<?php if(!in_array($oldCurrentLine, array('0', '1')) and !in_array($newCurrentLine, array('0', '1'))):?>
|
||||
<tr data-line='<?php echo $newCurrentLine ?>' class='empty'>
|
||||
<th class='w-num text-center'>...</th>
|
||||
<?php if($arrange == 'appose'):?>
|
||||
<td class='none code'></td>
|
||||
<?php endif;?>
|
||||
<th class='w-num text-center'>...</th>
|
||||
<td class='none code'></td>
|
||||
</tr>
|
||||
<?php endif?>
|
||||
<?php if($arrange == 'inline'):?>
|
||||
<?php foreach($content->lines as $line):?>
|
||||
<tr data-line='<?php echo $line->newlc ?>'>
|
||||
<th class='w-num text-right'><?php if($line->type != 'new') echo $line->oldlc?></th>
|
||||
<th class='w-num text-left'><?php if($line->type != 'old') echo $line->newlc?></th>
|
||||
<td class='line-<?php echo $line->type?> code'><?php
|
||||
$line->line = $repo->SCM == 'Subversion' ? htmlspecialchars($line->line) : $line->line;
|
||||
echo $line->type == 'old' ? preg_replace('/^\-/', '–', $line->line) : ($line->type == 'new' ? $line->line : ' ' . $line->line);
|
||||
?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php else:?>
|
||||
<?php foreach($content->lines as $line):?>
|
||||
<tr data-line='<?php echo $line->newlc ?>'>
|
||||
<?php
|
||||
if($line->type == 'old')
|
||||
{
|
||||
$oldlc = $line->oldlc;
|
||||
$newlc = '';
|
||||
if(isset($content->new[$oldlc]))
|
||||
{
|
||||
$newlc = $line->oldlc;
|
||||
$line->type = 'custom';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oldlc = $line->oldlc;
|
||||
$newlc = $line->newlc;
|
||||
if(!isset($content->new[$newlc])) continue;
|
||||
}
|
||||
?>
|
||||
<th class='w-num text-right'><?php echo $oldlc?></th>
|
||||
<td class='w-code line-<?php if($line->type != 'new')echo $line->type?> <?php if($line->type == 'custom') echo "line-old"?> code'><?php
|
||||
if(!isset($content->old[$oldlc])) $content->old[$oldlc] = '';
|
||||
$content->old[$oldlc] = $repo->SCM == 'Subversion' ? htmlspecialchars($content->old[$oldlc]) : $content->old[$oldlc];
|
||||
if(!empty($oldlc)) echo $line->type != 'all' ? preg_replace('/^\-/', '–', $content->old[$oldlc]) : ' ' . $content->old[$oldlc];
|
||||
?></td>
|
||||
<th class='w-num text-right'><?php echo $newlc?></th>
|
||||
<td class='w-code line-<?php if($line->type != 'old') echo $line->type?> <?php if($line->type == 'custom') echo "line-new"?> code'><?php
|
||||
if(!isset($content->new[$newlc])) $content->new[$newlc] = '';
|
||||
$content->new[$newlc] = $repo->SCM == 'Subversion' ? htmlspecialchars($content->new[$newlc]) : $content->new[$newlc];
|
||||
if(!empty($newlc)) echo $line->type != 'all' ? $content->new[$newlc] : ' ' . $content->new[$newlc];
|
||||
?></td>
|
||||
<?php
|
||||
if(isset($content->old[$oldlc])) unset($content->old[$oldlc]);
|
||||
if(isset($content->new[$newlc])) unset($content->new[$newlc]);
|
||||
?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach?>
|
||||
</div>
|
||||
<div class='revisions hidden'>
|
||||
<?php
|
||||
if(strpos($repo->SCM, 'Subversion') === false)
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? "$newRevision" : $oldRevision;
|
||||
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . $historys[$oldRevision] . ' : ' . $historys[$newRevision] . ')</span>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$oldRevision = $oldRevision == '^' ? $newRevision - 1 : $oldRevision;
|
||||
echo " <span class='label label-info'>$oldRevision : $newRevision</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<form method="post" id="exchange" class="hidden">
|
||||
<input type="hidden" name="revision[]" value="<?php echo $oldRevision;?>"/>
|
||||
<input type="hidden" name="revision[]" value="<?php echo $newRevision;?>"/>
|
||||
</form>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* The edit view file of mr module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package mr
|
||||
* @version $Id: create.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->mr->edit;?></h2>
|
||||
</div>
|
||||
<form id='mrForm' method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->gitlab->common;?></th>
|
||||
<td><?php echo $this->loadModel('gitlab')->getByID($MR->gitlabID)->name;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->sourceProject;?></th>
|
||||
<td>
|
||||
<div>
|
||||
<span class='fix-border text-left'>
|
||||
<?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->sourceProject)->name_with_namespace; ?>:
|
||||
<?php echo $MR->sourceBranch;?>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->targetProject;?></th>
|
||||
<td class='required'>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon fix-border'>
|
||||
<?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace;?>
|
||||
</span>
|
||||
<?php echo html::select('targetBranch', $targetBranchList, $MR->targetBranch, "class='form-control chosen'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->name;?></th>
|
||||
<td class='required'><?php echo html::input('title', $MR->title, "class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->description; ?></th>
|
||||
<td colspan='1'><?php echo html::textarea('description', $MR->description, "rows='3' class='form-control'"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->assignee;?></th>
|
||||
<td><?php echo html::select('assignee', $users, $assignee, "class='form-control chosen'")?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->mr->reviewer;?></th>
|
||||
<td><?php echo html::select('reviewer', $users, $reviewer, "class='form-control chosen'")?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td><?php echo $lang->mr->usersTips;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td colspan='2' class='text-left form-actions'>
|
||||
<?php echo html::submitButton(); ?>
|
||||
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php'; ?>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php if(!isset($MR->id)):?>
|
||||
<div id='mainContent'>
|
||||
<div class="table-empty-tip">
|
||||
<p>
|
||||
<span class="text-muted"><?php echo $lang->mr->notFound;?></span>
|
||||
<?php if(common::hasPriv('mr', 'create')):?>
|
||||
<?php echo html::a($this->createLink('mr', 'create'), "<i class='icon icon-plus'></i> " . $lang->mr->create, '', "class='btn btn-info'");?>
|
||||
<?php endif;?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php echo html::a($this->createLink('mr', 'browse'), '<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', "class='btn btn-secondary'");?>
|
||||
<div class="divider"></div>
|
||||
<div class="page-title">
|
||||
<span class="label label-id"><?php echo $MR->id?></span>
|
||||
<span class="text" title='<?php echo $MR->title;?>'><?php echo $MR->title;?></span>
|
||||
<span class="text" title='<?php echo $MR->title;?>' style='color: blue'><?php echo html::a($rawMR->web_url, $lang->mr->viewInGitlab, "_blank", "class='btn btn-link btn-active-text' style='color: blue'");?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mainContent" class="main-row">
|
||||
<div class="main-col">
|
||||
<div class="cell">
|
||||
<div class="detail">
|
||||
<div class="detail-title">
|
||||
<div><?php echo $lang->mr->from . html::a($sourceProjectURL, $sourceProjectName . ":" . $MR->sourceBranch, "_blank", "class='btn btn-link btn-active-text' style='color: blue'") . $lang->mr->to . html::a($targetProjectURL, $targetProjectName . ":" . $MR->targetBranch, "_blank", "class='btn btn-link btn-active-text' style='color: blue'");?></div>
|
||||
</div>
|
||||
<div class="detail-content article-content">
|
||||
<strong><?php echo $lang->mr->status;?></strong>
|
||||
<?php echo zget($lang->mr->statusList, $MR->status);?>
|
||||
<br>
|
||||
<?php if(isset($rawMR->head_pipeline->status)):?>
|
||||
<div>
|
||||
<strong><?php echo "{$lang->mr->pipeline}{$lang->mr->status}";?></strong>
|
||||
<?php echo zget($lang->mr->pipelineStatus, $rawMR->head_pipeline->status, $lang->mr->pipelineUnknown);?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<strong><?php echo $lang->mr->mergeStatus;?> </strong>
|
||||
<?php echo zget($lang->mr->mergeStatusList, $rawMR->merge_status);?>
|
||||
<br>
|
||||
<strong><?php echo $lang->mr->MRHasConflicts;?></strong>
|
||||
<?php echo ($rawMR->has_conflicts ? $lang->mr->hasConflicts : $lang->mr->hasNoConflict);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="detail">
|
||||
<div class="detail-title"><?php echo $lang->mr->description;?></div>
|
||||
<div class="detail-content article-content">
|
||||
<?php echo !empty($MR->description) ? $MR->description : "<div class='text-center text-muted'>" . $lang->noData . '</div>';?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($rawMR->state == 'opened'):?>
|
||||
<div class="cell"><?php echo sprintf($lang->mr->commandDocument, $httpRepoURL, $MR->sourceBranch, $branchPath, $MR->targetBranch, $branchPath, $MR->targetBranch);?></div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<?php if($rawMR->state == 'opened' and !$rawMR->has_conflicts):?>
|
||||
<?php echo html::a(inlink( 'accept', "mr=$MR->id"), '<i class="icon icon-checked"></i> ' . $lang->mr->acceptMR, '', "id='mergeButton' class='btn btn-wide btn-primary'");?>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -87,9 +87,9 @@ class repo extends control
|
||||
|
||||
/* Pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$recTotal = count($repoList);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$repoList = array_chunk($repoList, $pager->recPerPage);
|
||||
$recTotal = count($repoList);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$repoList = array_chunk($repoList, $pager->recPerPage);
|
||||
|
||||
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->browse;
|
||||
$this->view->position[] = $this->lang->repo->common;
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($repoList):?>
|
||||
<div class='table-footer'><?php $pager->show('rignt', 'pagerjs');?></div>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
<?php endif;?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -96,12 +96,13 @@ $lang->todo->priList[2] = 2;
|
||||
$lang->todo->priList[3] = 3;
|
||||
$lang->todo->priList[4] = 4;
|
||||
|
||||
$lang->todo->typeList['custom'] = '自定义';
|
||||
$lang->todo->typeList['cycle'] = '周期';
|
||||
$lang->todo->typeList['bug'] = 'Bug';
|
||||
$lang->todo->typeList['task'] = '任务';
|
||||
$lang->todo->typeList['story'] = $lang->SRCommon;
|
||||
$lang->todo->typeList['testtask'] = '测试单';
|
||||
$lang->todo->typeList['custom'] = '自定义';
|
||||
$lang->todo->typeList['cycle'] = '周期';
|
||||
$lang->todo->typeList['bug'] = 'Bug';
|
||||
$lang->todo->typeList['task'] = '任务';
|
||||
$lang->todo->typeList['story'] = $lang->SRCommon;
|
||||
$lang->todo->typeList['testtask'] = '测试单';
|
||||
$lang->todo->typeList['mrapprove'] = '合并请求审批';
|
||||
|
||||
$lang->todo->confirmDelete = "您确定要删除这条待办吗?";
|
||||
$lang->todo->thisIsPrivate = '这是一条私人事务。:)';
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if($webhooks):?>
|
||||
<div class='table-footer'><?php $pager->show('rignt', 'pagerjs');?></div>
|
||||
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
|
||||
<?php endif;?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user