Subsume 'harbormaster.querybuilds' with a modern search API method
Summary: We deprecate the existing API method used to access build information from the API, but preserve its response structure after calling through to the new method.  I've cordoned off the fields I needed to define in order to meet the output structure by putting those fields in a search attachment.
Test Plan:
Used the API console and looked at the list view controller for builds.
Old output structure:
```lang=json
{
  "data": [
    {
      "id": "16823",
      "phid": "PHID-HMBD-xghrwfz6luoye5rgc2hq",
      "uri": "https://secure.phabricator.com/harbormaster/build/16823/",
      "name": "Run Core Tests",
      "buildablePHID": "PHID-HMBB-s6ykzm2jzxz4ymduztq3",
      "buildPlanPHID": "PHID-HMCP-pcfxcgyoif67l3buc4zt",
      "buildStatus": "passed",
      "buildStatusName": "Passed"
    }
  ],
  "cursor": {
    "limit": 100,
    "after": "16823",
    "before": null
  }
}
```
New output structure:
```lang=json
{
  "data": [
    {
      "id": 1,
      "type": "HMBD",
      "phid": "PHID-HMBD-qpgcmv67tzaauzayzit5",
      "uri": "http://ec2-54-165-244-168.compute-1.amazonaws.com/harbormaster/build/1/",
      "name": "arc lint + arc unit",
      "buildStatusName": "Passed",
      "buildablePHID": "PHID-HMBB-qdefith5uakkepqpjr2g",
      "buildPlanPHID": "PHID-HMCP-zswbhazb7ipmaf4plygg",
      "buildStatus": "passed",
      "initiatorPHID": "PHID-USER-rihx4366f3aczsvc2wtb",
      "dateCreated": 1450295643,
      "dateModified": 1450295644,
      "policy": {
        "view": "users",
        "edit": "users"
      }
    }
  ],
  "maps": {},
  "query": {
    "queryKey": null
  },
  "cursor": {
    "limit": 100,
    "after": null,
    "before": null,
    "order": null
  }
}
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D16356
			
			
This commit is contained in:
		| @@ -1131,6 +1131,7 @@ phutil_register_library_map(array( | ||||
|     'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php', | ||||
|     'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php', | ||||
|     'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.php', | ||||
|     'HarbormasterBuildSearchConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildSearchConduitAPIMethod.php', | ||||
|     'HarbormasterBuildSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildSearchEngine.php', | ||||
|     'HarbormasterBuildStatus' => 'applications/harbormaster/constants/HarbormasterBuildStatus.php', | ||||
|     'HarbormasterBuildStatusDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php', | ||||
| @@ -1204,6 +1205,7 @@ phutil_register_library_map(array( | ||||
|     'HarbormasterQueryAutotargetsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryAutotargetsConduitAPIMethod.php', | ||||
|     'HarbormasterQueryBuildablesConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildablesConduitAPIMethod.php', | ||||
|     'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php', | ||||
|     'HarbormasterQueryBuildsSearchEngineAttachment' => 'applications/harbormaster/engineextension/HarbormasterQueryBuildsSearchEngineAttachment.php', | ||||
|     'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php', | ||||
|     'HarbormasterRunBuildPlansHeraldAction' => 'applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php', | ||||
|     'HarbormasterSchemaSpec' => 'applications/harbormaster/storage/HarbormasterSchemaSpec.php', | ||||
| @@ -5637,6 +5639,7 @@ phutil_register_library_map(array( | ||||
|       'HarbormasterDAO', | ||||
|       'PhabricatorApplicationTransactionInterface', | ||||
|       'PhabricatorPolicyInterface', | ||||
|       'PhabricatorConduitResultInterface', | ||||
|     ), | ||||
|     'HarbormasterBuildAbortedException' => 'Exception', | ||||
|     'HarbormasterBuildActionController' => 'HarbormasterController', | ||||
| @@ -5691,6 +5694,7 @@ phutil_register_library_map(array( | ||||
|     'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'HarbormasterBuildRequest' => 'Phobject', | ||||
|     'HarbormasterBuildSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', | ||||
|     'HarbormasterBuildSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'HarbormasterBuildStatus' => 'Phobject', | ||||
|     'HarbormasterBuildStatusDatasource' => 'PhabricatorTypeaheadDatasource', | ||||
| @@ -5777,6 +5781,7 @@ phutil_register_library_map(array( | ||||
|     'HarbormasterQueryAutotargetsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', | ||||
|     'HarbormasterQueryBuildablesConduitAPIMethod' => 'HarbormasterConduitAPIMethod', | ||||
|     'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', | ||||
|     'HarbormasterQueryBuildsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', | ||||
|     'HarbormasterRemarkupRule' => 'PhabricatorObjectRemarkupRule', | ||||
|     'HarbormasterRunBuildPlansHeraldAction' => 'HeraldAction', | ||||
|     'HarbormasterSchemaSpec' => 'PhabricatorConfigSchemaSpec', | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| final class HarbormasterBuildSearchConduitAPIMethod | ||||
|   extends PhabricatorSearchEngineAPIMethod { | ||||
|  | ||||
|   public function getAPIMethodName() { | ||||
|     return 'harbormaster.build.search'; | ||||
|   } | ||||
|  | ||||
|   public function newSearchEngine() { | ||||
|     return new HarbormasterBuildSearchEngine(); | ||||
|   } | ||||
|  | ||||
|   public function getMethodSummary() { | ||||
|     return pht('Find out information about builds.'); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -11,6 +11,14 @@ final class HarbormasterQueryBuildsConduitAPIMethod | ||||
|     return pht('Query Harbormaster builds.'); | ||||
|   } | ||||
|  | ||||
|   public function getMethodStatus() { | ||||
|     return self::METHOD_STATUS_DEPRECATED; | ||||
|   } | ||||
|  | ||||
|   public function getMethodStatusDescription() { | ||||
|     return pht('Use %s instead.', 'harbormaster.build.search'); | ||||
|   } | ||||
|  | ||||
|   protected function defineParamTypes() { | ||||
|     return array( | ||||
|       'ids' => 'optional list<id>', | ||||
| @@ -27,65 +35,39 @@ final class HarbormasterQueryBuildsConduitAPIMethod | ||||
|  | ||||
|   protected function execute(ConduitAPIRequest $request) { | ||||
|     $viewer = $request->getUser(); | ||||
|     $call = new ConduitCall( | ||||
|       'harbormaster.build.search', | ||||
|       array_filter(array( | ||||
|         'constraints' => array_filter(array( | ||||
|           'ids' => $request->getValue('ids'), | ||||
|           'phids' => $request->getValue('phids'), | ||||
|           'statuses' => $request->getValue('buildStatuses'), | ||||
|           'buildables' => $request->getValue('buildablePHIDs'), | ||||
|           'plans' => $request->getValue('buildPlanPHIDs'), | ||||
|         )), | ||||
|         'attachments' => array( | ||||
|           'querybuilds' => true, | ||||
|         ), | ||||
|         'limit' => $request->getValue('limit'), | ||||
|         'before' => $request->getValue('before'), | ||||
|         'after' => $request->getValue('after'), | ||||
|       ))); | ||||
|  | ||||
|     $query = id(new HarbormasterBuildQuery()) | ||||
|       ->setViewer($viewer); | ||||
|     $subsumption = $call->setUser($viewer) | ||||
|       ->execute(); | ||||
|  | ||||
|     $ids = $request->getValue('ids'); | ||||
|     if ($ids !== null) { | ||||
|       $query->withIDs($ids); | ||||
|     $data = []; | ||||
|     foreach ($subsumption['data'] as $build_data) { | ||||
|       $querybuilds = idxv($build_data, array('attachments', 'querybuilds'), []); | ||||
|       $fields = idx($build_data, 'fields', []); | ||||
|       unset($build_data['fields']); | ||||
|       unset($build_data['attachments']); | ||||
|       $data[] = array_mergev(array($build_data, $querybuilds, $fields)); | ||||
|     } | ||||
|  | ||||
|     $phids = $request->getValue('phids'); | ||||
|     if ($phids !== null) { | ||||
|       $query->withPHIDs($phids); | ||||
|     } | ||||
|     $subsumption['data'] = $data; | ||||
|  | ||||
|     $statuses = $request->getValue('buildStatuses'); | ||||
|     if ($statuses !== null) { | ||||
|       $query->withBuildStatuses($statuses); | ||||
|     } | ||||
|  | ||||
|     $buildable_phids = $request->getValue('buildablePHIDs'); | ||||
|     if ($buildable_phids !== null) { | ||||
|       $query->withBuildablePHIDs($buildable_phids); | ||||
|     } | ||||
|  | ||||
|     $build_plan_phids = $request->getValue('buildPlanPHIDs'); | ||||
|     if ($build_plan_phids !== null) { | ||||
|       $query->withBuildPlanPHIDs($build_plan_phids); | ||||
|     } | ||||
|  | ||||
|     $pager = $this->newPager($request); | ||||
|  | ||||
|     $builds = $query->executeWithCursorPager($pager); | ||||
|  | ||||
|     $data = array(); | ||||
|     foreach ($builds as $build) { | ||||
|  | ||||
|       $id = $build->getID(); | ||||
|       $uri = '/harbormaster/build/'.$id.'/'; | ||||
|       $status = $build->getBuildStatus(); | ||||
|       $status_name = HarbormasterBuildStatus::getBuildStatusName($status); | ||||
|  | ||||
|       $data[] = array( | ||||
|         'id' => $id, | ||||
|         'phid' => $build->getPHID(), | ||||
|         'uri' => PhabricatorEnv::getProductionURI($uri), | ||||
|         'name' => $build->getBuildPlan()->getName(), | ||||
|         'buildablePHID' => $build->getBuildablePHID(), | ||||
|         'buildPlanPHID' => $build->getBuildPlanPHID(), | ||||
|         'buildStatus' => $status, | ||||
|         'buildStatusName' => $status_name, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     $results = array( | ||||
|       'data' => $data, | ||||
|     ); | ||||
|  | ||||
|     $results = $this->addPagerResults($results, $pager); | ||||
|     return $results; | ||||
|     return $subsumption; | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| final class HarbormasterQueryBuildsSearchEngineAttachment | ||||
|   extends PhabricatorSearchEngineAttachment { | ||||
|  | ||||
|   public function getAttachmentName() { | ||||
|     return pht('Harbormaster Query Builds'); | ||||
|   } | ||||
|  | ||||
|   public function getAttachmentDescription() { | ||||
|     return pht( | ||||
|       'This attachment exists solely to provide compatibility with the '. | ||||
|       'message format returned by an outdated API method. It will be '. | ||||
|       'taken away at some point and you should not rely on these fields '. | ||||
|       'being available.'); | ||||
|   } | ||||
|  | ||||
|   public function getAttachmentForObject($object, $data, $spec) { | ||||
|     $status_name = HarbormasterBuildStatus::getBuildStatusName( | ||||
|       $object->getBuildStatus()); | ||||
|     return array( | ||||
|       'uri' => PhabricatorEnv::getProductionURI($object->getURI()), | ||||
|       'name' => $object->getName(), | ||||
|       'buildStatusName' => $status_name, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -24,6 +24,12 @@ final class HarbormasterBuildSearchEngine | ||||
|         ->setDescription( | ||||
|           pht('Search for builds running a given build plan.')) | ||||
|         ->setDatasource(new HarbormasterBuildPlanDatasource()), | ||||
|       id(new PhabricatorPHIDsSearchField()) | ||||
|         ->setLabel(pht('Buildables')) | ||||
|         ->setKey('buildables') | ||||
|         ->setAliases(array('buildable')) | ||||
|         ->setDescription( | ||||
|           pht('Search for builds running against particular buildables.')), | ||||
|       id(new PhabricatorSearchDatasourceField()) | ||||
|         ->setLabel(pht('Statuses')) | ||||
|         ->setKey('statuses') | ||||
| @@ -42,6 +48,12 @@ final class HarbormasterBuildSearchEngine | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected function getHiddenFields() { | ||||
|     return array( | ||||
|       'buildables', | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected function buildQueryFromParameters(array $map) { | ||||
|     $query = $this->newQuery(); | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,8 @@ | ||||
| final class HarbormasterBuild extends HarbormasterDAO | ||||
|   implements | ||||
|     PhabricatorApplicationTransactionInterface, | ||||
|     PhabricatorPolicyInterface { | ||||
|     PhabricatorPolicyInterface, | ||||
|     PhabricatorConduitResultInterface { | ||||
|  | ||||
|   protected $buildablePHID; | ||||
|   protected $buildPlanPHID; | ||||
| @@ -397,4 +398,49 @@ final class HarbormasterBuild extends HarbormasterDAO | ||||
|     return pht('A build inherits policies from its buildable.'); | ||||
|   } | ||||
|  | ||||
|  | ||||
| /* -(  PhabricatorConduitResultInterface  )---------------------------------- */ | ||||
|  | ||||
|  | ||||
|   public function getFieldSpecificationsForConduit() { | ||||
|     return array( | ||||
|       id(new PhabricatorConduitSearchFieldSpecification()) | ||||
|         ->setKey('buildablePHID') | ||||
|         ->setType('phid') | ||||
|         ->setDescription(pht('PHID of the object this build is building.')), | ||||
|       id(new PhabricatorConduitSearchFieldSpecification()) | ||||
|         ->setKey('buildPlanPHID') | ||||
|         ->setType('phid') | ||||
|         ->setDescription(pht('PHID of the build plan being run.')), | ||||
|       id(new PhabricatorConduitSearchFieldSpecification()) | ||||
|         ->setKey('buildStatus') | ||||
|         ->setType('map<string, wild>') | ||||
|         ->setDescription(pht('The current status of this build.')), | ||||
|       id(new PhabricatorConduitSearchFieldSpecification()) | ||||
|         ->setKey('initiatorPHID') | ||||
|         ->setType('phid') | ||||
|         ->setDescription(pht('The person (or thing) that started this build.')), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getFieldValuesForConduit() { | ||||
|     $status = $this->getBuildStatus(); | ||||
|     return array( | ||||
|       'buildablePHID' => $this->getBuildablePHID(), | ||||
|       'buildPlanPHID' => $this->getBuildPlanPHID(), | ||||
|       'buildStatus' => array( | ||||
|         'value' => $status, | ||||
|         'name' => HarbormasterBuildStatus::getBuildStatusName($status), | ||||
|       ), | ||||
|       'initiatorPHID' => nonempty($this->getInitiatorPHID(), null), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getConduitSearchAttachments() { | ||||
|     return array( | ||||
|       id(new HarbormasterQueryBuildsSearchEngineAttachment()) | ||||
|         ->setAttachmentKey('querybuilds'), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Mike Riley
					Mike Riley