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

Implement support for leasing from Drydock hosts in Harbormaster

Summary:
This adds LeaseHostBuildStepImplementation for getting leases on hosts in Drydock via Harbormaster. It stores the resulting lease in an artifact.

There is also a few bug fixes as well.

Test Plan: Created a build plan with a "Lease Host" build step. Ran the build plan and saw the build pass and the artifact in the database.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley

CC: Korvin, epriestley, aran

Maniphest Tasks: T1049, T4111

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

+190 -9
+2
src/__phutil_library_map__.php
··· 775 775 'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php', 776 776 'JavelinViewExample' => 'applications/uiexample/examples/JavelinViewExample.php', 777 777 'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php', 778 + 'LeaseHostBuildStepImplementation' => 'applications/harbormaster/step/LeaseHostBuildStepImplementation.php', 778 779 'LegalpadConstants' => 'applications/legalpad/constants/LegalpadConstants.php', 779 780 'LegalpadController' => 'applications/legalpad/controller/LegalpadController.php', 780 781 'LegalpadDAO' => 'applications/legalpad/storage/LegalpadDAO.php', ··· 3154 3155 'JavelinUIExample' => 'PhabricatorUIExample', 3155 3156 'JavelinViewExample' => 'PhabricatorUIExample', 3156 3157 'JavelinViewExampleServerView' => 'AphrontView', 3158 + 'LeaseHostBuildStepImplementation' => 'BuildStepImplementation', 3157 3159 'LegalpadController' => 'PhabricatorController', 3158 3160 'LegalpadDAO' => 'PhabricatorLiskDAO', 3159 3161 'LegalpadDocument' =>
+57 -3
src/applications/harbormaster/step/BuildStepImplementation.php
··· 57 57 } 58 58 59 59 /** 60 - * Loads the settings for this build step implementation from a build target. 60 + * Loads the settings for this build step implementation from a build 61 + * step or target. 61 62 */ 62 - public final function loadSettings(HarbormasterBuildTarget $build_target) { 63 + public final function loadSettings($build_object) { 63 64 $this->settings = array(); 64 65 $this->validateSettingDefinitions(); 65 66 foreach ($this->getSettingDefinitions() as $name => $opt) { 66 - $this->settings[$name] = $build_target->getDetail($name); 67 + $this->settings[$name] = $build_object->getDetail($name); 67 68 } 68 69 return $this->settings; 69 70 } ··· 93 94 */ 94 95 public function getSettingRemarkupInstructions() { 95 96 return null; 97 + } 98 + 99 + /** 100 + * Return the name of artifacts produced by this command. 101 + * 102 + * Something like: 103 + * 104 + * return array( 105 + * 'some_name_input_by_user' => 'host'); 106 + * 107 + * Future steps will calculate all available artifact mappings 108 + * before them and filter on the type. 109 + * 110 + * @return array The mappings of artifact names to their types. 111 + */ 112 + public function getArtifactMappings() { 113 + return array(); 114 + } 115 + 116 + /** 117 + * Returns a list of all artifacts made available by previous build steps. 118 + */ 119 + public static function getAvailableArtifacts( 120 + HarbormasterBuildStep $current_build_step, 121 + $artifact_type) { 122 + 123 + $build_plan_phid = $current_build_step->getBuildPlanPHID(); 124 + 125 + $build_plan = id(new HarbormasterBuildPlanQuery()) 126 + ->withPHIDs(array($build_plan_phid)) 127 + ->executeOne(); 128 + 129 + $build_steps = $build_plan->loadOrderedBuildSteps(); 130 + 131 + $previous_implementations = array(); 132 + for ($i = 0; $i < count($build_steps); $i++) { 133 + if ($build_steps[$i]->getPHID() === $current_build_step->getPHID()) { 134 + break; 135 + } 136 + $previous_implementations[$i] = $build_steps[$i]->getStepImplementation(); 137 + } 138 + 139 + $artifact_arrays = mpull($previous_implementations, 'getArtifactMappings'); 140 + $artifacts = array(); 141 + foreach ($artifact_arrays as $array) { 142 + foreach ($array as $name => $type) { 143 + if ($type !== $artifact_type) { 144 + continue; 145 + } 146 + $artifacts[$name] = $type; 147 + } 148 + } 149 + return $artifacts; 96 150 } 97 151 }
+76
src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php
··· 1 + <?php 2 + 3 + final class LeaseHostBuildStepImplementation 4 + extends BuildStepImplementation { 5 + 6 + public function getName() { 7 + return pht('Lease Host'); 8 + } 9 + 10 + public function getGenericDescription() { 11 + return pht('Obtain a lease on a Drydock host for performing builds.'); 12 + } 13 + 14 + public function getDescription() { 15 + $settings = $this->getSettings(); 16 + 17 + return pht( 18 + 'Obtain a lease on a Drydock host whose platform is \'%s\'.', 19 + $settings['platform']); 20 + } 21 + 22 + public function execute( 23 + HarbormasterBuild $build, 24 + HarbormasterBuildTarget $build_target) { 25 + 26 + $settings = $this->getSettings(); 27 + 28 + // Create the lease. 29 + $lease = new DrydockLease(); 30 + $lease->setResourceType('host'); 31 + $lease->setAttributes( 32 + array('platform' => $settings['platform'])); 33 + $lease->queueForActivation(); 34 + 35 + // Wait until the lease is fulfilled. 36 + // TODO: This will throw an exception if the lease can't be fulfilled; 37 + // we should treat that as build failure not build error. 38 + $lease->waitUntilActive(); 39 + 40 + // Create the associated artifact. 41 + $artifact = $build->createArtifact( 42 + $build_target, 43 + $settings['name'], 44 + 'host'); 45 + $artifact->setArtifactData(array( 46 + 'drydock-lease' => $lease->getID())); 47 + $artifact->save(); 48 + } 49 + 50 + public function validateSettings() { 51 + $settings = $this->getSettings(); 52 + 53 + if ($settings['name'] === null || !is_string($settings['name'])) { 54 + return false; 55 + } 56 + if ($settings['platform'] === null || !is_string($settings['platform'])) { 57 + return false; 58 + } 59 + 60 + return true; 61 + } 62 + 63 + public function getSettingDefinitions() { 64 + return array( 65 + 'name' => array( 66 + 'name' => 'Artifact Name', 67 + 'description' => 68 + 'The name of the artifact to reference in future build steps.', 69 + 'type' => BuildStepImplementation::SETTING_TYPE_STRING), 70 + 'platform' => array( 71 + 'name' => 'Platform', 72 + 'description' => 'The platform of the host.', 73 + 'type' => BuildStepImplementation::SETTING_TYPE_STRING)); 74 + } 75 + 76 + }
+13
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 106 106 return $log; 107 107 } 108 108 109 + public function createArtifact( 110 + HarbormasterBuildTarget $build_target, 111 + $artifact_key, 112 + $artifact_type) { 113 + 114 + $artifact = 115 + HarbormasterBuildArtifact::initializeNewBuildArtifact($build_target); 116 + $artifact->setArtifactKey($artifact_key); 117 + $artifact->setArtifactType($artifact_type); 118 + $artifact->save(); 119 + return $artifact; 120 + } 121 + 109 122 /** 110 123 * Checks for and handles build cancellation. If this method returns 111 124 * true, the caller should stop any current operations and return control
+9 -2
src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php
··· 3 3 final class HarbormasterBuildArtifact extends HarbormasterDAO 4 4 implements PhabricatorPolicyInterface { 5 5 6 - protected $buildablePHID; 6 + protected $buildTargetPHID; 7 7 protected $artifactType; 8 8 protected $artifactIndex; 9 9 protected $artifactKey; 10 10 protected $artifactData = array(); 11 + 12 + public static function initializeNewBuildArtifact( 13 + HarbormasterBuildTarget $build_target) { 14 + return id(new HarbormasterBuildArtifact()) 15 + ->setBuildTargetPHID($build_target->getPHID()); 16 + } 11 17 12 18 public function getConfiguration() { 13 19 return array( ··· 27 33 } 28 34 29 35 public function setArtifactKey($key) { 30 - $this->artifactIndex = PhabricatorHash::digestForIndex($key); 36 + $this->artifactIndex = 37 + PhabricatorHash::digestForIndex($this->buildTargetPHID.$key); 31 38 $this->artifactKey = $key; 32 39 return $this; 33 40 }
+13
src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php
··· 36 36 return $this->assertAttached($this->buildSteps); 37 37 } 38 38 39 + /** 40 + * Returns a standard, ordered list of build steps for this build plan. 41 + * 42 + * This method should be used to load build steps for a given build plan 43 + * so that the ordering is consistent. 44 + */ 45 + public function loadOrderedBuildSteps() { 46 + return id(new HarbormasterBuildStepQuery()) 47 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 48 + ->withBuildPlanPHIDs(array($this->getPHID())) 49 + ->execute(); 50 + } 51 + 39 52 40 53 /* -( PhabricatorSubscribableInterface )----------------------------------- */ 41 54
+19
src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php
··· 41 41 return $this; 42 42 } 43 43 44 + public function getStepImplementation() { 45 + if ($this->className === null) { 46 + throw new Exception("No implementation set for the given step."); 47 + } 48 + 49 + static $implementations = null; 50 + if ($implementations === null) { 51 + $implementations = BuildStepImplementation::getImplementations(); 52 + } 53 + 54 + $class = $this->className; 55 + if (!in_array($class, $implementations)) { 56 + throw new Exception( 57 + "Class name '".$class."' does not extend BuildStepImplementation."); 58 + } 59 + $implementation = newv($class, array()); 60 + $implementation->loadSettings($this); 61 + return $implementation; 62 + } 44 63 45 64 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 46 65
+1 -4
src/applications/harbormaster/worker/HarbormasterBuildWorker.php
··· 38 38 $buildable = $build->getBuildable(); 39 39 $plan = $build->getBuildPlan(); 40 40 41 - $steps = id(new HarbormasterBuildStepQuery()) 42 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 43 - ->withBuildPlanPHIDs(array($plan->getPHID())) 44 - ->execute(); 41 + $steps = $plan->loadOrderedBuildSteps(); 45 42 46 43 // Perform the build. 47 44 foreach ($steps as $step) {