mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Provide a basic search engine for builds
Summary: This supports a few basic use cases that aren't served by the buildable search engine: - I'm trying to discover when the last time that this particular build plan failed was. - I want to know if any builds have deadlocked. - At a glance, I'm more interested in what build plans are running, not which buildables are being built. This is more often than not the case. Test Plan: {F1744003} Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin, epriestley Differential Revision: https://secure.phabricator.com/D16347
This commit is contained in:
parent
bbc2ae7858
commit
2c55a4ad72
7 changed files with 218 additions and 22 deletions
|
@ -1107,6 +1107,7 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildFailureException' => 'applications/harbormaster/exception/HarbormasterBuildFailureException.php',
|
||||
'HarbormasterBuildGraph' => 'applications/harbormaster/engine/HarbormasterBuildGraph.php',
|
||||
'HarbormasterBuildLintMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php',
|
||||
'HarbormasterBuildListController' => 'applications/harbormaster/controller/HarbormasterBuildListController.php',
|
||||
'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php',
|
||||
'HarbormasterBuildLogChunk' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunk.php',
|
||||
'HarbormasterBuildLogChunkIterator' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunkIterator.php',
|
||||
|
@ -1129,6 +1130,8 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php',
|
||||
'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php',
|
||||
'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.php',
|
||||
'HarbormasterBuildSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildSearchEngine.php',
|
||||
'HarbormasterBuildStatusDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php',
|
||||
'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php',
|
||||
'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php',
|
||||
'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php',
|
||||
|
@ -5647,6 +5650,7 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildFailureException' => 'Exception',
|
||||
'HarbormasterBuildGraph' => 'AbstractDirectedGraph',
|
||||
'HarbormasterBuildLintMessage' => 'HarbormasterDAO',
|
||||
'HarbormasterBuildListController' => 'HarbormasterController',
|
||||
'HarbormasterBuildLog' => array(
|
||||
'HarbormasterDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
|
@ -5682,6 +5686,8 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'HarbormasterBuildRequest' => 'Phobject',
|
||||
'HarbormasterBuildSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'HarbormasterBuildStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'HarbormasterBuildStep' => array(
|
||||
'HarbormasterDAO',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
|
|
|
@ -70,6 +70,7 @@ final class PhabricatorHarbormasterApplication extends PhabricatorApplication {
|
|||
=> 'HarbormasterBuildableActionController',
|
||||
),
|
||||
'build/' => array(
|
||||
$this->getQueryRoutePattern() => 'HarbormasterBuildListController',
|
||||
'(?P<id>\d+)/' => 'HarbormasterBuildViewController',
|
||||
'(?P<action>pause|resume|restart|abort)/'.
|
||||
'(?P<id>\d+)/(?:(?P<via>[^/]+)/)?'
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
final class HarbormasterBuildListController extends HarbormasterController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new HarbormasterBuildSearchEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,15 @@ final class HarbormasterBuildableListController extends HarbormasterController {
|
|||
public function handleRequest(AphrontRequest $request) {
|
||||
$items = array();
|
||||
|
||||
$items[] = id(new PHUIListItemView())
|
||||
->setType(PHUIListItemView::TYPE_LABEL)
|
||||
->setName(pht('Builds'));
|
||||
|
||||
$items[] = id(new PHUIListItemView())
|
||||
->setType(PHUIListItemView::TYPE_LINK)
|
||||
->setName(pht('Browse Builds'))
|
||||
->setHref($this->getApplicationURI('build/'));
|
||||
|
||||
$items[] = id(new PHUIListItemView())
|
||||
->setType(PHUIListItemView::TYPE_LABEL)
|
||||
->setName(pht('Build Plans'));
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
final class HarbormasterBuildSearchEngine
|
||||
extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Harbormaster Builds');
|
||||
}
|
||||
|
||||
public function getApplicationClassName() {
|
||||
return 'PhabricatorHarbormasterApplication';
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
return new HarbormasterBuildQuery();
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array(
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setLabel(pht('Build Plans'))
|
||||
->setKey('plans')
|
||||
->setAliases(array('plan'))
|
||||
->setDescription(
|
||||
pht('Search for builds running a given build plan.'))
|
||||
->setDatasource(new HarbormasterBuildPlanDatasource()),
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setLabel(pht('Statuses'))
|
||||
->setKey('statuses')
|
||||
->setAliases(array('status'))
|
||||
->setDescription(
|
||||
pht('Search for builds with given statuses.'))
|
||||
->setDatasource(new HarbormasterBuildStatusDatasource()),
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
if ($map['plans']) {
|
||||
$query->withBuildPlanPHIDs($map['plans']);
|
||||
}
|
||||
|
||||
if ($map['statuses']) {
|
||||
$query->withBuildStatuses($map['statuses']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/harbormaster/build/'.$path;
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
return array(
|
||||
'all' => pht('All Builds'),
|
||||
);
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromBuiltin($query_key) {
|
||||
$query = $this->newSavedQuery();
|
||||
$query->setQueryKey($query_key);
|
||||
|
||||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query;
|
||||
}
|
||||
|
||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $builds,
|
||||
PhabricatorSavedQuery $query,
|
||||
array $handles) {
|
||||
assert_instances_of($builds, 'HarbormasterBuild');
|
||||
|
||||
$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));
|
||||
|
||||
$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 = HarbormasterBuild::getBuildStatusIcon($status);
|
||||
$status_color = HarbormasterBuild::getBuildStatusColor($status);
|
||||
$status_label = HarbormasterBuild::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;
|
||||
}
|
||||
|
||||
}
|
|
@ -71,28 +71,22 @@ final class HarbormasterBuild extends HarbormasterDAO
|
|||
* @return string Human-readable name.
|
||||
*/
|
||||
public static function getBuildStatusName($status) {
|
||||
switch ($status) {
|
||||
case self::STATUS_INACTIVE:
|
||||
return pht('Inactive');
|
||||
case self::STATUS_PENDING:
|
||||
return pht('Pending');
|
||||
case self::STATUS_BUILDING:
|
||||
return pht('Building');
|
||||
case self::STATUS_PASSED:
|
||||
return pht('Passed');
|
||||
case self::STATUS_FAILED:
|
||||
return pht('Failed');
|
||||
case self::STATUS_ABORTED:
|
||||
return pht('Aborted');
|
||||
case self::STATUS_ERROR:
|
||||
return pht('Unexpected Error');
|
||||
case self::STATUS_PAUSED:
|
||||
return pht('Paused');
|
||||
case self::STATUS_DEADLOCKED:
|
||||
return pht('Deadlocked');
|
||||
default:
|
||||
return pht('Unknown');
|
||||
}
|
||||
$map = self::getBuildStatusMap();
|
||||
return idx($map, $status, pht('Unknown ("%s")', $status));
|
||||
}
|
||||
|
||||
public static function getBuildStatusMap() {
|
||||
return array(
|
||||
self::STATUS_INACTIVE => pht('Inactive'),
|
||||
self::STATUS_PENDING => pht('Pending'),
|
||||
self::STATUS_BUILDING => pht('Building'),
|
||||
self::STATUS_PASSED => pht('Passed'),
|
||||
self::STATUS_FAILED => pht('Failed'),
|
||||
self::STATUS_ABORTED => pht('Aborted'),
|
||||
self::STATUS_ERROR => pht('Unexpected Error'),
|
||||
self::STATUS_PAUSED => pht('Paused'),
|
||||
self::STATUS_DEADLOCKED => pht('Deadlocked'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function getBuildStatusIcon($status) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
final class HarbormasterBuildStatusDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function getBrowseTitle() {
|
||||
return pht('Choose Build Statuses');
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a build status name...');
|
||||
}
|
||||
|
||||
public function getDatasourceApplicationClass() {
|
||||
return 'PhabricatorHarbormasterApplication';
|
||||
}
|
||||
|
||||
public function loadResults() {
|
||||
$results = $this->buildResults();
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
public function renderTokens(array $values) {
|
||||
return $this->renderTokensFromResults($this->buildResults(), $values);
|
||||
}
|
||||
|
||||
private function buildResults() {
|
||||
$results = array();
|
||||
|
||||
$status_map = HarbormasterBuild::getBuildStatusMap();
|
||||
foreach ($status_map as $value => $name) {
|
||||
$result = id(new PhabricatorTypeaheadResult())
|
||||
->setIcon(HarbormasterBuild::getBuildStatusIcon($value))
|
||||
->setColor(HarbormasterBuild::getBuildStatusColor($value))
|
||||
->setPHID($value)
|
||||
->setName($name)
|
||||
->addAttribute(pht('Status'));
|
||||
|
||||
$results[$value] = $result;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue