diff --git a/TracToGitlabPlugin.php b/TracToGitlabPlugin.php index 7ed3947e282443475f0a14c8db26277bc7d5b8ee..01466eca3f3a3d2908abb99b4399998496860a96 100644 --- a/TracToGitlabPlugin.php +++ b/TracToGitlabPlugin.php @@ -123,6 +123,10 @@ final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, S 'merge', new Navigation(_('Zu portierende Bugfixes'), PluginEngine::getURL($this, [], 'merge')) ); + $navigation->addSubNavigation( + 'merge-requests', + new Navigation(_('Merge Requests'), PluginEngine::getURL($this, [], 'mergerequests')) + ); Navigation::addItem('/gitlab-dashboard', $navigation); } diff --git a/controllers/mergerequests.php b/controllers/mergerequests.php new file mode 100644 index 0000000000000000000000000000000000000000..16ab1825d1189c87d349c93df663142bd020597a --- /dev/null +++ b/controllers/mergerequests.php @@ -0,0 +1,112 @@ +<?php +final class MergerequestsController extends TracToGitlab\GitlabController +{ + public function before_filter(&$action, &$args) + { + parent::before_filter($action, $args); + + PageLayout::setTitle(_('Merge Requests')); + $this->activateNavigation('merge-requests'); + } + + public function index_action() + { + $data = $this->readFromCache('merge-requests', true); + if ($data === false) { + $this->mrs = $this->fetchMergeRequests(); + $this->writeToCache('merge-requests', $this->issues); + } else { + $this->mrs = $data['data']; + + Sidebar::get()->addWidget(new TemplateWidget( + 'Aus dem Cache', + $this->get_template_factory()->open( + $this->get_default_template('sidebar') + ), + ['time' => $data['time']] + )); + } + } + + public function diff_action($mr_iid) + { +// $versions = $this->gitlab->mergeRequests()-> + } + + private function fetchMergeRequests(): array + { + $mrs = $this->gitlabPager->fetchAll( + $this->gitlab->mergeRequests(), + 'all', + [ + $this->gitlabProjectId, + [ + 'sort' => 'asc', + 'scope' => 'all', + 'state' => 'opened', + ] + ] + ); + + $mrs = array_filter($mrs, function ($mr) { + if ($mr['draft'] || $mr['work_in_progress'] || $mr['merge_when_pipeline_succeeds']) { + return false; + } + + return true; + +// foreach (['worksforme', 'wontfix', 'Duplicate', 'invalid'] as $label) { +// if (in_array($label, $issue['labels'])) { +// return false; +// } +// } +// +// $has_version = array_reduce($issue['labels'], function ($has_version, $label) { +// return $has_version || strpos($label, 'Version::') === 0; +// }, false); +// return $has_version; + }); + +// var_dump($mrs);die; +// +// $issues = array_map(function ($issue) { +// $issue['studip_version'] = $this->extractVersion($issue['labels']); +// $issue['mr'] = $this->fetchRelatedMergeRequest($issue['iid']); +// return $issue; +// }, $issues); +// + usort($mrs, function ($a, $b) { + return strcmp($b['updated_at'], $a['updated_at']); + }); + + return $mrs; + } + + private function fetchRelatedMergeRequest(int $issue_id) + { + $mrs = $this->gitlab->issues()->closedByMergeRequests( + $this->gitlabProjectId, + $issue_id + ); + foreach ($mrs as $mr) { + if ($mr['state'] === 'merged') { + return $mr['iid']; + } + } + return null; + } + + private function extractVersion(array $labels): string + { + $version = ''; + foreach ($labels as $label) { + if (strpos($label, 'Version::') === 0) { + $v = substr($label, 9); + if (!$version || $v < $version) { + $version = $v; + } + } + } + return $version; + } +} diff --git a/views/mergerequests/index.php b/views/mergerequests/index.php new file mode 100644 index 0000000000000000000000000000000000000000..b845b08769a0fcb1ac26128c666ce757ac893959 --- /dev/null +++ b/views/mergerequests/index.php @@ -0,0 +1,59 @@ +<?php +/** + * @var array<int, array> $mrs + */ +?> +<table class="default"> + <thead> + <tr> + <th><?= _('Merge Request') ?></th> + <th><?= _('Status') ?></th> + <th><?= _('Konflikte') ?></th> + <th><?= _('Von') ?></th> + <th><?= _('Bearbeitung') ?></th> + <th><?= _('Review') ?></th> + <th><?= _('Erstellt') ?></th> + <th><?= _('Letzte Änderung') ?></th> + </tr> + </thead> + <tbody> + <? if (!$mrs): ?> + <tr> + <td colspan="7" style="text-align: center"> + <?= _('Keine offenen Merge Request vorhanden 🥳🍺') ?> + </td> + </tr> + <? endif; ?> + <? foreach ($mrs as $mr): ?> + <tr> + <td> + <a href="<?= htmlReady($mr['web_url']) ?>" target="_blank"> + #<?= htmlReady($mr['iid']) ?>: + <?= htmlReady($mr['title']) ?> + </td> + <td> + <? if ($mr['task_completion_status']['count'] === $mr['task_completion_status']['completed_count']): ?> + <?= Icon::create('accept', Icon::ROLE_STATUS_GREEN)->asImg(['alt' => 'ok']) ?> + <? else: ?> + <?= Icon::create('decline', Icon::ROLE_STATUS_RED)->asImg(['alt' => 'nicht ok']) ?> + <? endif; ?> + <? if ($mr['task_completion_status']['count'] > 0): ?> + <?= $mr['task_completion_status']['completed_count'] ?> / <?= $mr['task_completion_status']['count'] ?> + <? endif; ?> + </td> + <td> + <? if ($mr['has_conflicts']): ?> + <?= Icon::create('exclaim', Icon::ROLE_STATUS_RED)->asImg(['alt' => 'Ja']) ?> + <? else: ?> + <?= Icon::create('accept', Icon::ROLE_STATUS_GREEN)->asImg(['alt' => 'Nein']) ?> + <? endif; ?> + </td> + <td><?= htmlReady($mr['author']['username']) ?></td> + <td><?= $mr['assignee'] ? htmlReady($mr['assignee']['username']) : '–' ?></td> + <td><?= htmlReady(implode(',', array_column($mr['reviewers'], 'username'))) ?: '–' ?></td> + <td><?= strftime('%x %X', strtotime($mr['created_at'])) ?></td> + <td><?= strftime('%x %X', strtotime($mr['updated_at'])) ?></td> + </tr> + <? endforeach; ?> + </tbody> +</table> diff --git a/views/mergerequests/sidebar.php b/views/mergerequests/sidebar.php new file mode 100644 index 0000000000000000000000000000000000000000..d8de1a3a16f952649f3a1edc52f86726ff438cb6 --- /dev/null +++ b/views/mergerequests/sidebar.php @@ -0,0 +1 @@ +Zeitpunkt: <?= date('d.m.Y H:i:s', $time) ?>