@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

Modularize the Harbormaster "Run build plan" Herald action

Ref T8726. Modularizes "Run build plan" in Differential and Diffusion.

+223 -84
+6
resources/sql/autopatches/20150730.herald.7.sql
··· 1 + UPDATE {$NAMESPACE}_herald.herald_action a 2 + JOIN {$NAMESPACE}_herald.herald_rule r 3 + ON a.ruleID = r.id 4 + SET a.action = 'harbormaster.build' 5 + WHERE r.ruleType != 'personal' 6 + AND a.action = 'applybuildplans';
+11 -2
src/__phutil_library_map__.php
··· 963 963 'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php', 964 964 'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php', 965 965 'HarbormasterBuildableActionController' => 'applications/harbormaster/controller/HarbormasterBuildableActionController.php', 966 + 'HarbormasterBuildableAdapterInterface' => 'applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php', 966 967 'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php', 967 968 'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php', 968 969 'HarbormasterBuildablePHIDType' => 'applications/harbormaster/phid/HarbormasterBuildablePHIDType.php', ··· 996 997 'HarbormasterQueryBuildablesConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildablesConduitAPIMethod.php', 997 998 'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php', 998 999 'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php', 1000 + 'HarbormasterRunBuildPlansHeraldAction' => 'applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php', 999 1001 'HarbormasterSchemaSpec' => 'applications/harbormaster/storage/HarbormasterSchemaSpec.php', 1000 1002 'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php', 1001 1003 'HarbormasterSendMessageConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php', ··· 4703 4705 'HarbormasterQueryBuildablesConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 4704 4706 'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 4705 4707 'HarbormasterRemarkupRule' => 'PhabricatorObjectRemarkupRule', 4708 + 'HarbormasterRunBuildPlansHeraldAction' => 'HeraldAction', 4706 4709 'HarbormasterSchemaSpec' => 'PhabricatorConfigSchemaSpec', 4707 4710 'HarbormasterScratchTable' => 'HarbormasterDAO', 4708 4711 'HarbormasterSendMessageConduitAPIMethod' => 'HarbormasterConduitAPIMethod', ··· 4728 4731 'HeraldApplicationActionGroup' => 'HeraldActionGroup', 4729 4732 'HeraldApplyTranscript' => 'Phobject', 4730 4733 'HeraldBasicFieldGroup' => 'HeraldFieldGroup', 4731 - 'HeraldCommitAdapter' => 'HeraldAdapter', 4734 + 'HeraldCommitAdapter' => array( 4735 + 'HeraldAdapter', 4736 + 'HarbormasterBuildableAdapterInterface', 4737 + ), 4732 4738 'HeraldCondition' => 'HeraldDAO', 4733 4739 'HeraldConditionTranscript' => 'Phobject', 4734 4740 'HeraldContentSourceField' => 'HeraldField', ··· 4737 4743 'HeraldDAO' => 'PhabricatorLiskDAO', 4738 4744 'HeraldDifferentialAdapter' => 'HeraldAdapter', 4739 4745 'HeraldDifferentialDiffAdapter' => 'HeraldDifferentialAdapter', 4740 - 'HeraldDifferentialRevisionAdapter' => 'HeraldDifferentialAdapter', 4746 + 'HeraldDifferentialRevisionAdapter' => array( 4747 + 'HeraldDifferentialAdapter', 4748 + 'HarbormasterBuildableAdapterInterface', 4749 + ), 4741 4750 'HeraldDisableController' => 'HeraldController', 4742 4751 'HeraldDoNothingAction' => 'HeraldAction', 4743 4752 'HeraldEditFieldGroup' => 'HeraldFieldGroup',
-5
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 901 901 'auditReasonMap', $this->auditReasonMap); 902 902 } 903 903 904 - HarbormasterBuildable::applyBuildPlans( 905 - $object->getPHID(), 906 - $object->getRepository()->getPHID(), 907 - $adapter->getBuildPlans()); 908 - 909 904 $limit = self::MAX_FILES_SHOWN_IN_EMAIL; 910 905 $files = $adapter->loadAffectedPaths(); 911 906 sort($files);
-14
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 1591 1591 return $adapter; 1592 1592 } 1593 1593 1594 - protected function didApplyHeraldRules( 1595 - PhabricatorLiskDAO $object, 1596 - HeraldAdapter $adapter, 1597 - HeraldTranscript $transcript) { 1598 - 1599 - // Apply build plans. 1600 - HarbormasterBuildable::applyBuildPlans( 1601 - $adapter->getDiff()->getPHID(), 1602 - $adapter->getPHID(), 1603 - $adapter->getBuildPlans()); 1604 - 1605 - return array(); 1606 - } 1607 - 1608 1594 /** 1609 1595 * Update the table which links Differential revisions to paths they affect, 1610 1596 * so Diffusion can efficiently find pending revisions for a given file.
+18 -41
src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
··· 1 1 <?php 2 2 3 3 final class HeraldDifferentialRevisionAdapter 4 - extends HeraldDifferentialAdapter { 4 + extends HeraldDifferentialAdapter 5 + implements HarbormasterBuildableAdapterInterface { 5 6 6 7 protected $revision; 7 8 8 - protected $buildPlans = array(); 9 - 10 9 protected $affectedPackages; 11 10 protected $changesets; 12 11 private $haveHunks; 12 + 13 + private $buildPlanPHIDs = array(); 13 14 14 15 public function getAdapterApplicationClass() { 15 16 return 'PhabricatorDifferentialApplication'; ··· 79 80 return $object; 80 81 } 81 82 82 - public function getBuildPlans() { 83 - return $this->buildPlans; 84 - } 85 - 86 83 public function getHeraldName() { 87 84 return $this->revision->getTitle(); 88 85 } ··· 130 127 return mpull($reviewers, 'getReviewerPHID'); 131 128 } 132 129 133 - public function getActions($rule_type) { 134 - switch ($rule_type) { 135 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 136 - return array_merge( 137 - array( 138 - self::ACTION_APPLY_BUILD_PLANS, 139 - ), 140 - parent::getActions($rule_type)); 141 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 142 - return array_merge( 143 - array(), 144 - parent::getActions($rule_type)); 145 - } 130 + 131 + /* -( HarbormasterBuildableAdapterInterface )------------------------------ */ 132 + 133 + 134 + public function getHarbormasterBuildablePHID() { 135 + return $this->getDiff()->getPHID(); 146 136 } 147 137 148 - public function applyHeraldEffects(array $effects) { 149 - assert_instances_of($effects, 'HeraldEffect'); 138 + public function getHarbormasterContainerPHID() { 139 + return $this->getObject()->getPHID(); 140 + } 150 141 151 - $result = array(); 142 + public function getQueuedHarbormasterBuildPlanPHIDs() { 143 + return $this->buildPlanPHIDs; 144 + } 152 145 153 - foreach ($effects as $effect) { 154 - $action = $effect->getAction(); 155 - switch ($action) { 156 - case self::ACTION_APPLY_BUILD_PLANS: 157 - foreach ($effect->getTarget() as $phid) { 158 - $this->buildPlans[] = $phid; 159 - } 160 - $result[] = new HeraldApplyTranscript( 161 - $effect, 162 - true, 163 - pht('Applied build plans.')); 164 - break; 165 - default: 166 - $result[] = $this->applyStandardEffect($effect); 167 - break; 168 - } 169 - } 170 - return $result; 146 + public function queueHarbormasterBuildPlanPHID($phid) { 147 + $this->buildPlanPHIDs[] = $phid; 171 148 } 172 149 173 150 }
+25 -16
src/applications/diffusion/herald/HeraldCommitAdapter.php
··· 1 1 <?php 2 2 3 - final class HeraldCommitAdapter extends HeraldAdapter { 3 + final class HeraldCommitAdapter 4 + extends HeraldAdapter 5 + implements HarbormasterBuildableAdapterInterface { 4 6 5 7 protected $diff; 6 8 protected $revision; ··· 11 13 private $commitDiff; 12 14 13 15 protected $auditMap = array(); 14 - protected $buildPlans = array(); 15 16 16 17 protected $affectedPaths; 17 18 protected $affectedRevision; 18 19 protected $affectedPackages; 19 20 protected $auditNeededPackages; 20 21 22 + private $buildPlanPHIDs = array(); 23 + 21 24 public function getAdapterApplicationClass() { 22 25 return 'PhabricatorDiffusionApplication'; 23 26 } ··· 90 93 return array_merge( 91 94 array( 92 95 self::ACTION_AUDIT, 93 - self::ACTION_APPLY_BUILD_PLANS, 94 96 ), 95 97 parent::getActions($rule_type)); 96 98 case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: ··· 149 151 150 152 public function getAuditMap() { 151 153 return $this->auditMap; 152 - } 153 - 154 - public function getBuildPlans() { 155 - return $this->buildPlans; 156 154 } 157 155 158 156 public function getHeraldName() { ··· 343 341 true, 344 342 pht('Triggered an audit.')); 345 343 break; 346 - case self::ACTION_APPLY_BUILD_PLANS: 347 - foreach ($effect->getTarget() as $phid) { 348 - $this->buildPlans[] = $phid; 349 - } 350 - $result[] = new HeraldApplyTranscript( 351 - $effect, 352 - true, 353 - pht('Applied build plans.')); 354 - break; 355 344 default: 356 345 $result[] = $this->applyStandardEffect($effect); 357 346 break; 358 347 } 359 348 } 360 349 return $result; 350 + } 351 + 352 + 353 + /* -( HarbormasterBuildableAdapterInterface )------------------------------ */ 354 + 355 + 356 + public function getHarbormasterBuildablePHID() { 357 + return $this->getObject()->getPHID(); 358 + } 359 + 360 + public function getHarbormasterContainerPHID() { 361 + return $this->getObject()->getRepository()->getPHID(); 362 + } 363 + 364 + public function getQueuedHarbormasterBuildPlanPHIDs() { 365 + return $this->buildPlanPHIDs; 366 + } 367 + 368 + public function queueHarbormasterBuildPlanPHID($phid) { 369 + $this->buildPlanPHIDs[] = $phid; 361 370 } 362 371 363 372 }
+34
src/applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php
··· 1 + <?php 2 + 3 + interface HarbormasterBuildableAdapterInterface { 4 + 5 + public function getHarbormasterBuildablePHID(); 6 + public function getHarbormasterContainerPHID(); 7 + public function getQueuedHarbormasterBuildPlanPHIDs(); 8 + public function queueHarbormasterBuildPlanPHID($phid); 9 + 10 + } 11 + 12 + // TEMPLATE IMPLEMENTATION ///////////////////////////////////////////////////// 13 + 14 + 15 + /* -( HarbormasterBuildableAdapterInterface )------------------------------ */ 16 + /* 17 + 18 + public function getHarbormasterBuildablePHID() { 19 + return $this->getObject()->getPHID(); 20 + } 21 + 22 + public function getHarbormasterContainerPHID() { 23 + return null; 24 + } 25 + 26 + public function getQueuedHarbormasterBuildPlanPHIDs() { 27 + return $this->buildPlanPHIDs; 28 + } 29 + 30 + public function queueHarbormasterBuildPlanPHID($phid) { 31 + $this->buildPlanPHIDs[] = $phid; 32 + } 33 + 34 + */
+121
src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php
··· 1 + <?php 2 + 3 + final class HarbormasterRunBuildPlansHeraldAction 4 + extends HeraldAction { 5 + 6 + const DO_NO_TARGETS = 'do.no-targets'; 7 + const DO_INVALID = 'do.invalid'; 8 + const DO_BUILD = 'do.build'; 9 + 10 + const ACTIONCONST = 'harbormaster.build'; 11 + 12 + public function getActionGroupKey() { 13 + return HeraldSupportActionGroup::ACTIONGROUPKEY; 14 + } 15 + 16 + public function supportsObject($object) { 17 + $adapter = $this->getAdapter(); 18 + return ($adapter instanceof HarbormasterBuildableAdapterInterface); 19 + } 20 + 21 + protected function applyBuilds(array $phids) { 22 + $adapter = $this->getAdapter(); 23 + 24 + $phids = array_fuse($phids); 25 + if (!$phids) { 26 + $this->logEffect(self::DO_NO_TARGETS); 27 + return; 28 + } 29 + 30 + $plans = id(new HarbormasterBuildPlanQuery()) 31 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 32 + ->withPHIDs($phids) 33 + ->execute(); 34 + $plans = mpull($plans, null, 'getPHID'); 35 + 36 + $invalid = array(); 37 + foreach ($phids as $phid) { 38 + if (empty($plans[$phid])) { 39 + $invalid[] = $phid; 40 + unset($plans[$phid]); 41 + } 42 + } 43 + 44 + if ($invalid) { 45 + $this->logEffect(self::DO_INVALID, $phids); 46 + } 47 + 48 + if (!$phids) { 49 + return; 50 + } 51 + 52 + foreach ($phids as $phid) { 53 + $adapter->queueHarbormasterBuildPlanPHID($phid); 54 + } 55 + 56 + $this->logEffect(self::DO_BUILD, $phids); 57 + } 58 + 59 + protected function getActionEffectMap() { 60 + return array( 61 + self::DO_NO_TARGETS => array( 62 + 'icon' => 'fa-ban', 63 + 'color' => 'grey', 64 + 'name' => pht('No Targets'), 65 + ), 66 + self::DO_INVALID => array( 67 + 'icon' => 'fa-ban', 68 + 'color' => 'red', 69 + 'name' => pht('Invalid Targets'), 70 + ), 71 + self::DO_ALREADY_REQUIRED => array( 72 + 'icon' => 'fa-play', 73 + 'color' => 'green', 74 + 'name' => pht('Building'), 75 + ), 76 + ); 77 + } 78 + 79 + public function renderActionEffectDescription($type, $data) { 80 + switch ($type) { 81 + case self::DO_NO_TARGETS: 82 + return pht('Rule lists no targets.'); 83 + case self::DO_INVALID: 84 + return pht( 85 + '%s build plan(s) are not valid: %s.', 86 + new PhutilNumber(count($data)), 87 + $this->renderHandleList($data)); 88 + case self::DO_REQUIRED: 89 + return pht( 90 + 'Started %s build(s): %s.', 91 + new PhutilNumber(count($data)), 92 + $this->renderHandleList($data)); 93 + } 94 + } 95 + 96 + public function getHeraldActionName() { 97 + return pht('Run build plans'); 98 + } 99 + 100 + public function supportsRuleType($rule_type) { 101 + return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); 102 + } 103 + 104 + public function applyEffect($object, HeraldEffect $effect) { 105 + return $this->applyBuilds($effect->getTarget()); 106 + } 107 + 108 + public function getHeraldActionStandardType() { 109 + return self::STANDARD_PHID_LIST; 110 + } 111 + 112 + protected function getDatasource() { 113 + return new HarbormasterBuildPlanDatasource(); 114 + } 115 + 116 + public function renderActionDescription($value) { 117 + return pht( 118 + 'Run build plans: %s.', 119 + $this->renderHandleList($value)); 120 + } 121 + }
+1 -1
src/applications/harbormaster/storage/HarbormasterBuildable.php
··· 104 104 $container_phid, 105 105 array $plan_phids) { 106 106 107 - if (count($plan_phids) === 0) { 107 + if (!$plan_phids) { 108 108 return; 109 109 } 110 110
-5
src/applications/herald/adapter/HeraldAdapter.php
··· 27 27 const CONDITION_IS_FALSE = 'false'; 28 28 29 29 const ACTION_AUDIT = 'audit'; 30 - const ACTION_APPLY_BUILD_PLANS = 'applybuildplans'; 31 30 const ACTION_BLOCK = 'block'; 32 31 33 32 private $contentSource; ··· 714 713 case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 715 714 $standard = array( 716 715 self::ACTION_AUDIT => pht('Trigger an Audit by'), 717 - self::ACTION_APPLY_BUILD_PLANS => pht('Run build plans'), 718 716 self::ACTION_BLOCK => pht('Block change with message'), 719 717 ); 720 718 break; ··· 800 798 } else { 801 799 switch ($action) { 802 800 case self::ACTION_AUDIT: 803 - case self::ACTION_APPLY_BUILD_PLANS: 804 - return $this->buildTokenizerFieldValue( 805 - new HarbormasterBuildPlanDatasource()); 806 801 case self::ACTION_BLOCK: 807 802 return new HeraldTextFieldValue(); 808 803 }
+7
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 2811 2811 $this->setHeraldAdapter($adapter); 2812 2812 $this->setHeraldTranscript($xscript); 2813 2813 2814 + if ($adapter instanceof HarbormasterBuildableAdapterInterface) { 2815 + HarbormasterBuildable::applyBuildPlans( 2816 + $adapter->getHarbormasterBuildablePHID(), 2817 + $adapter->getHarbormasterContainerPHID(), 2818 + $adapter->getQueuedHarbormasterBuildPlanPHIDs()); 2819 + } 2820 + 2814 2821 return array_merge( 2815 2822 $this->didApplyHeraldRules($object, $adapter, $xscript), 2816 2823 $adapter->getQueuedTransactions());