@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 builds to have parameters

Summary: Ref T9352. See D13635. Build targets can have variables already, but let builds have them too. This mostly enables future use cases (sub-builds, more sophisticated build triggers).

Test Plan: With a custom Herald rule + action like the one in T9352, updated a revision and saw it generate multiple builds with varying parameters.

Reviewers: chad, hach-que

Reviewed By: hach-que

Maniphest Tasks: T9352

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

+108 -27
+5
resources/sql/autopatches/20151002.harbormaster.bparam.1.sql
··· 1 + ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_build 2 + ADD buildParameters LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL; 3 + 4 + UPDATE {$NAMESPACE}_harbormaster.harbormaster_build 5 + SET buildParameters = '{}' WHERE buildParameters = '';
+2
src/__phutil_library_map__.php
··· 972 972 'HarbormasterBuildPlanTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlanTransaction.php', 973 973 'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php', 974 974 'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php', 975 + 'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.php', 975 976 'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php', 976 977 'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php', 977 978 'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php', ··· 4757 4758 'HarbormasterBuildPlanTransaction' => 'PhabricatorApplicationTransaction', 4758 4759 'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 4759 4760 'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4761 + 'HarbormasterBuildRequest' => 'Phobject', 4760 4762 'HarbormasterBuildStep' => array( 4761 4763 'HarbormasterDAO', 4762 4764 'PhabricatorApplicationTransactionInterface',
+6 -5
src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
··· 10 10 protected $changesets; 11 11 private $haveHunks; 12 12 13 - private $buildPlanPHIDs = array(); 13 + private $buildRequests = array(); 14 14 15 15 public function getAdapterApplicationClass() { 16 16 return 'PhabricatorDifferentialApplication'; ··· 139 139 return $this->getObject()->getPHID(); 140 140 } 141 141 142 - public function getQueuedHarbormasterBuildPlanPHIDs() { 143 - return $this->buildPlanPHIDs; 142 + public function getQueuedHarbormasterBuildRequests() { 143 + return $this->buildRequests; 144 144 } 145 145 146 - public function queueHarbormasterBuildPlanPHID($phid) { 147 - $this->buildPlanPHIDs[] = $phid; 146 + public function queueHarbormasterBuildRequest( 147 + HarbormasterBuildRequest $request) { 148 + $this->buildRequests[] = $request; 148 149 } 149 150 150 151 }
+6 -5
src/applications/diffusion/herald/HeraldCommitAdapter.php
··· 17 17 protected $affectedPackages; 18 18 protected $auditNeededPackages; 19 19 20 - private $buildPlanPHIDs = array(); 20 + private $buildRequests = array(); 21 21 22 22 public function getAdapterApplicationClass() { 23 23 return 'PhabricatorDiffusionApplication'; ··· 308 308 return $this->getObject()->getRepository()->getPHID(); 309 309 } 310 310 311 - public function getQueuedHarbormasterBuildPlanPHIDs() { 312 - return $this->buildPlanPHIDs; 311 + public function getQueuedHarbormasterBuildRequests() { 312 + return $this->buildRequests; 313 313 } 314 314 315 - public function queueHarbormasterBuildPlanPHID($phid) { 316 - $this->buildPlanPHIDs[] = $phid; 315 + public function queueHarbormasterBuildRequest( 316 + HarbormasterBuildRequest $request) { 317 + $this->buildRequests[] = $request; 317 318 } 318 319 319 320 }
+1 -1
src/applications/harbormaster/controller/HarbormasterPlanRunController.php
··· 62 62 63 63 if (!$errors) { 64 64 $buildable->save(); 65 - $buildable->applyPlan($plan); 65 + $buildable->applyPlan($plan, array()); 66 66 67 67 $buildable_uri = '/B'.$buildable->getID(); 68 68 return id(new AphrontRedirectResponse())->setURI($buildable_uri);
+37
src/applications/harbormaster/engine/HarbormasterBuildRequest.php
··· 1 + <?php 2 + 3 + /** 4 + * Structure used to ask Harbormaster to start a build. 5 + * 6 + * Requests to start builds sometimes originate several layers away from where 7 + * they are processed. For example, Herald rules which start builds pass the 8 + * requests through the adapter and then through the editor before they reach 9 + * Harbormaster. 10 + * 11 + * This class is just a thin wrapper around these requests so we can make them 12 + * more complex later without needing to rewrite any APIs. 13 + */ 14 + final class HarbormasterBuildRequest extends Phobject { 15 + 16 + private $buildPlanPHID; 17 + private $buildParameters = array(); 18 + 19 + public function setBuildPlanPHID($build_plan_phid) { 20 + $this->buildPlanPHID = $build_plan_phid; 21 + return $this; 22 + } 23 + 24 + public function getBuildPlanPHID() { 25 + return $this->buildPlanPHID; 26 + } 27 + 28 + public function setBuildParameters(array $build_parameters) { 29 + $this->buildParameters = $build_parameters; 30 + return $this; 31 + } 32 + 33 + public function getBuildParameters() { 34 + return $this->buildParameters; 35 + } 36 + 37 + }
+1 -1
src/applications/harbormaster/engine/HarbormasterTargetEngine.php
··· 206 206 // resource and "own" it, so we don't try to handle this, but may need 207 207 // to be more careful here if use of autotargets expands. 208 208 209 - $build = $buildable->applyPlan($plan); 209 + $build = $buildable->applyPlan($plan, array()); 210 210 PhabricatorWorker::setRunAllTasksInProcess(false); 211 211 } catch (Exception $ex) { 212 212 PhabricatorWorker::setRunAllTasksInProcess(false);
+3 -2
src/applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php
··· 4 4 5 5 public function getHarbormasterBuildablePHID(); 6 6 public function getHarbormasterContainerPHID(); 7 - public function getQueuedHarbormasterBuildPlanPHIDs(); 8 - public function queueHarbormasterBuildPlanPHID($phid); 7 + public function getQueuedHarbormasterBuildRequests(); 8 + public function queueHarbormasterBuildRequest( 9 + HarbormasterBuildRequest $request); 9 10 10 11 } 11 12
+3 -1
src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php
··· 31 31 $phids = array_fuse(array_keys($targets)); 32 32 33 33 foreach ($phids as $phid) { 34 - $adapter->queueHarbormasterBuildPlanPHID($phid); 34 + $request = id(new HarbormasterBuildRequest()) 35 + ->setBuildPlanPHID($phid); 36 + $adapter->queueHarbormasterBuildRequest($request); 35 37 } 36 38 37 39 $this->logEffect(self::DO_BUILD, $phids);
+1 -1
src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php
··· 89 89 PhabricatorEnv::getProductionURI('/B'.$buildable->getID())); 90 90 91 91 PhabricatorWorker::setRunAllTasksInProcess(true); 92 - $buildable->applyPlan($plan); 92 + $buildable->applyPlan($plan, array()); 93 93 94 94 $console->writeOut("%s\n", pht('Done.')); 95 95
+1 -1
src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php
··· 194 194 * @return string String with variables replaced safely into it. 195 195 */ 196 196 protected function mergeVariables($function, $pattern, array $variables) { 197 - $regexp = '/\\$\\{(?P<name>[a-z\\.]+)\\}/'; 197 + $regexp = '@\\$\\{(?P<name>[a-z\\./-]+)\\}@'; 198 198 199 199 $matches = null; 200 200 preg_match_all($regexp, $pattern, $matches);
+33 -9
src/applications/harbormaster/storage/HarbormasterBuildable.php
··· 96 96 } 97 97 98 98 /** 99 - * Looks up the plan PHIDs and applies the plans to the specified 100 - * object identified by it's PHID. 99 + * Start builds for a given buildable. 100 + * 101 + * @param phid PHID of the object to build. 102 + * @param phid Container PHID for the buildable. 103 + * @param list<HarbormasterBuildRequest> List of builds to perform. 104 + * @return void 101 105 */ 102 106 public static function applyBuildPlans( 103 107 $phid, 104 108 $container_phid, 105 - array $plan_phids) { 109 + array $requests) { 110 + 111 + assert_instances_of($requests, 'HarbormasterBuildRequest'); 106 112 107 - if (!$plan_phids) { 113 + if (!$requests) { 108 114 return; 109 115 } 110 116 ··· 115 121 if (!PhabricatorApplication::isClassInstalled($harbormaster_app)) { 116 122 return; 117 123 } 124 + 125 + $viewer = PhabricatorUser::getOmnipotentUser(); 118 126 119 127 $buildable = self::createOrLoadExisting( 120 - PhabricatorUser::getOmnipotentUser(), 128 + $viewer, 121 129 $phid, 122 130 $container_phid); 123 131 132 + $plan_phids = mpull($requests, 'getBuildPlanPHID'); 124 133 $plans = id(new HarbormasterBuildPlanQuery()) 125 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 134 + ->setViewer($viewer) 126 135 ->withPHIDs($plan_phids) 127 136 ->execute(); 128 - foreach ($plans as $plan) { 137 + $plans = mpull($plans, null, 'getPHID'); 138 + 139 + foreach ($requests as $request) { 140 + $plan_phid = $request->getBuildPlanPHID(); 141 + $plan = idx($plans, $plan_phid); 142 + 143 + if (!$plan) { 144 + throw new Exception( 145 + pht( 146 + 'Failed to load build plan ("%s").', 147 + $plan_phid)); 148 + } 149 + 129 150 if ($plan->isDisabled()) { 130 151 // TODO: This should be communicated more clearly -- maybe we should 131 152 // create the build but set the status to "disabled" or "derelict". 132 153 continue; 133 154 } 134 155 135 - $buildable->applyPlan($plan); 156 + $parameters = $request->getBuildParameters(); 157 + $buildable->applyPlan($plan, $parameters); 136 158 } 137 159 } 138 160 139 - public function applyPlan(HarbormasterBuildPlan $plan) { 161 + public function applyPlan(HarbormasterBuildPlan $plan, array $parameters) { 162 + 140 163 $viewer = PhabricatorUser::getOmnipotentUser(); 141 164 $build = HarbormasterBuild::initializeNewBuild($viewer) 142 165 ->setBuildablePHID($this->getPHID()) 143 166 ->setBuildPlanPHID($plan->getPHID()) 167 + ->setBuildParameters($parameters) 144 168 ->setBuildStatus(HarbormasterBuild::STATUS_PENDING); 145 169 146 170 $auto_key = $plan->getPlanAutoKey();
+8
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 9 9 protected $buildPlanPHID; 10 10 protected $buildStatus; 11 11 protected $buildGeneration; 12 + protected $buildParameters = array(); 12 13 protected $planAutoKey; 13 14 14 15 private $buildable = self::ATTACHABLE; ··· 156 157 protected function getConfiguration() { 157 158 return array( 158 159 self::CONFIG_AUX_PHID => true, 160 + self::CONFIG_SERIALIZATION => array( 161 + 'buildParameters' => self::SERIALIZATION_JSON, 162 + ), 159 163 self::CONFIG_COLUMN_SCHEMA => array( 160 164 'buildStatus' => 'text32', 161 165 'buildGeneration' => 'uint32', ··· 257 261 'step.timestamp' => null, 258 262 'build.id' => null, 259 263 ); 264 + 265 + foreach ($this->getBuildParameters() as $key => $value) { 266 + $results['build/'.$key] = $value; 267 + } 260 268 261 269 $buildable = $this->getBuildable(); 262 270 $object = $buildable->getBuildableObject();
+1 -1
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 2837 2837 HarbormasterBuildable::applyBuildPlans( 2838 2838 $adapter->getHarbormasterBuildablePHID(), 2839 2839 $adapter->getHarbormasterContainerPHID(), 2840 - $adapter->getQueuedHarbormasterBuildPlanPHIDs()); 2840 + $adapter->getQueuedHarbormasterBuildRequests()); 2841 2841 } 2842 2842 2843 2843 return array_merge(