mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 21:02:41 +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',
|
'HarbormasterBuildFailureException' => 'applications/harbormaster/exception/HarbormasterBuildFailureException.php',
|
||||||
'HarbormasterBuildGraph' => 'applications/harbormaster/engine/HarbormasterBuildGraph.php',
|
'HarbormasterBuildGraph' => 'applications/harbormaster/engine/HarbormasterBuildGraph.php',
|
||||||
'HarbormasterBuildLintMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php',
|
'HarbormasterBuildLintMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php',
|
||||||
|
'HarbormasterBuildListController' => 'applications/harbormaster/controller/HarbormasterBuildListController.php',
|
||||||
'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php',
|
'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php',
|
||||||
'HarbormasterBuildLogChunk' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunk.php',
|
'HarbormasterBuildLogChunk' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunk.php',
|
||||||
'HarbormasterBuildLogChunkIterator' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunkIterator.php',
|
'HarbormasterBuildLogChunkIterator' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunkIterator.php',
|
||||||
|
@ -1129,6 +1130,8 @@ phutil_register_library_map(array(
|
||||||
'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php',
|
'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php',
|
||||||
'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php',
|
'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php',
|
||||||
'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.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',
|
'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php',
|
||||||
'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php',
|
'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php',
|
||||||
'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php',
|
'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php',
|
||||||
|
@ -5647,6 +5650,7 @@ phutil_register_library_map(array(
|
||||||
'HarbormasterBuildFailureException' => 'Exception',
|
'HarbormasterBuildFailureException' => 'Exception',
|
||||||
'HarbormasterBuildGraph' => 'AbstractDirectedGraph',
|
'HarbormasterBuildGraph' => 'AbstractDirectedGraph',
|
||||||
'HarbormasterBuildLintMessage' => 'HarbormasterDAO',
|
'HarbormasterBuildLintMessage' => 'HarbormasterDAO',
|
||||||
|
'HarbormasterBuildListController' => 'HarbormasterController',
|
||||||
'HarbormasterBuildLog' => array(
|
'HarbormasterBuildLog' => array(
|
||||||
'HarbormasterDAO',
|
'HarbormasterDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
|
@ -5682,6 +5686,8 @@ phutil_register_library_map(array(
|
||||||
'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'HarbormasterBuildRequest' => 'Phobject',
|
'HarbormasterBuildRequest' => 'Phobject',
|
||||||
|
'HarbormasterBuildSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'HarbormasterBuildStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'HarbormasterBuildStep' => array(
|
'HarbormasterBuildStep' => array(
|
||||||
'HarbormasterDAO',
|
'HarbormasterDAO',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
|
|
@ -70,6 +70,7 @@ final class PhabricatorHarbormasterApplication extends PhabricatorApplication {
|
||||||
=> 'HarbormasterBuildableActionController',
|
=> 'HarbormasterBuildableActionController',
|
||||||
),
|
),
|
||||||
'build/' => array(
|
'build/' => array(
|
||||||
|
$this->getQueryRoutePattern() => 'HarbormasterBuildListController',
|
||||||
'(?P<id>\d+)/' => 'HarbormasterBuildViewController',
|
'(?P<id>\d+)/' => 'HarbormasterBuildViewController',
|
||||||
'(?P<action>pause|resume|restart|abort)/'.
|
'(?P<action>pause|resume|restart|abort)/'.
|
||||||
'(?P<id>\d+)/(?:(?P<via>[^/]+)/)?'
|
'(?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) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$items = array();
|
$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())
|
$items[] = id(new PHUIListItemView())
|
||||||
->setType(PHUIListItemView::TYPE_LABEL)
|
->setType(PHUIListItemView::TYPE_LABEL)
|
||||||
->setName(pht('Build Plans'));
|
->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.
|
* @return string Human-readable name.
|
||||||
*/
|
*/
|
||||||
public static function getBuildStatusName($status) {
|
public static function getBuildStatusName($status) {
|
||||||
switch ($status) {
|
$map = self::getBuildStatusMap();
|
||||||
case self::STATUS_INACTIVE:
|
return idx($map, $status, pht('Unknown ("%s")', $status));
|
||||||
return pht('Inactive');
|
}
|
||||||
case self::STATUS_PENDING:
|
|
||||||
return pht('Pending');
|
public static function getBuildStatusMap() {
|
||||||
case self::STATUS_BUILDING:
|
return array(
|
||||||
return pht('Building');
|
self::STATUS_INACTIVE => pht('Inactive'),
|
||||||
case self::STATUS_PASSED:
|
self::STATUS_PENDING => pht('Pending'),
|
||||||
return pht('Passed');
|
self::STATUS_BUILDING => pht('Building'),
|
||||||
case self::STATUS_FAILED:
|
self::STATUS_PASSED => pht('Passed'),
|
||||||
return pht('Failed');
|
self::STATUS_FAILED => pht('Failed'),
|
||||||
case self::STATUS_ABORTED:
|
self::STATUS_ABORTED => pht('Aborted'),
|
||||||
return pht('Aborted');
|
self::STATUS_ERROR => pht('Unexpected Error'),
|
||||||
case self::STATUS_ERROR:
|
self::STATUS_PAUSED => pht('Paused'),
|
||||||
return pht('Unexpected Error');
|
self::STATUS_DEADLOCKED => pht('Deadlocked'),
|
||||||
case self::STATUS_PAUSED:
|
);
|
||||||
return pht('Paused');
|
|
||||||
case self::STATUS_DEADLOCKED:
|
|
||||||
return pht('Deadlocked');
|
|
||||||
default:
|
|
||||||
return pht('Unknown');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getBuildStatusIcon($status) {
|
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