1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Add a "Recent Builds" element to the Build Plan UI and tighten up a few odds and ends

Summary:
Depends on D20218. Ref T13258. It's somewhat cumbersome to get from build plans to related builds but this is a reasonable thing to want to do, so make it a little easier.

Also clean up / standardize / hint a few things a little better.

Test Plan: {F6244116}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13258

Differential Revision: https://secure.phabricator.com/D20219
This commit is contained in:
epriestley 2019-02-26 05:37:51 -08:00
parent 8338f94057
commit 620047bcfe
6 changed files with 151 additions and 65 deletions

View file

@ -1370,6 +1370,7 @@ phutil_register_library_map(array(
'HarbormasterBuildTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildTransactionQuery.php',
'HarbormasterBuildUnitMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php',
'HarbormasterBuildUnitMessageQuery' => 'applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php',
'HarbormasterBuildView' => 'applications/harbormaster/view/HarbormasterBuildView.php',
'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php',
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
@ -6999,6 +7000,7 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
),
'HarbormasterBuildUnitMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildView' => 'AphrontView',
'HarbormasterBuildViewController' => 'HarbormasterController',
'HarbormasterBuildWorker' => 'HarbormasterWorker',
'HarbormasterBuildable' => array(

View file

@ -18,11 +18,6 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
return new Aphront404Response();
}
$timeline = $this->buildTransactionTimeline(
$plan,
new HarbormasterBuildPlanTransactionQuery());
$timeline->setShouldTerminate(true);
$title = $plan->getName();
$header = id(new PHUIHeaderView())
@ -33,24 +28,30 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
$curtain = $this->buildCurtainView($plan);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Plan %d', $id));
$crumbs->setBorder(true);
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($plan->getObjectName())
->setBorder(true);
list($step_list, $has_any_conflicts, $would_deadlock) =
list($step_list, $has_any_conflicts, $would_deadlock, $steps) =
$this->buildStepList($plan);
$error = null;
if ($would_deadlock) {
$error = pht('This build plan will deadlock when executed, due to '.
'circular dependencies present in the build plan. '.
'Examine the step list and resolve the deadlock.');
if (!$steps) {
$error = pht(
'This build plan does not have any build steps yet, so it will '.
'not do anything when run.');
} else if ($would_deadlock) {
$error = pht(
'This build plan will deadlock when executed, due to circular '.
'dependencies present in the build plan. Examine the step list '.
'and resolve the deadlock.');
} else if ($has_any_conflicts) {
// A deadlocking build will also cause all the artifacts to be
// invalid, so we just skip showing this message if that's the
// case.
$error = pht('This build plan has conflicts in one or more build steps. '.
'Examine the step list and resolve the listed errors.');
$error = pht(
'This build plan has conflicts in one or more build steps. '.
'Examine the step list and resolve the listed errors.');
}
if ($error) {
@ -59,18 +60,28 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
->appendChild($error);
}
$builds_view = $this->newBuildsView($plan);
$timeline = $this->buildTransactionTimeline(
$plan,
new HarbormasterBuildPlanTransactionQuery());
$timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$error,
$step_list,
$timeline,
));
->setMainColumn(
array(
$error,
$step_list,
$builds_view,
$timeline,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(array($plan->getPHID()))
->appendChild($view);
}
@ -213,7 +224,7 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($step_list);
return array($step_box, $has_any_conflicts, $is_deadlocking);
return array($step_box, $has_any_conflicts, $is_deadlocking, $steps);
}
private function buildCurtainView(HarbormasterBuildPlan $plan) {
@ -376,7 +387,7 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
array $steps) {
$has_conflicts = false;
if (count($step_phids) === 0) {
if (!$step_phids) {
return null;
}
@ -436,4 +447,41 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
return array($ui, $has_conflicts);
}
private function newBuildsView(HarbormasterBuildPlan $plan) {
$viewer = $this->getViewer();
$builds = id(new HarbormasterBuildQuery())
->setViewer($viewer)
->withBuildPlanPHIDs(array($plan->getPHID()))
->setLimit(10)
->execute();
$list = id(new HarbormasterBuildView())
->setViewer($viewer)
->setBuilds($builds)
->newObjectList();
$list->setNoDataString(pht('No recent builds.'));
$more_href = new PhutilURI(
$this->getApplicationURI('/build/'),
array('plan' => $plan->getPHID()));
$more_link = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-list-ul')
->setText(pht('View All Builds'))
->setHref($more_href);
$header = id(new PHUIHeaderView())
->setHeader(pht('Recent Builds'))
->addActionLink($more_link);
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($list);
}
}

