@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.

Allow repositories to be bound to an AlmanacService

Summary:
Ref T2783. This is primarily exploratory and just figuring out what we're blocked on:

- Allow a Repository to be bound to a Service. The Service may eventually define multiple read/write nodes, etc.
- There's no UI to do this binding yet, you have to touch the database manually.
- If a repository is bound to a Service, effect Conduit calls via calls to the remote service instead of executing them in-process.
- These don't actually work yet since there's no authentication (see T5955).

Test Plan:
- Made a nice Service with a nice Binding to a nice Interface on a nice Device.
- Force-associated a repository with the service using a raw MySQL query.
- Saw Phabricator try to make a remote call to the service (on localhost) and fail because of missing auth stuff.
- Also ran `almanac.queryservices`.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T2783

Differential Revision: https://secure.phabricator.com/D10982

+96 -18
+2
resources/sql/autopatches/20141210.reposervice.sql
··· 1 + ALTER TABLE {$NAMESPACE}_repository.repository 2 + ADD almanacServicePHID VARBINARY(64);
+3 -12
src/applications/almanac/conduit/AlmanacQueryServicesConduitAPIMethod.php
··· 31 31 $viewer = $request->getUser(); 32 32 33 33 $query = id(new AlmanacServiceQuery()) 34 - ->setViewer($viewer); 34 + ->setViewer($viewer) 35 + ->needBindings(true); 35 36 36 37 $ids = $request->getValue('ids'); 37 38 if ($ids !== null) { ··· 52 53 53 54 $services = $query->executeWithCursorPager($pager); 54 55 55 - if ($services) { 56 - $bindings = id(new AlmanacBindingQuery()) 57 - ->setViewer($viewer) 58 - ->withServicePHIDs(mpull($services, 'getPHID')) 59 - ->execute(); 60 - $bindings = mgroup($bindings, 'getServicePHID'); 61 - } else { 62 - $bindings = array(); 63 - } 64 - 65 56 $data = array(); 66 57 foreach ($services as $service) { 67 58 $phid = $service->getPHID(); ··· 69 60 $properties = $service->getAlmanacProperties(); 70 61 $properties = mpull($properties, 'getFieldValue', 'getFieldName'); 71 62 72 - $service_bindings = idx($bindings, $phid, array()); 63 + $service_bindings = $service->getBindings(); 73 64 $service_bindings = array_values($service_bindings); 74 65 foreach ($service_bindings as $key => $service_binding) { 75 66 $service_bindings[$key] = $this->getBindingDictionary($service_binding);
+24
src/applications/almanac/query/AlmanacServiceQuery.php
··· 6 6 private $ids; 7 7 private $phids; 8 8 private $names; 9 + private $needBindings; 9 10 10 11 public function withIDs(array $ids) { 11 12 $this->ids = $ids; ··· 19 20 20 21 public function withNames(array $names) { 21 22 $this->names = $names; 23 + return $this; 24 + } 25 + 26 + public function needBindings($need_bindings) { 27 + $this->needBindings = $need_bindings; 22 28 return $this; 23 29 } 24 30 ··· 69 75 $where[] = $this->buildPagingClause($conn_r); 70 76 71 77 return $this->formatWhereClause($where); 78 + } 79 + 80 + protected function didFilterPage(array $services) { 81 + if ($this->needBindings) { 82 + $service_phids = mpull($services, 'getPHID'); 83 + $bindings = id(new AlmanacBindingQuery()) 84 + ->setViewer($this->getViewer()) 85 + ->withServicePHIDs($service_phids) 86 + ->execute(); 87 + $bindings = mgroup($bindings, 'getServicePHID'); 88 + 89 + foreach ($services as $service) { 90 + $service_bindings = idx($bindings, $service->getPHID(), array()); 91 + $service->attachBindings($service_bindings); 92 + } 93 + } 94 + 95 + return parent::didFilterPage($services); 72 96 } 73 97 74 98 }
+10
src/applications/almanac/storage/AlmanacService.php
··· 17 17 18 18 private $customFields = self::ATTACHABLE; 19 19 private $almanacProperties = self::ATTACHABLE; 20 + private $bindings = self::ATTACHABLE; 20 21 21 22 public static function initializeNewService() { 22 23 return id(new AlmanacService()) ··· 63 64 64 65 public function getURI() { 65 66 return '/almanac/service/view/'.$this->getName().'/'; 67 + } 68 + 69 + public function getBindings() { 70 + return $this->assertAttached($this->bindings); 71 + } 72 + 73 + public function attachBindings(array $bindings) { 74 + $this->bindings = $bindings; 75 + return $this; 66 76 } 67 77 68 78
+55 -6
src/applications/diffusion/query/DiffusionQuery.php
··· 62 62 63 63 $params = $params + $core_params; 64 64 65 - return id(new ConduitCall( 66 - $method, 67 - $params 68 - )) 69 - ->setUser($user) 70 - ->execute(); 65 + $service_phid = $repository->getAlmanacServicePHID(); 66 + if ($service_phid === null) { 67 + return id(new ConduitCall($method, $params)) 68 + ->setUser($user) 69 + ->execute(); 70 + } 71 + 72 + $service = id(new AlmanacServiceQuery()) 73 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 74 + ->withPHIDs(array($service_phid)) 75 + ->needBindings(true) 76 + ->executeOne(); 77 + if (!$service) { 78 + throw new Exception( 79 + pht( 80 + 'The Alamnac service for this repository is invalid or could not '. 81 + 'be loaded.')); 82 + } 83 + 84 + $bindings = $service->getBindings(); 85 + if (!$bindings) { 86 + throw new Exception( 87 + pht( 88 + 'The Alamanc service for this repository is not bound to any '. 89 + 'interfaces.')); 90 + } 91 + 92 + $uris = array(); 93 + foreach ($bindings as $binding) { 94 + $iface = $binding->getInterface(); 95 + 96 + $protocol = $binding->getAlmanacPropertyValue('protocol'); 97 + if ($protocol === 'http') { 98 + $uris[] = 'http://'.$iface->renderDisplayAddress().'/'; 99 + } else if ($protocol === 'https' || $protocol === null) { 100 + $uris[] = 'https://'.$iface->renderDisplayAddress().'/'; 101 + } else { 102 + throw new Exception( 103 + pht( 104 + 'The Almanac service for this repository has a binding to an '. 105 + 'invalid interface with an unknown protocol ("%s").', 106 + $protocol)); 107 + } 108 + } 109 + 110 + shuffle($uris); 111 + $uri = head($uris); 112 + 113 + $domain = id(new PhutilURI(PhabricatorEnv::getURI('/')))->getDomain(); 114 + 115 + // TODO: This call needs authentication, which is blocked by T5955. 116 + 117 + return id(new ConduitClient($uri)) 118 + ->setHost($domain) 119 + ->callMethodSynchronous($method, $params); 71 120 } 72 121 73 122 public function execute() {
+2
src/applications/repository/storage/PhabricatorRepository.php
··· 52 52 protected $versionControlSystem; 53 53 protected $details = array(); 54 54 protected $credentialPHID; 55 + protected $almanacServicePHID; 55 56 56 57 private $commitCount = self::ATTACHABLE; 57 58 private $mostRecentCommit = self::ATTACHABLE; ··· 86 87 'uuid' => 'text64?', 87 88 'pushPolicy' => 'policy', 88 89 'credentialPHID' => 'phid?', 90 + 'almanacServicePHID' => 'phid?', 89 91 ), 90 92 self::CONFIG_KEY_SCHEMA => array( 91 93 'key_phid' => null,