| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333 |
- <?php
- /**
- * The model file of mr module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
- * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author dingguodong <dingguodong@easycorp.ltd>
- * @package mr
- * @link https://www.zentao.net
- * @property gitlabModel $gitlab
- */
- class mrModel extends model
- {
- public $moduleName = 'mr';
- public function __construct($appName = '')
- {
- parent::__construct($appName);
- if($this->app->rawModule == 'pullreq') $this->moduleName = 'pullreq';
- }
- /**
- * 获取合并请求列表.
- * Get MR list of gitlab project.
- *
- * @param string $mode
- * @param string $param
- * @param string $orderBy
- * @param array $filterProjects
- * @param int $repoID
- * @param int $objectID
- * @param object $pager
- * @access public
- * @return array
- */
- public function getList($mode = 'all', $param = 'all', $orderBy = 'id_desc', $filterProjects = array(), $repoID = 0, $objectID = 0, $pager = null)
- {
- $filterProjectSql = '';
- if(!$this->app->user->admin && !empty($filterProjects))
- {
- foreach($filterProjects as $hostID => $projectID)
- {
- $filterProjectSql .= "(hostID = {$hostID} AND sourceProject = '{$projectID}') OR ";
- }
- if($filterProjectSql) $filterProjectSql = '(' . substr($filterProjectSql, 0, -3) . ')'; // Remove last or.
- }
- if($this->app->tab == 'project')
- {
- $executionIdList = $this->loadModel('execution')->fetchExecutionList($objectID, 'all');
- if(!empty($executionIdList)) $objectID = array_merge(array_keys($executionIdList), array($objectID));
- }
- return $this->dao->select('*')->from(TABLE_MR)
- ->where('deleted')->eq('0')
- ->beginIF($mode == 'status' && $param != 'all')->andWhere('status')->eq($param)->fi()
- ->beginIF($mode == 'assignee' && $param != 'all')->andWhere('assignee')->eq($param)->fi()
- ->beginIF($mode == 'creator' && $param != 'all')->andWhere('createdBy')->eq($param)->fi()
- ->beginIF($filterProjectSql)->andWhere($filterProjectSql)->fi()
- ->beginIF($repoID)->andWhere('repoID')->eq($repoID)->fi()
- ->beginIF($this->moduleName == 'mr')->andWhere('isFlow')->eq('0')->fi()
- ->beginIF($this->moduleName == 'pullreq')->andWhere('isFlow')->eq('1')->fi()
- ->beginIF($objectID && $this->moduleName == 'mr')->andWhere('executionID')->in($objectID)->fi()
- ->orderBy($orderBy)
- ->page($pager)
- ->fetchAll('id');
- }
- /**
- * 根据代码库ID获取合并请求列表.
- * Get MR list by repoID.
- *
- * @access public
- * @return array
- * @param int $repoID
- */
- public function getPairs($repoID)
- {
- return $this->dao->select('id,title')
- ->from(TABLE_MR)
- ->where('deleted')->eq('0')
- ->andWhere('repoID')->eq($repoID)
- ->orderBy('id')
- ->fetchPairs('id', 'title');
- }
- /**
- * 获取Gitea服务器的项目.
- * Get gitea projects.
- *
- * @param int $hostID
- * @access public
- * @return array
- */
- public function getGiteaProjects($hostID = 0)
- {
- $projects = $this->loadModel('gitea')->apiGetProjects($hostID);
- return array($hostID => helper::arrayColumn($projects, null, 'full_name'));
- }
- /**
- * 获取Gogs服务器的项目.
- * Get gogs projects.
- *
- * @param int $hostID
- * @access public
- * @return array
- */
- public function getGogsProjects($hostID = 0)
- {
- $projects = $this->loadModel('gogs')->apiGetProjects($hostID);
- return array($hostID => helper::arrayColumn($projects, null, 'full_name'));
- }
- /**
- * 获取Gitlab服务器的项目.
- * Get gitlab projects.
- *
- * @param int $hostID
- * @param array $projectIdList
- * @access public
- * @return array
- */
- public function getGitlabProjects($hostID = 0, $projectIdList = array())
- {
- if(!$this->app->user->admin)
- {
- $gitlabUsers = $this->loadModel('pipeline')->getProviderPairsByAccount('gitlab');
- if(!isset($gitlabUsers[$hostID])) return array();
- }
- $minProject = $maxProject = 0;
- /* Mysql string to int. */
- $MR = $this->dao->select('min(CAST(sourceProject AS DECIMAL)) as minSource, MAX(CAST(sourceProject AS DECIMAL)) as maxSource,MIN(CAST(targetProject AS DECIMAL)) as minTarget,MAX(CAST(targetProject AS DECIMAL)) as maxTarget')->from(TABLE_MR)
- ->where('deleted')->eq('0')
- ->andWhere('hostID')->eq($hostID)
- ->beginIF($projectIdList)->andWhere('sourceProject', true)->in($projectIdList)
- ->orWhere('targetProject')->in($projectIdList)
- ->markRight(1)
- ->fi()
- ->fetch();
- if(empty($MR->minSource) && empty($MR->minTarget)) return array();
- $minProject = min($MR->minSource, $MR->minTarget);
- $maxProject = max($MR->maxSource, $MR->maxTarget);
- /* If not an administrator, need to obtain group member information. */
- $groupIDList = array(0 => 0);
- $this->loadModel('gitlab');
- if(!$this->app->user->admin)
- {
- $groups = $this->gitlab->apiGetGroups($hostID, 'name_asc', 'reporter');
- foreach($groups as $group) $groupIDList[] = $group->id;
- }
- $allProjectPairs = array();
- $allProjects = $this->gitlab->apiGetProjects($hostID, 'false', (int)$minProject, (int)$maxProject);
- foreach($allProjects as $project)
- {
- if($projectIdList && !in_array($project->id, $projectIdList)) continue;
- if(!$this->gitlab->checkUserAccess($hostID, 0, $project, $groupIDList, 'reporter')) continue;
- $project->isDeveloper = $this->gitlab->checkUserAccess($hostID, 0, $project, $groupIDList, 'developer');
- $allProjectPairs[$hostID][$project->id] = $project;
- }
- return $allProjectPairs;
- }
- /**
- * 创建合并请求。
- * Create MR function.
- *
- * @param object $MR
- * @access public
- * @return array
- */
- public function create($MR)
- {
- $result = $this->checkSameOpened($MR->hostID, $MR->sourceProject, $MR->sourceBranch, $MR->targetProject, $MR->targetBranch);
- if($result['result'] == 'fail') return $result;
- $MRID = $this->insertMr($MR);
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- $this->loadModel('action')->create($this->moduleName, $MRID, 'opened');
- if($MR->needCI && $MR->jobID) $this->execJob($MRID, (int)$MR->jobID);
- $rawMR = $this->apiCreateMR($MR->hostID, $MR);
- /**
- * 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();
- $errorMessage = $this->convertApiError($rawMR->message);
- return array('result' => 'fail', 'message' => sprintf($this->lang->mr->apiError->createMR, $errorMessage));
- }
- /* 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);
- }
- /* Create a todo item for this MR. */
- if(empty($MR->jobID)) $this->apiCreateMRTodo($MR->hostID, $MR->targetProject, $rawMR->iid);
- $newMR = new stdclass();
- $newMR->mriid = $rawMR->iid;
- $newMR->status = $rawMR->state == 'open' ? 'opened' : $rawMR->state;
- $newMR->mergeStatus = $rawMR->merge_status;
- $this->dao->update(TABLE_MR)->data($newMR)->where('id')->eq($MRID)->autoCheck()->exec();
- /* Link stories,bugs and tasks. */
- $MR->id = $MRID;
- $MR->mriid = $newMR->mriid;
- $this->linkObjects($MR);
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- $linkParams = $this->app->tab == 'execution' || $this->app->tab == 'project' ? "repoID=0&mode=status¶m=opened&objectID={$MR->executionID}" : "repoID={$MR->repoID}";
- return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => helper::createLink($this->moduleName, 'browse', $linkParams));
- }
- /**
- * 通过API创建合并请求。
- * Create MR function by api.
- *
- * @access public
- * @return bool|int
- */
- public function apiCreate()
- {
- $postData = fixer::input('post')->get();
- $repo = $this->dao->findByID($postData->repoID)->from(TABLE_REPO)->fetch();
- if(empty($repo))
- {
- dao::$errors[] = 'No matched gitlab.';
- return false;
- }
- /* Process and insert mr data. */
- $MR = new stdClass();
- $MR->hostID = (int)$repo->serviceHost;
- $MR->sourceProject = $repo->serviceProject;
- $MR->sourceBranch = $postData->sourceBranch;
- $MR->targetProject = $repo->serviceProject;
- $MR->targetBranch = $postData->targetBranch;
- $MR->diffs = $postData->diffs;
- $MR->title = $this->lang->mr->common . ' ' . $postData->sourceBranch . $this->lang->mr->to . $postData->targetBranch ;
- $MR->repoID = $repo->id;
- $MR->jobID = $postData->jobID;
- $MR->status = 'opened';
- $MR->synced = '0';
- $MR->needCI = '1';
- $MR->hasNoConflict = $postData->mergeStatus ? '0' : '1';
- $MR->mergeStatus = $postData->mergeStatus ? 'can_be_merged' : 'cannot_be_merged';
- $MR->createdBy = $this->app->user->account;
- $MR->createdDate = date('Y-m-d H:i:s');
- if($MR->sourceProject == $MR->targetProject && $MR->sourceBranch == $MR->targetBranch)
- {
- dao::$errors[] = $this->lang->mr->errorLang[1];
- return false;
- }
- $result = $this->checkSameOpened($MR->hostID, (string)$MR->sourceProject, $MR->sourceBranch, (string)$MR->targetProject, $MR->targetBranch);
- if($result['result'] == 'fail')
- {
- dao::$errors[] = $result['message'];
- return false;
- }
- $MRID = $this->insertMr($MR);
- if(dao::isError()) return false;
- $this->loadModel('action')->create($this->moduleName, $MRID, 'opened');
- /* Exec Job */
- if($MR->hasNoConflict == '0' && $MR->mergeStatus == 'can_be_merged' && $MR->jobID) $this->execJob($MRID, (int)$MR->jobID);
- return $MRID;
- }
- /**
- * 更新合并请求。
- * Edit MR function.
- *
- * @param int $MRID
- * @param object $MR
- * @access public
- * @return array
- */
- public function update($MRID, $MR)
- {
- $oldMR = $this->fetchByID($MRID);
- $diff = array_diff_assoc((array)$oldMR, (array)$MR);
- if(!$oldMR) return array('result' => 'fail', 'message' => $this->lang->mr->notFound);
- /* The source and target branches cannot be the same. */
- if($oldMR->sourceBranch == $MR->targetBranch ) return array('result' => 'fail', 'message' => $this->lang->mr->errorLang[1]);
- $this->dao->update(TABLE_MR)->data($MR)->checkIF($MR->needCI, 'jobID', 'notempty');
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- /* Exec Job */
- $needExecJob = isset($diff['targetBranch']) || isset($diff['jobID']) ? true : false;
- if($needExecJob && isset($MR->jobID) && $MR->jobID)
- {
- $this->execJob($MRID, (int)$MR->jobID);
- if(dao::isError()) return array('result' => 'fail', 'message' => implode("\n", dao::getError()));
- }
- /* Known issue: `reviewer_ids` takes no effect. */
- $rawMR = $this->apiUpdateMR($oldMR, $MR);
- if(!isset($rawMR->id) and isset($rawMR->message))
- {
- $errorMessage = $this->convertApiError($rawMR->message);
- return array('result' => 'fail', 'message' => $errorMessage);
- }
- /* Update MR in Zentao database. */
- $this->dao->update(TABLE_MR)->data($MR, $this->config->mr->edit->skippedFields)
- ->where('id')->eq($MRID)
- ->batchCheck($this->config->mr->edit->requiredFields, 'notempty')
- ->autoCheck()
- ->exec();
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- $MR = $this->fetchByID($MRID);
- $this->linkObjects($MR);
- $actionID = $this->loadModel('action')->create($this->moduleName, $MRID, 'edited');
- $changes = common::createChanges($oldMR, $MR);
- if(!empty($changes))
- {
- foreach($changes as &$change) if($change['field'] == 'assignee') $change['field'] = 'reviewer';
- $this->action->logHistory($actionID, $changes);
- }
- $this->createMRLinkedAction($MRID, 'edit' . $this->moduleName, $MR->editedDate);
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- if($this->session->{$this->app->tab}) $MR->executionID = $this->session->{$this->app->tab};
- $linkParams = $this->app->tab == 'execution' || $this->app->tab == 'project' ? "repoID=0&mode=status¶m=opened&objectID={$MR->executionID}" : "repoID={$MR->repoID}";
- return array('result' => 'success', 'message' => $needExecJob ? $this->lang->mr->triggeredCI : $this->lang->saveSuccess, 'load' => helper::createLink($this->moduleName, 'browse', $linkParams));
- }
- /**
- * 更新合并请求关联信息。
- * Update MR linked info.
- *
- * @param int $MRID
- * @param string $action createmr|editmr|removemr
- * @param string $actionDate
- * @access public
- * @return bool
- */
- public function createMRLinkedAction($MRID, $action, $actionDate = '')
- {
- if(empty($actionDate)) $actionDate = helper::now();
- $MRAction = $actionDate . '::' . $this->app->user->account . '::' . helper::createLink($this->moduleName, 'view', "mr={$MRID}");
- $this->loadModel('action');
- foreach(array('story', 'task', 'bug') as $objectType)
- {
- $linkedObjects = $this->mrTao->getLinkedObjectPairs($MRID, $objectType);
- foreach($linkedObjects as $objectID) $this->action->create($objectType, $objectID, $action, '', $MRAction);
- }
- return !dao::isError();
- }
- /**
- * 通过API同步合并请求。
- * Sync MR from GitLab API to Zentao database.
- *
- * @param object $MR
- * @access public
- * @return object|false
- */
- public function apiSyncMR($MR)
- {
- $rawMR = $this->apiGetSingleMR($MR->repoID, $MR->mriid);
- /* Sync MR in ZenTao database whatever status of MR in GitLab. */
- if(isset($rawMR->iid))
- {
- $newMR = new stdclass();
- $gitUsers = $this->loadModel('pipeline')->getUserBindedPairs($MR->hostID, $rawMR->gitService, 'openID,account');
- foreach($this->config->mr->maps->sync as $syncField => $config)
- {
- $value = '';
- list($field, $optionType, $options) = explode('|', $config);
- if($optionType == 'field') $value = $rawMR->$field;
- if($optionType == 'userPairs')
- {
- $gitUserID = '';
- if(isset($rawMR->$field))
- {
- $values = $rawMR->$field;
- if(isset($values[0])) $gitUserID = $values[0]->$options;
- }
- $value = zget($gitUsers, $gitUserID, '');
- }
- if($value) $newMR->$syncField = $value;
- }
- /* For compatibility with PHP 5.4 . */
- $condition = (array)$newMR;
- if(empty($condition)) return false;
- /* Update compile status of current MR object */
- if(isset($MR->needCI) && $MR->needCI == '1')
- {
- $compile = $this->loadModel('compile')->getByID($MR->id);
- $newMR->compileStatus = $compile ? $compile->status : 'failed';
- }
- /* Update MR in Zentao database. */
- $newMR->editedBy = $this->app->user->account;
- $newMR->editedDate = helper::now();
- $this->dao->update(TABLE_MR)->data($newMR)
- ->where('id')->eq($MR->id)
- ->exec();
- }
- return $this->fetchByID($MR->id);
- }
- /**
- * 通过API批量同步合并请求。
- * Batch Sync GitLab MR Database.
- *
- * @param array $MRList
- * @access public
- * @return array
- */
- public function batchSyncMR($MRList)
- {
- if(empty($MRList)) return array();
- foreach($MRList as $key => $MR)
- {
- if($MR->status != 'opened') continue;
- $MRList[$key] = $this->apiSyncMR($MR);
- }
- return $MRList;
- }
- /**
- * 创建远程合并请求。
- * Create MR by API.
- *
- * @param int $hostID
- * @param object $MR
- * @access public
- * @return object|null
- */
- public function apiCreateMR($hostID, $MR)
- {
- $repo = $this->loadModel('repo')->getByID($MR->repoID);
- if(!$repo) return null;
- $openID = $this->loadModel('pipeline')->getOpenIdByAccount($hostID, strtolower($repo->SCM), $this->app->user->account);
- $assignee = '';
- if($MR->assignee) $assignee = $this->pipeline->getOpenIdByAccount($hostID, strtolower($repo->SCM), $MR->assignee);
- $scm = $this->app->loadClass('scm');
- $scm->setEngine($repo);
- $result = $scm->createMR($MR, $openID, $assignee);
- if(!empty($result->message)) $result->message = $this->convertApiError($result->message);
- return $result;
- }
- /**
- * 通过API查看是否有相同的合并请求。
- * Get same opened mr by api.
- *
- * @param int $hostID
- * @param string $sourceProject
- * @param string $sourceBranch
- * @param string $targetProject
- * @param string $targetBranch
- * @access public
- * @return object|null
- */
- public function apiGetSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch)
- {
- if(empty($hostID) || empty($sourceProject) || empty($sourceBranch) || empty($targetProject) || empty($targetBranch)) return null;
- $url = sprintf($this->loadModel('gitlab')->getApiRoot((int)$hostID), "/projects/{$sourceProject}/merge_requests") . "&state=opened&source_branch={$sourceBranch}&target_branch={$targetBranch}";
- $response = json_decode(commonModel::http($url));
- if($response)
- {
- foreach($response as $MR)
- {
- if(empty($MR->source_project_id) || empty($MR->target_project_id)) return null;
- if($MR->source_project_id == $sourceProject && $MR->target_project_id == $targetProject) return $MR;
- }
- }
- return null;
- }
- /**
- * 通过API获取单个合并请求。
- * Get single MR by API.
- *
- * @param int $repoID
- * @param int $MRID
- * @access public
- * @return object|null
- */
- public function apiGetSingleMR($repoID, $MRID)
- {
- $repo = $this->loadModel('repo')->getByID($repoID);
- if(!$repo) return null;
- $scm = $this->app->loadClass('scm');
- $scm->setEngine($repo);
- $MR = $scm->getSingleMR($MRID);
- if($MR)
- {
- if(!isset($MR->flow)) $MR->flow = 0;
- $MR->gitService = strtolower($repo->SCM);
- if($MR->state == 'open') $MR->state = 'opened';
- }
- return $MR;
- }
- /**
- * 通过API获取合并请求的提交信息。
- * Get MR commits by API.
- *
- * @param int $hostID
- * @param string $projectID targetProject
- * @param int $MRID
- * @access public
- * @return array|null
- */
- public function apiGetMRCommits($hostID, $projectID, $MRID)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- $apiRoot = $this->loadModel($host->type)->getApiRoot($hostID);
- if($host->type == 'gitlab')
- {
- $url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/commits");
- }
- else
- {
- $url = sprintf($apiRoot, "/repos/$projectID/pulls/$MRID/commits");
- }
- return (array)json_decode(commonModel::http($url, null, array(), is_object($apiRoot) ? $apiRoot->header : array()));
- }
- /**
- * 通过API更新合并请求。
- * Update MR by API.
- *
- * @param object $oldMR
- * @param object $MR
- * @access public
- * @return object|null
- */
- public function apiUpdateMR($oldMR, $MR)
- {
- $host = $this->loadModel('pipeline')->getByID($oldMR->hostID);
- if(!$host) return null;
- if(!empty($MR->assignee)) $assignee = $this->pipeline->getOpenIdByAccount($host->id, $host->type, $MR->assignee);
- $apiRoot = $this->loadModel($host->type)->getApiRoot($host->id);
- $MRObject = new stdclass();
- $MRObject->title = $MR->title;
- if($host->type == 'gitlab')
- {
- if(isset($MR->targetBranch)) $MRObject->target_branch = zget($MR, 'targetBranch', $oldMR->targetBranch);
- if(isset($MR->description)) $MRObject->description = $MR->description;
- if(isset($MR->remove_source_branch)) $MRObject->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false;
- if(isset($MR->squash)) $MRObject->squash = $MR->squash == '1' ? 1 : 0;
- if(!empty($assignee)) $MRObject->assignee_ids = $assignee;
- $url = sprintf($apiRoot, "/projects/{$oldMR->sourceProject}/merge_requests/{$oldMR->mriid}");
- return json_decode(commonModel::http($url, $MRObject, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
- }
- else
- {
- if(isset($MR->targetBranch)) $MRObject->base = zget($MR, 'targetBranch', $oldMR->targetBranch);
- if(isset($MR->description)) $MRObject->body = $MR->description;
- if(!empty($assignee)) $MRObject->assignee = $assignee;
- $url = sprintf($apiRoot, "/repos/{$oldMR->sourceProject}/pulls/{$oldMR->mriid}");
- $mergeResult = json_decode(commonModel::http($url, $MRObject, array(), array(), 'json', 'PATCH'));
- if(isset($mergeResult->number)) $mergeResult->iid = $host->type == 'gitea' ? $mergeResult->number : $mergeResult->id;
- if(isset($mergeResult->mergeable))
- {
- if($mergeResult->mergeable) $mergeResult->merge_status = 'can_be_merged';
- if(!$mergeResult->mergeable) $mergeResult->merge_status = 'cannot_be_merged';
- }
- if(isset($mergeResult->state) && $mergeResult->state == 'open') $mergeResult->state = 'opened';
- if(isset($mergeResult->merged) && $mergeResult->merged) $mergeResult->state = 'merged';
- return $mergeResult;
- }
- }
- /**
- * 通过API删除合并请求。
- * Delete MR by API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return object|null
- */
- public function apiDeleteMR($hostID, $projectID, $MRID)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- if(!$host) return null;
- if($host->type == 'gitlab')
- {
- $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID");
- return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE')));
- }
- $repoID = $this->dao->select('repoID')->from(TABLE_MR)
- ->where('hostID')->eq($hostID)
- ->andWhere('sourceProject')->eq($projectID)
- ->andWhere('mriid')->eq($MRID)
- ->andWhere('deleted')->eq('0')
- ->fetch('repoID');
- $rowMR = $this->apiGetSingleMR((int)$repoID, $MRID);
- if($rowMR && $rowMR->state == 'opened')
- {
- $apiRoot = $this->loadModel($host->type)->getApiRoot($hostID);
- $header = is_string($apiRoot) ? array() : $apiRoot->header;
- if(is_object($apiRoot)) $apiRoot = $apiRoot->url;
- $api = "/repos/$projectID/pulls/$MRID";
- return json_decode(commonModel::http(sprintf($apiRoot, $api), array('state' => 'closed'), array(), $header, 'json', 'PATCH'));
- }
- return null;
- }
- /**
- * 通过API关闭合并请求。
- * Close MR by API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return object|null
- */
- public function apiCloseMR($hostID, $projectID, $MRID)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- if(!$host) return null;
- if($host->type == 'gitlab')
- {
- $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=close';
- return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
- }
- else
- {
- return $this->apiDeleteMR($hostID, $projectID, $MRID);
- }
- }
- /**
- * 通过API重新打开合并请求。
- * Reopen MR by API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return object|null
- */
- public function apiReopenMR($hostID, $projectID, $MRID)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- if(!$host) return null;
- $apiRoot = $this->loadModel($host->type)->getApiRoot($hostID);
- if($host->type == 'gitlab')
- {
- $url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID") . '&state_event=reopen';
- return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
- }
- else
- {
- $url = sprintf($apiRoot, "/repos/$projectID/pulls/$MRID");
- return json_decode(commonModel::http($url, array('state' => 'open'), array(), array(), 'json', 'PATCH'));
- }
- }
- /**
- * 通过API接受合并请求。
- * Accept MR by API.
- *
- * @param object $MR
- * @access public
- * @return object|null
- */
- public function apiAcceptMR($MR)
- {
- $host = $this->loadModel('pipeline')->getByID($MR->hostID);
- if(!$host) return null;
- $apiRoot = $this->loadModel($host->type)->getApiRoot($MR->hostID);
- if($host->type == 'gitlab')
- {
- $approveUrl = sprintf($apiRoot, "/projects/$MR->targetProject/merge_requests/$MR->mriid/approved");
- commonModel::http($approveUrl, null, array(CURLOPT_CUSTOMREQUEST => 'POST'));
- $url = sprintf($apiRoot, "/projects/$MR->targetProject/merge_requests/$MR->mriid/merge");
- return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
- }
- else
- {
- $url = sprintf($apiRoot, "/repos/$MR->targetProject/pulls/$MR->mriid/merge");
- $data = array('Do' => $MR->squash == '1' ? 'squash' : 'merge');
- if($MR->removeSourceBranch == '1') $data['delete_branch_after_merge'] = true;
- }
- $rowMR = json_decode(commonModel::http($url, $data, array(), array(), 'json', 'POST'));
- if(!isset($rowMR->massage))
- {
- $rowMR = $this->apiGetSingleMR($MR->repoID, $MR->mriid);
- if($MR->removeSourceBranch == '1' && $host->type == 'gogs') $this->loadModel($host->type)->apiDeleteBranch($MR->hostID, $MR->sourceProject, $MR->sourceBranch);
- }
- return $rowMR;
- }
- /**
- * 获取合并请求的对比信息。
- * Get MR diff versions by API.
- *
- * @param object $MR
- * @access public
- * @return array
- */
- public function getDiffs($MR)
- {
- if(!isset($MR->repoID)) return array();
- $repo = $this->loadModel('repo')->getByID($MR->repoID);
- if(!$repo) return array();
- $host = $this->loadModel('pipeline')->getByID($MR->hostID);
- $scm = $this->app->loadClass('scm');
- $scm->setEngine($repo);
- $lines = array();
- if($host->type == 'gitlab')
- {
- $diffVersions = array();
- if($MR->synced) $diffVersions = $this->apiGetDiffVersions($MR->hostID, $MR->targetProject, $MR->mriid);
- foreach($diffVersions as $diffVersion)
- {
- $singleDiff = $this->apiGetSingleDiffVersion($MR->hostID, $MR->targetProject, $MR->mriid, $diffVersion->id);
- if($singleDiff->state == 'empty') continue;
- $diffs = $singleDiff->diffs;
- foreach($diffs as $diff)
- {
- $lines[] = sprintf("diff --git a/%s b/%s", $diff->old_path, $diff->new_path);
- $lines[] = sprintf("index %s ... %s %s ", $singleDiff->head_commit_sha, $singleDiff->base_commit_sha, $diff->b_mode);
- $lines[] = sprintf("--a/%s", $diff->old_path);
- $lines[] = sprintf("--b/%s", $diff->new_path);
- $diffLines = explode("\n", $diff->diff);
- foreach($diffLines as $diffLine) $lines[] = $diffLine;
- }
- }
- }
- else
- {
- $lines = $this->apiGetDiffs($MR->hostID, $MR->targetProject, $MR->mriid);
- }
- if(empty($MR->synced)) $lines = preg_replace('/^\s*$\n?\r?/m', '', $MR->diffs);
- if(is_string($lines)) $lines = explode("\n", $lines);
- return $scm->engine->parseDiff($lines);
- }
- /**
- * 通过API创建合并请求待办。
- * Create a todo item for merge request.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return object|null
- */
- public function apiCreateMRTodo($hostID, $projectID, $MRID)
- {
- $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/todo");
- return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'POST')));
- }
- /**
- * 通过API获取合并请求的对比版本信息。
- * Get diff versions of MR from GitLab API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return array|null
- */
- public function apiGetDiffVersions($hostID, $projectID, $MRID)
- {
- $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/versions");
- return json_decode(commonModel::http($url));
- }
- /**
- * 通过API获取合并请求的单个对比版本信息。
- * Get a single diff version of MR from GitLab API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @param int $versionID
- * @access public
- * @return object|null
- */
- public function apiGetSingleDiffVersion($hostID, $projectID, $MRID, $versionID)
- {
- $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/versions/$versionID");
- return json_decode(commonModel::http($url));
- }
- /**
- * 通过Gitea API获取合并请求的对比信息。
- * Get diff of MR from Gitea API.
- *
- * @param int $hostID
- * @param string $projectID
- * @param int $MRID
- * @access public
- * @return string
- */
- public function apiGetDiffs($hostID, $projectID, $MRID)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- if(!$host || $host->type == 'gitlab') return '';
- $url = sprintf($this->loadModel($host->type)->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID.diff");
- return commonModel::http($url);
- }
- /**
- * 审核合并请求。
- * Reject or Approve this MR.
- *
- * @param object $MR
- * @param string $action approve|reject
- * @param string $comment
- * @return array
- */
- public function approve($MR, $action = 'approve', $comment = '')
- {
- if(isset($MR->status) && $MR->status == 'opened')
- {
- $oldMR = clone $MR;
- $rawApprovalStatus = zget($MR, 'approvalStatus', '');
- if($action == 'reject' && $rawApprovalStatus != 'rejected') $MR->approvalStatus = 'rejected';
- if($action == 'approve' && $rawApprovalStatus != 'approved') $MR->approvalStatus = 'approved';
- if(isset($MR->approvalStatus) && $rawApprovalStatus != $MR->approvalStatus)
- {
- $changes = common::createChanges($oldMR, $MR);
- unset($MR->editedDate);
- $MR->approver = $this->app->user->account;
- $this->dao->update(TABLE_MR)->data($MR)
- ->where('id')->eq($MR->id)
- ->exec();
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- /* Save approval history into db. */
- $approval = new stdClass;
- $approval->date = helper::now();
- $approval->mrID = $MR->id;
- $approval->account = $MR->approver;
- $approval->action = $action;
- $approval->comment = $comment;
- $this->dao->insert(TABLE_MRAPPROVAL)->data($approval, $this->config->mrapproval->create->skippedFields)
- ->batchCheck($this->config->mrapproval->create->requiredFields, 'notempty')
- ->autoCheck()
- ->exec();
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- $actionID = $this->loadModel('action')->create($this->moduleName, $MR->id, $action);
- $this->action->logHistory($actionID, $changes);
- return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true);
- }
- }
- return array('result' => 'fail', 'message' => $this->lang->mr->repeatedOperation, 'load' => helper::createLink($this->moduleName, 'view', "mr={$MR->id}"));
- }
- /**
- * 关闭合并请求。
- * Close this MR.
- *
- * @param object $MR
- * @access public
- * @return array
- */
- public function close($MR)
- {
- if($MR->status == 'closed') return array('result' => 'fail', 'message' => $this->lang->mr->repeatedOperation);
- $actionID = $this->loadModel('action')->create($this->moduleName, $MR->id, 'closed');
- $rawMR = $this->apiCloseMR($MR->hostID, $MR->targetProject, $MR->mriid);
- $changes = common::createChanges($MR, $rawMR);
- $this->action->logHistory($actionID, $changes);
- if(isset($rawMR->state) && $rawMR->state == 'closed') return array('result' => 'success', 'message' => $this->lang->mr->closeSuccess, 'load' => 'reload');
- return array('result' => 'fail', 'message' => $this->lang->fail);
- }
- /**
- * 重新打开合并请求。
- * Reopen this MR.
- *
- * @param object $MR
- * @access public
- * @return array
- */
- public function reopen($MR)
- {
- if($MR->status == 'opened') return array('result' => 'fail', 'message' => $this->lang->mr->repeatedOperation);
- $this->loadModel('action')->create($this->moduleName, $MR->id, 'reopen');
- $rawMR = $this->apiReopenMR($MR->hostID, $MR->targetProject, $MR->mriid);
- if(!empty($rawMR) && empty($rawMR->message)) return array('result' => 'success', 'message' => $this->lang->mr->reopenSuccess, 'load' => 'reload');
- return array('result' => 'fail', 'message' => $this->lang->fail);
- }
- /**
- * 获取合并请求关联的对象。
- * Get mr link list.
- *
- * @param int $MRID
- * @param string $type story|task|bug
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getLinkList($MRID, $type, $orderBy = 'id_desc', $pager = null)
- {
- if(!isset($this->config->objectTables[$type])) return array();
- $orderBy = str_replace('name_', 'title_', $orderBy);
- if($type == 'task') $orderBy = str_replace('title_', 'name_', $orderBy);
- return $this->dao->select('t1.*')->from($this->config->objectTables[$type])->alias('t1')
- ->leftJoin(TABLE_RELATION)->alias('t2')->on('t1.id=t2.BID')
- ->where('t2.relation')->eq('interrated')
- ->andWhere('t2.AType')->eq($this->moduleName)
- ->andWhere('t2.AID')->eq($MRID)
- ->andWhere('t2.BType')->eq($type)
- ->andWhere('t1.deleted')->eq(0)
- ->orderBy($orderBy)
- ->page($pager)
- ->fetchAll('id');
- }
- /**
- * 根据对象信息获取合并请求列表。
- * Get linked MR pairs.
- *
- * @param int $objectID
- * @param string $objectType
- * @param string $module mr|pullreq
- * @access public
- * @return array
- */
- public function getLinkedMRPairs($objectID, $objectType = 'story', $module = '')
- {
- if(!$module) $module = $this->moduleName;
- return $this->dao->select("t2.id,t2.title,t2.status")->from(TABLE_RELATION)->alias('t1')
- ->leftJoin(TABLE_MR)->alias('t2')->on('t1.AID = t2.id')
- ->where('t1.AType')->eq($module)
- ->andWhere('t1.BType')->eq($objectType)
- ->andWhere('t1.BID')->eq($objectID)
- ->andWhere('t2.id')->ne(0)
- ->fetchAll('id');
- }
- /**
- * 合并请求关联对象。
- * Create an mr link.
- *
- * @param int $MRID
- * @param string $type story|task|bug
- * @param array $objects
- * @access public
- * @return bool
- */
- public function link($MRID, $type, $objects)
- {
- if(!isset($this->config->objectTables[$type])) return false;
- $MR = $this->fetchByID($MRID);
- if(!$MR) return false;
- /* Set link action text. */
- $user = $this->loadModel('user')->getRealNameAndEmails($MR->createdBy);
- $comment = $MR->createdDate . '::' . zget($user, 'realname', $this->app->user->realname) . '::' . helper::createLink($this->moduleName, 'view', "mr={$MR->id}");
- $this->loadModel('action');
- foreach($objects as $objectID)
- {
- $relation = new stdclass();
- $relation->product = 0;
- $relation->AType = $this->moduleName;
- $relation->AID = $MRID;
- $relation->relation = 'interrated';
- $relation->BType = $type;
- $relation->BID = $objectID;
- $this->dao->replace(TABLE_RELATION)->data($relation)->exec();
- $this->action->create($type, (int)$objectID, 'create' . $this->moduleName, '', $comment);
- }
- return !dao::isError();
- }
- /**
- * 保存合并请求关联的对象。
- * Save linked objects.
- *
- * @param object $MR
- * @access public
- * @return bool
- */
- public function linkObjects($MR)
- {
- /* Get commits by MR. */
- $commits = $this->apiGetMRCommits($MR->hostID, (string)$MR->targetProject, $MR->mriid);
- if(empty($commits)) return true;
- /* Init objects. */
- $objectList = array('story' => array(), 'bug' => array(), 'task' => array());
- $this->loadModel('repo');
- foreach($commits as $commit)
- {
- if(empty($commit->message)) $commit->message = zget($commit, 'title', '');
- $objects = $this->repo->parseComment($commit->message);
- $objectList['story'] = array_merge($objectList['story'], $objects['stories']);
- $objectList['bug'] = array_merge($objectList['bug'], $objects['bugs']);
- $objectList['task'] = array_merge($objectList['task'], $objects['tasks']);
- }
- $users = $this->loadModel('user')->getPairs('noletter');
- $MRCreateAction = $MR->createdDate . '::' . zget($users, $MR->createdBy) . '::' . $MR->id;
- $product = $this->getMRProduct($MR);
- $this->loadModel('action');
- foreach($objectList as $type => $objectIDs)
- {
- $relation = new stdclass();
- $relation->product = $product ? $product->id : 0;
- $relation->AType = $this->moduleName;
- $relation->AID = $MR->id;
- $relation->relation = 'interrated';
- $relation->BType = $type;
- foreach($objectIDs as $objectID)
- {
- $relation->BID = $objectID;
- $this->dao->replace(TABLE_RELATION)->data($relation)->exec();
- $this->action->create($type, (int)$objectID, 'create' . $this->moduleName, '', $MRCreateAction);
- }
- }
- return !dao::isError();
- }
- /**
- * 解除合并请求关联的对象。
- * Unlink an mr link.
- *
- * @param int $MRID
- * @param string $type
- * @param int $objectID
- * @access public
- * @return bool
- */
- public function unlink($MRID, $type, $objectID)
- {
- if(!isset($this->config->objectTables[$type])) return false;
- $this->dao->delete()->from(TABLE_RELATION)
- ->where('AType')->eq($this->moduleName)
- ->andWhere('AID')->eq($MRID)
- ->andWhere('relation')->eq('interrated')
- ->andWhere('BType')->eq($type)
- ->andWhere('BID')->eq($objectID)
- ->exec();
- $this->loadModel('action')->create($type, $objectID, 'deletemr', '', helper::createLink($this->moduleName, 'view', "mr={$MRID}"));
- return !dao::isError();
- }
- /**
- * 获取合并请求的产品。
- * Get mr product.
- *
- * @param object $MR
- * @access public
- * @return object|false
- */
- public function getMRProduct($MR)
- {
- $productID = $this->dao->select('product')->from(TABLE_REPO)->where('id')->eq($MR->repoID)->fetch('product');
- if(!$productID) return false;
- return $this->loadModel('product')->getById((int)$productID);
- }
- /**
- * 获取合并请求的收件人和抄送人。
- * Get toList and ccList.
- *
- * @param object $MR
- * @access public
- * @return array
- */
- public function getToAndCcList($MR)
- {
- return array($MR->createdBy, $MR->assignee);
- }
- /**
- * 将合并的操作记录到链接
- * Log merged action to links.
- *
- * @param object $MR
- * @access public
- * @return bool
- */
- public function logMergedAction($MR)
- {
- $this->loadModel('action')->create($this->moduleName, $MR->id, 'merged' . $this->moduleName);
- foreach(array('story', 'bug', 'task') as $type)
- {
- $objects = $this->getLinkList($MR->id, $type);
- foreach($objects as $object)
- {
- $this->action->create($type, $object->id, 'merged' . $this->moduleName, '', helper::createLink($this->moduleName, 'view', "mr={$MR->id}"));
- }
- }
- $this->dao->update(TABLE_MR)->data(array('status' => 'merged'))->where('id')->eq($MR->id)->exec();
- return !dao::isError();
- }
- /**
- * 检查是否有相同的未关闭合并请求。
- * Check same opened mr for source branch.
- *
- * @param int $hostID
- * @param string $sourceProject
- * @param string $sourceBranch
- * @param string $targetProject
- * @param string $targetBranch
- * @access public
- * @return array
- */
- public function checkSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch)
- {
- if($sourceProject == $targetProject && $sourceBranch == $targetBranch) return array('result' => 'fail', 'message' => $this->lang->mr->errorLang[1]);
- $dbOpenedID = $this->dao->select('id')->from(TABLE_MR)
- ->where('hostID')->eq($hostID)
- ->andWhere('sourceProject')->eq($sourceProject)
- ->andWhere('sourceBranch')->eq($sourceBranch)
- ->andWhere('targetProject')->eq($targetProject)
- ->andWhere('targetBranch')->eq($targetBranch)
- ->andWhere('status')->eq('opened')
- ->andWhere('deleted')->eq('0')
- ->fetch('id');
- if(!empty($dbOpenedID)) return array('result' => 'fail', 'message' => sprintf($this->lang->mr->hasSameOpenedMR, $dbOpenedID));
- $MR = $this->apiGetSameOpened($hostID, (string)$sourceProject, $sourceBranch, (string)$targetProject, $targetBranch);
- if($MR) return array('result' => 'fail', 'message' => sprintf($this->lang->mr->errorLang[2], $MR->iid));
- return array('result' => 'success');
- }
- /**
- * 解析API错误信息。
- * Convert API error.
- *
- * @param array $message
- * @access public
- * @return string
- */
- public function convertApiError($message)
- {
- if(is_array($message)) $message = $message[0];
- if(!is_string($message)) return $message;
- foreach($this->lang->mr->apiErrorMap as $key => $errorMsg)
- {
- if(strpos($errorMsg, '/') === 0)
- {
- $result = preg_match($errorMsg, $message, $matches);
- if($result) $errorMessage = sprintf(zget($this->lang->mr->errorLang, $key), zget($matches, 1, $matches[0]));
- }
- elseif($message == $errorMsg)
- {
- $errorMessage = zget($this->lang->mr->errorLang, $key, $message);
- }
- if(isset($errorMessage)) break;
- }
- return isset($errorMessage) ? $errorMessage : $message;
- }
- /**
- * 判断按钮是否可点击。
- * Adjust the action clickable.
- *
- * @param object $MR
- * @param string $action
- * @access public
- * @return bool
- */
- public static function isClickable($MR, $action)
- {
- if($action == 'edit' && !$MR->synced) return false;
- if($action == 'edit') return $MR->canEdit != 'disabled';
- if($action == 'delete') return $MR->canDelete != 'disabled';
- return true;
- }
- /**
- * 根据ID删除合并请求。
- * Delete MR by ID.
- *
- * @param int $MRID
- * @access public
- * @return bool
- */
- public function deleteByID($MRID)
- {
- $MR = $this->fetchByID($MRID);
- if(!$MR) return false;
- if($MR->synced)
- {
- $res = $this->apiDeleteMR($MR->hostID, $MR->targetProject, $MR->mriid);
- if(isset($res->message)) dao::$errors[] = $this->convertApiError($res->message);
- if(dao::isError()) return false;
- }
- $this->dao->delete()->from(TABLE_MR)->where('id')->eq($MRID)->exec();
- $this->loadModel('action')->create($this->moduleName, $MRID, 'deleted', '', $MR->title);
- $this->createMRLinkedAction($MRID, 'remove' . $this->moduleName);
- return !dao::isError();
- }
- /**
- * 执行合并请求流水线。
- * Execute MR pipeline.
- *
- * @param int $MRID
- * @param int $jobID
- * @access public
- * @return bool
- */
- public function execJob($MRID, $jobID)
- {
- if(empty($MRID) || empty($jobID)) return false;
- $MR = $this->fetchByID($MRID);
- if(!$MR) return false;
- $compile = $this->loadModel('job')->exec($jobID, array('sourceBranch' => $MR->sourceBranch, 'targetBranch' => $MR->targetBranch), 'commit');
- if(!$compile) return false;
- $newMR = new stdclass();
- $newMR->compileID = $compile->id;
- $newMR->compileStatus = $compile->status;
- if($newMR->compileStatus == 'failure') $newMR->status = 'closed';
- if($newMR->compileStatus == 'create_fail') $newMR->status = 'closed';
- $this->loadModel('repo')->saveRelation($MRID, 'mr', $compile->id, 'compile', 'mrjob');
- $this->dao->update(TABLE_MR)->data($newMR)->where('id')->eq($MRID)->autoCheck()->exec();
- return dao::isError();
- }
- /**
- * 创建合并请求。
- * Insert a merge request.
- *
- * @param object $MR
- * @access public
- * @return int|false
- */
- public function insertMr($MR)
- {
- $this->dao->insert(TABLE_MR)->data($MR, $this->config->mr->create->skippedFields)
- ->batchCheck($this->config->mr->create->requiredFields, 'notempty')
- ->checkIF(!empty($MR->needCI), 'jobID', 'notempty')
- ->exec();
- if(dao::isError()) return false;
- return $this->dao->lastInsertID();
- }
- }
|