View file

@ -128,49 +128,14 @@ final class HarbormasterBuildSearchEngine
$viewer = $this->requireViewer();
$buildables = mpull($builds, 'getBuildable');
$object_phids = mpull($buildables, 'getBuildablePHID');
$initiator_phids = mpull($builds, 'getInitiatorPHID');
$phids = array_mergev(array($initiator_phids, $object_phids));
$phids = array_unique(array_filter($phids));
$list = id(new HarbormasterBuildView())
->setViewer($viewer)
->setBuilds($builds)
->newObjectList();
$handles = $viewer->loadHandles($phids);
$list = new PHUIObjectItemListView();
foreach ($builds as $build) {
$id = $build->getID();
$initiator = $handles[$build->getInitiatorPHID()];
$buildable_object = $handles[$build->getBuildable()->getBuildablePHID()];
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
->setObject($build)
->setObjectName(pht('Build %d', $build->getID()))
->setHeader($build->getName())
->setHref($build->getURI())
->setEpoch($build->getDateCreated())
->addAttribute($buildable_object->getName());
if ($initiator) {
$item->addHandleIcon($initiator, $initiator->getName());
}
$status = $build->getBuildStatus();
$status_icon = HarbormasterBuildStatus::getBuildStatusIcon($status);
$status_color = HarbormasterBuildStatus::getBuildStatusColor($status);
$status_label = HarbormasterBuildStatus::getBuildStatusName($status);
$item->setStatusIcon("{$status_icon} {$status_color}", $status_label);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No builds found.'));
return $result;
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No builds found.'));
}
}

View file

@ -193,6 +193,10 @@ final class HarbormasterBuild extends HarbormasterDAO
return HarbormasterBuildStatus::newBuildStatusObject($status_key);
}
public function getObjectName() {
return pht('Build %d', $this->getID());
}
/* -( Build Commands )----------------------------------------------------- */

View file

@ -91,7 +91,7 @@ final class HarbormasterBuildPlan extends HarbormasterDAO
}
public function getObjectName() {
return pht('Build Plan %d', $this->getID());
return pht('Plan %d', $this->getID());
}

View file

@ -0,0 +1,67 @@
<?php
final class HarbormasterBuildView
extends AphrontView {
private $builds = array();
public function setBuilds(array $builds) {
assert_instances_of($builds, 'HarbormasterBuild');
$this->builds = $builds;
return $this;
}
public function getBuilds() {
return $this->builds;
}
public function render() {
return $this->newObjectList();
}
public function newObjectList() {
$viewer = $this->getViewer();
$builds = $this->getBuilds();
$buildables = mpull($builds, 'getBuildable');
$object_phids = mpull($buildables, 'getBuildablePHID');
$initiator_phids = mpull($builds, 'getInitiatorPHID');
$phids = array_mergev(array($initiator_phids, $object_phids));
$phids = array_unique(array_filter($phids));
$handles = $viewer->loadHandles($phids);
$list = new PHUIObjectItemListView();
foreach ($builds as $build) {
$id = $build->getID();
$initiator = $handles[$build->getInitiatorPHID()];
$buildable_object = $handles[$build->getBuildable()->getBuildablePHID()];
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
->setObject($build)
->setObjectName($build->getObjectName())
->setHeader($build->getName())
->setHref($build->getURI())
->setEpoch($build->getDateCreated())
->addAttribute($buildable_object->getName());
if ($initiator) {
$item->addByline($initiator->renderLink());
}
$status = $build->getBuildStatus();
$status_icon = HarbormasterBuildStatus::getBuildStatusIcon($status);
$status_color = HarbormasterBuildStatus::getBuildStatusColor($status);
$status_label = HarbormasterBuildStatus::getBuildStatusName($status);
$item->setStatusIcon("{$status_icon} {$status_color}", $status_label);
$list->addItem($item);
}
return $list;
}
}