mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 14:30:56 +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:
parent
8338f94057
commit
620047bcfe
6 changed files with 151 additions and 65 deletions
|
@ -1370,6 +1370,7 @@ phutil_register_library_map(array(
|
||||||
'HarbormasterBuildTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildTransactionQuery.php',
|
'HarbormasterBuildTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildTransactionQuery.php',
|
||||||
'HarbormasterBuildUnitMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php',
|
'HarbormasterBuildUnitMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php',
|
||||||
'HarbormasterBuildUnitMessageQuery' => 'applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php',
|
'HarbormasterBuildUnitMessageQuery' => 'applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php',
|
||||||
|
'HarbormasterBuildView' => 'applications/harbormaster/view/HarbormasterBuildView.php',
|
||||||
'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php',
|
'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php',
|
||||||
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
|
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
|
||||||
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
|
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
|
||||||
|
@ -6999,6 +7000,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
'HarbormasterBuildUnitMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'HarbormasterBuildUnitMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'HarbormasterBuildView' => 'AphrontView',
|
||||||
'HarbormasterBuildViewController' => 'HarbormasterController',
|
'HarbormasterBuildViewController' => 'HarbormasterController',
|
||||||
'HarbormasterBuildWorker' => 'HarbormasterWorker',
|
'HarbormasterBuildWorker' => 'HarbormasterWorker',
|
||||||
'HarbormasterBuildable' => array(
|
'HarbormasterBuildable' => array(
|
||||||
|
|
|
@ -18,11 +18,6 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$timeline = $this->buildTransactionTimeline(
|
|
||||||
$plan,
|
|
||||||
new HarbormasterBuildPlanTransactionQuery());
|
|
||||||
$timeline->setShouldTerminate(true);
|
|
||||||
|
|
||||||
$title = $plan->getName();
|
$title = $plan->getName();
|
||||||
|
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
|
@ -33,24 +28,30 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
|
|
||||||
$curtain = $this->buildCurtainView($plan);
|
$curtain = $this->buildCurtainView($plan);
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs()
|
||||||
$crumbs->addTextCrumb(pht('Plan %d', $id));
|
->addTextCrumb($plan->getObjectName())
|
||||||
$crumbs->setBorder(true);
|
->setBorder(true);
|
||||||
|
|
||||||
list($step_list, $has_any_conflicts, $would_deadlock) =
|
list($step_list, $has_any_conflicts, $would_deadlock, $steps) =
|
||||||
$this->buildStepList($plan);
|
$this->buildStepList($plan);
|
||||||
|
|
||||||
$error = null;
|
$error = null;
|
||||||
if ($would_deadlock) {
|
if (!$steps) {
|
||||||
$error = pht('This build plan will deadlock when executed, due to '.
|
$error = pht(
|
||||||
'circular dependencies present in the build plan. '.
|
'This build plan does not have any build steps yet, so it will '.
|
||||||
'Examine the step list and resolve the deadlock.');
|
'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) {
|
} else if ($has_any_conflicts) {
|
||||||
// A deadlocking build will also cause all the artifacts to be
|
// A deadlocking build will also cause all the artifacts to be
|
||||||
// invalid, so we just skip showing this message if that's the
|
// invalid, so we just skip showing this message if that's the
|
||||||
// case.
|
// case.
|
||||||
$error = pht('This build plan has conflicts in one or more build steps. '.
|
$error = pht(
|
||||||
'Examine the step list and resolve the listed errors.');
|
'This build plan has conflicts in one or more build steps. '.
|
||||||
|
'Examine the step list and resolve the listed errors.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($error) {
|
if ($error) {
|
||||||
|
@ -59,18 +60,28 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
->appendChild($error);
|
->appendChild($error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$builds_view = $this->newBuildsView($plan);
|
||||||
|
|
||||||
|
$timeline = $this->buildTransactionTimeline(
|
||||||
|
$plan,
|
||||||
|
new HarbormasterBuildPlanTransactionQuery());
|
||||||
|
$timeline->setShouldTerminate(true);
|
||||||
|
|
||||||
$view = id(new PHUITwoColumnView())
|
$view = id(new PHUITwoColumnView())
|
||||||
->setHeader($header)
|
->setHeader($header)
|
||||||
->setCurtain($curtain)
|
->setCurtain($curtain)
|
||||||
->setMainColumn(array(
|
->setMainColumn(
|
||||||
$error,
|
array(
|
||||||
$step_list,
|
$error,
|
||||||
$timeline,
|
$step_list,
|
||||||
));
|
$builds_view,
|
||||||
|
$timeline,
|
||||||
|
));
|
||||||
|
|
||||||
return $this->newPage()
|
return $this->newPage()
|
||||||
->setTitle($title)
|
->setTitle($title)
|
||||||
->setCrumbs($crumbs)
|
->setCrumbs($crumbs)
|
||||||
|
->setPageObjectPHIDs(array($plan->getPHID()))
|
||||||
->appendChild($view);
|
->appendChild($view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +224,7 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||||
->appendChild($step_list);
|
->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) {
|
private function buildCurtainView(HarbormasterBuildPlan $plan) {
|
||||||
|
@ -376,7 +387,7 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
array $steps) {
|
array $steps) {
|
||||||
$has_conflicts = false;
|
$has_conflicts = false;
|
||||||
|
|
||||||
if (count($step_phids) === 0) {
|
if (!$step_phids) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,4 +447,41 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController {
|
||||||
|
|
||||||
return array($ui, $has_conflicts);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,49 +128,14 @@ final class HarbormasterBuildSearchEngine
|
||||||
|
|
||||||
$viewer = $this->requireViewer();
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
$buildables = mpull($builds, 'getBuildable');
|
$list = id(new HarbormasterBuildView())
|
||||||
$object_phids = mpull($buildables, 'getBuildablePHID');
|
->setViewer($viewer)
|
||||||
$initiator_phids = mpull($builds, 'getInitiatorPHID');
|
->setBuilds($builds)
|
||||||
$phids = array_mergev(array($initiator_phids, $object_phids));
|
->newObjectList();
|
||||||
$phids = array_unique(array_filter($phids));
|
|
||||||
|
|
||||||
$handles = $viewer->loadHandles($phids);
|
return id(new PhabricatorApplicationSearchResultView())
|
||||||
|
->setObjectList($list)
|
||||||
$list = new PHUIObjectItemListView();
|
->setNoDataString(pht('No builds found.'));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,10 @@ final class HarbormasterBuild extends HarbormasterDAO
|
||||||
return HarbormasterBuildStatus::newBuildStatusObject($status_key);
|
return HarbormasterBuildStatus::newBuildStatusObject($status_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getObjectName() {
|
||||||
|
return pht('Build %d', $this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Build Commands )----------------------------------------------------- */
|
/* -( Build Commands )----------------------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ final class HarbormasterBuildPlan extends HarbormasterDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getObjectName() {
|
public function getObjectName() {
|
||||||
return pht('Build Plan %d', $this->getID());
|
return pht('Plan %d', $this->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
67
src/applications/harbormaster/view/HarbormasterBuildView.php
Normal file
67
src/applications/harbormaster/view/HarbormasterBuildView.php
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue