@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Mike Riley and committed by
yelirekim
2c55a4ad bbc2ae78

+218 -22
+6
src/__phutil_library_map__.php
··· 1107 1107 'HarbormasterBuildFailureException' => 'applications/harbormaster/exception/HarbormasterBuildFailureException.php', 1108 1108 'HarbormasterBuildGraph' => 'applications/harbormaster/engine/HarbormasterBuildGraph.php', 1109 1109 'HarbormasterBuildLintMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php', 1110 + 'HarbormasterBuildListController' => 'applications/harbormaster/controller/HarbormasterBuildListController.php', 1110 1111 'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php', 1111 1112 'HarbormasterBuildLogChunk' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunk.php', 1112 1113 'HarbormasterBuildLogChunkIterator' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunkIterator.php', ··· 1129 1130 'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php', 1130 1131 'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php', 1131 1132 'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.php', 1133 + 'HarbormasterBuildSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildSearchEngine.php', 1134 + 'HarbormasterBuildStatusDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php', 1132 1135 'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php', 1133 1136 'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php', 1134 1137 'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php', ··· 5647 5650 'HarbormasterBuildFailureException' => 'Exception', 5648 5651 'HarbormasterBuildGraph' => 'AbstractDirectedGraph', 5649 5652 'HarbormasterBuildLintMessage' => 'HarbormasterDAO', 5653 + 'HarbormasterBuildListController' => 'HarbormasterController', 5650 5654 'HarbormasterBuildLog' => array( 5651 5655 'HarbormasterDAO', 5652 5656 'PhabricatorPolicyInterface', ··· 5682 5686 'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 5683 5687 'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 5684 5688 'HarbormasterBuildRequest' => 'Phobject', 5689 + 'HarbormasterBuildSearchEngine' => 'PhabricatorApplicationSearchEngine', 5690 + 'HarbormasterBuildStatusDatasource' => 'PhabricatorTypeaheadDatasource', 5685 5691 'HarbormasterBuildStep' => array( 5686 5692 'HarbormasterDAO', 5687 5693 'PhabricatorApplicationTransactionInterface',
+1
src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
··· 70 70 => 'HarbormasterBuildableActionController', 71 71 ), 72 72 'build/' => array( 73 + $this->getQueryRoutePattern() => 'HarbormasterBuildListController', 73 74 '(?P<id>\d+)/' => 'HarbormasterBuildViewController', 74 75 '(?P<action>pause|resume|restart|abort)/'. 75 76 '(?P<id>\d+)/(?:(?P<via>[^/]+)/)?'
+15
src/applications/harbormaster/controller/HarbormasterBuildListController.php
··· 1 + <?php 2 + 3 + final class HarbormasterBuildListController extends HarbormasterController { 4 + 5 + public function shouldAllowPublic() { 6 + return true; 7 + } 8 + 9 + public function handleRequest(AphrontRequest $request) { 10 + return id(new HarbormasterBuildSearchEngine()) 11 + ->setController($this) 12 + ->buildResponse(); 13 + } 14 + 15 + }
+9
src/applications/harbormaster/controller/HarbormasterBuildableListController.php
··· 11 11 12 12 $items[] = id(new PHUIListItemView()) 13 13 ->setType(PHUIListItemView::TYPE_LABEL) 14 + ->setName(pht('Builds')); 15 + 16 + $items[] = id(new PHUIListItemView()) 17 + ->setType(PHUIListItemView::TYPE_LINK) 18 + ->setName(pht('Browse Builds')) 19 + ->setHref($this->getApplicationURI('build/')); 20 + 21 + $items[] = id(new PHUIListItemView()) 22 + ->setType(PHUIListItemView::TYPE_LABEL) 14 23 ->setName(pht('Build Plans')); 15 24 16 25 $items[] = id(new PHUIListItemView())
+126
src/applications/harbormaster/query/HarbormasterBuildSearchEngine.php
··· 1 + <?php 2 + 3 + final class HarbormasterBuildSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Harbormaster Builds'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorHarbormasterApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return new HarbormasterBuildQuery(); 16 + } 17 + 18 + protected function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchDatasourceField()) 21 + ->setLabel(pht('Build Plans')) 22 + ->setKey('plans') 23 + ->setAliases(array('plan')) 24 + ->setDescription( 25 + pht('Search for builds running a given build plan.')) 26 + ->setDatasource(new HarbormasterBuildPlanDatasource()), 27 + id(new PhabricatorSearchDatasourceField()) 28 + ->setLabel(pht('Statuses')) 29 + ->setKey('statuses') 30 + ->setAliases(array('status')) 31 + ->setDescription( 32 + pht('Search for builds with given statuses.')) 33 + ->setDatasource(new HarbormasterBuildStatusDatasource()), 34 + ); 35 + } 36 + 37 + protected function buildQueryFromParameters(array $map) { 38 + $query = $this->newQuery(); 39 + 40 + if ($map['plans']) { 41 + $query->withBuildPlanPHIDs($map['plans']); 42 + } 43 + 44 + if ($map['statuses']) { 45 + $query->withBuildStatuses($map['statuses']); 46 + } 47 + 48 + return $query; 49 + } 50 + 51 + protected function getURI($path) { 52 + return '/harbormaster/build/'.$path; 53 + } 54 + 55 + protected function getBuiltinQueryNames() { 56 + return array( 57 + 'all' => pht('All Builds'), 58 + ); 59 + } 60 + 61 + public function buildSavedQueryFromBuiltin($query_key) { 62 + $query = $this->newSavedQuery(); 63 + $query->setQueryKey($query_key); 64 + 65 + switch ($query_key) { 66 + case 'all': 67 + return $query; 68 + } 69 + 70 + return parent::buildSavedQueryFromBuiltin($query_key); 71 + } 72 + 73 + protected function renderResultList( 74 + array $builds, 75 + PhabricatorSavedQuery $query, 76 + array $handles) { 77 + assert_instances_of($builds, 'HarbormasterBuild'); 78 + 79 + $viewer = $this->requireViewer(); 80 + 81 + $buildables = mpull($builds, 'getBuildable'); 82 + $object_phids = mpull($buildables, 'getBuildablePHID'); 83 + $initiator_phids = mpull($builds, 'getInitiatorPHID'); 84 + $phids = array_mergev(array($initiator_phids, $object_phids)); 85 + $phids = array_unique(array_filter($phids)); 86 + 87 + $handles = $viewer->loadHandles($phids); 88 + 89 + $list = new PHUIObjectItemListView(); 90 + foreach ($builds as $build) { 91 + $id = $build->getID(); 92 + $initiator = $handles[$build->getInitiatorPHID()]; 93 + $buildable_object = $handles[$build->getBuildable()->getBuildablePHID()]; 94 + 95 + $item = id(new PHUIObjectItemView()) 96 + ->setViewer($viewer) 97 + ->setObject($build) 98 + ->setObjectName(pht('Build %d', $build->getID())) 99 + ->setHeader($build->getName()) 100 + ->setHref($build->getURI()) 101 + ->setEpoch($build->getDateCreated()) 102 + ->addAttribute($buildable_object->getName()); 103 + 104 + if ($initiator) { 105 + $item->addHandleIcon($initiator, $initiator->getName()); 106 + } 107 + 108 + $status = $build->getBuildStatus(); 109 + 110 + $status_icon = HarbormasterBuild::getBuildStatusIcon($status); 111 + $status_color = HarbormasterBuild::getBuildStatusColor($status); 112 + $status_label = HarbormasterBuild::getBuildStatusName($status); 113 + 114 + $item->setStatusIcon("{$status_icon} {$status_color}", $status_label); 115 + 116 + $list->addItem($item); 117 + } 118 + 119 + $result = new PhabricatorApplicationSearchResultView(); 120 + $result->setObjectList($list); 121 + $result->setNoDataString(pht('No builds found.')); 122 + 123 + return $result; 124 + } 125 + 126 + }
+16 -22
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 71 71 * @return string Human-readable name. 72 72 */ 73 73 public static function getBuildStatusName($status) { 74 - switch ($status) { 75 - case self::STATUS_INACTIVE: 76 - return pht('Inactive'); 77 - case self::STATUS_PENDING: 78 - return pht('Pending'); 79 - case self::STATUS_BUILDING: 80 - return pht('Building'); 81 - case self::STATUS_PASSED: 82 - return pht('Passed'); 83 - case self::STATUS_FAILED: 84 - return pht('Failed'); 85 - case self::STATUS_ABORTED: 86 - return pht('Aborted'); 87 - case self::STATUS_ERROR: 88 - return pht('Unexpected Error'); 89 - case self::STATUS_PAUSED: 90 - return pht('Paused'); 91 - case self::STATUS_DEADLOCKED: 92 - return pht('Deadlocked'); 93 - default: 94 - return pht('Unknown'); 95 - } 74 + $map = self::getBuildStatusMap(); 75 + return idx($map, $status, pht('Unknown ("%s")', $status)); 76 + } 77 + 78 + public static function getBuildStatusMap() { 79 + return array( 80 + self::STATUS_INACTIVE => pht('Inactive'), 81 + self::STATUS_PENDING => pht('Pending'), 82 + self::STATUS_BUILDING => pht('Building'), 83 + self::STATUS_PASSED => pht('Passed'), 84 + self::STATUS_FAILED => pht('Failed'), 85 + self::STATUS_ABORTED => pht('Aborted'), 86 + self::STATUS_ERROR => pht('Unexpected Error'), 87 + self::STATUS_PAUSED => pht('Paused'), 88 + self::STATUS_DEADLOCKED => pht('Deadlocked'), 89 + ); 96 90 } 97 91 98 92 public static function getBuildStatusIcon($status) {
+45
src/applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php
··· 1 + <?php 2 + 3 + final class HarbormasterBuildStatusDatasource 4 + extends PhabricatorTypeaheadDatasource { 5 + 6 + public function getBrowseTitle() { 7 + return pht('Choose Build Statuses'); 8 + } 9 + 10 + public function getPlaceholderText() { 11 + return pht('Type a build status name...'); 12 + } 13 + 14 + public function getDatasourceApplicationClass() { 15 + return 'PhabricatorHarbormasterApplication'; 16 + } 17 + 18 + public function loadResults() { 19 + $results = $this->buildResults(); 20 + return $this->filterResultsAgainstTokens($results); 21 + } 22 + 23 + public function renderTokens(array $values) { 24 + return $this->renderTokensFromResults($this->buildResults(), $values); 25 + } 26 + 27 + private function buildResults() { 28 + $results = array(); 29 + 30 + $status_map = HarbormasterBuild::getBuildStatusMap(); 31 + foreach ($status_map as $value => $name) { 32 + $result = id(new PhabricatorTypeaheadResult()) 33 + ->setIcon(HarbormasterBuild::getBuildStatusIcon($value)) 34 + ->setColor(HarbormasterBuild::getBuildStatusColor($value)) 35 + ->setPHID($value) 36 + ->setName($name) 37 + ->addAttribute(pht('Status')); 38 + 39 + $results[$value] = $result; 40 + } 41 + 42 + return $results; 43 + } 44 + 45 + }