[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 abstract class HarbormasterBuildStepImplementation { 4 5 public static function getImplementations() { 6 return id(new PhutilSymbolLoader()) 7 ->setAncestorClass('HarbormasterBuildStepImplementation') 8 ->loadObjects(); 9 } 10 11 public static function getImplementation($class) { 12 $base = idx(self::getImplementations(), $class); 13 14 if ($base) { 15 return (clone $base); 16 } 17 18 return null; 19 } 20 21 public static function requireImplementation($class) { 22 if (!$class) { 23 throw new Exception(pht('No implementation is specified!')); 24 } 25 26 $implementation = self::getImplementation($class); 27 if (!$implementation) { 28 throw new Exception(pht('No such implementation "%s" exists!', $class)); 29 } 30 31 return $implementation; 32 } 33 34 /** 35 * The name of the implementation. 36 */ 37 abstract public function getName(); 38 39 /** 40 * The generic description of the implementation. 41 */ 42 public function getGenericDescription() { 43 return ''; 44 } 45 46 /** 47 * The description of the implementation, based on the current settings. 48 */ 49 public function getDescription() { 50 return $this->getGenericDescription(); 51 } 52 53 /** 54 * Run the build target against the specified build. 55 */ 56 abstract public function execute( 57 HarbormasterBuild $build, 58 HarbormasterBuildTarget $build_target); 59 60 /** 61 * Gets the settings for this build step. 62 */ 63 public function getSettings() { 64 return $this->settings; 65 } 66 67 public function getSetting($key, $default = null) { 68 return idx($this->settings, $key, $default); 69 } 70 71 /** 72 * Loads the settings for this build step implementation from a build 73 * step or target. 74 */ 75 public final function loadSettings($build_object) { 76 $this->settings = $build_object->getDetails(); 77 return $this; 78 } 79 80 /** 81 * Return the name of artifacts produced by this command. 82 * 83 * Something like: 84 * 85 * return array( 86 * 'some_name_input_by_user' => 'host'); 87 * 88 * Future steps will calculate all available artifact mappings 89 * before them and filter on the type. 90 * 91 * @return array The mappings of artifact names to their types. 92 */ 93 public function getArtifactInputs() { 94 return array(); 95 } 96 97 public function getArtifactOutputs() { 98 return array(); 99 } 100 101 public function getDependencies(HarbormasterBuildStep $build_step) { 102 $dependencies = $build_step->getDetail('dependsOn', array()); 103 104 $inputs = $build_step->getStepImplementation()->getArtifactInputs(); 105 $inputs = ipull($inputs, null, 'key'); 106 107 $artifacts = $this->getAvailableArtifacts( 108 $build_step->getBuildPlan(), 109 $build_step, 110 null); 111 112 foreach ($artifacts as $key => $type) { 113 if (!array_key_exists($key, $inputs)) { 114 unset($artifacts[$key]); 115 } 116 } 117 118 $artifact_steps = ipull($artifacts, 'step'); 119 $artifact_steps = mpull($artifact_steps, 'getPHID'); 120 121 $dependencies = array_merge($dependencies, $artifact_steps); 122 123 return $dependencies; 124 } 125 126 /** 127 * Returns a list of all artifacts made available in the build plan. 128 */ 129 public static function getAvailableArtifacts( 130 HarbormasterBuildPlan $build_plan, 131 $current_build_step, 132 $artifact_type) { 133 134 $steps = id(new HarbormasterBuildStepQuery()) 135 ->setViewer(PhabricatorUser::getOmnipotentUser()) 136 ->withBuildPlanPHIDs(array($build_plan->getPHID())) 137 ->execute(); 138 139 $artifacts = array(); 140 141 $artifact_arrays = array(); 142 foreach ($steps as $step) { 143 if ($current_build_step !== null && 144 $step->getPHID() === $current_build_step->getPHID()) { 145 146 continue; 147 } 148 149 $implementation = $step->getStepImplementation(); 150 $array = $implementation->getArtifactOutputs(); 151 $array = ipull($array, 'type', 'key'); 152 foreach ($array as $name => $type) { 153 if ($type !== $artifact_type && $artifact_type !== null) { 154 continue; 155 } 156 $artifacts[$name] = array('type' => $type, 'step' => $step); 157 } 158 } 159 160 return $artifacts; 161 } 162 163 /** 164 * Convert a user-provided string with variables in it, like: 165 * 166 * ls ${dirname} 167 * 168 * ...into a string with variables merged into it safely: 169 * 170 * ls 'dir with spaces' 171 * 172 * @param string Name of a `vxsprintf` function, like @{function:vcsprintf}. 173 * @param string User-provided pattern string containing `${variables}`. 174 * @param dict List of available replacement variables. 175 * @return string String with variables replaced safely into it. 176 */ 177 protected function mergeVariables($function, $pattern, array $variables) { 178 $regexp = '/\\$\\{(?P<name>[a-z\\.]+)\\}/'; 179 180 $matches = null; 181 preg_match_all($regexp, $pattern, $matches); 182 183 $argv = array(); 184 foreach ($matches['name'] as $name) { 185 if (!array_key_exists($name, $variables)) { 186 throw new Exception(pht("No such variable '%s'!", $name)); 187 } 188 $argv[] = $variables[$name]; 189 } 190 191 $pattern = str_replace('%', '%%', $pattern); 192 $pattern = preg_replace($regexp, '%s', $pattern); 193 194 return call_user_func($function, $pattern, $argv); 195 } 196 197 public function getFieldSpecifications() { 198 return array(); 199 } 200 201 protected function formatSettingForDescription($key, $default = null) { 202 return $this->formatValueForDescription($this->getSetting($key, $default)); 203 } 204 205 protected function formatValueForDescription($value) { 206 if (strlen($value)) { 207 return phutil_tag('strong', array(), $value); 208 } else { 209 return phutil_tag('em', array(), pht('(null)')); 210 } 211 } 212 213 public function supportsWaitForMessage() { 214 return false; 215 } 216 217 public function shouldWaitForMessage(HarbormasterBuildTarget $target) { 218 if (!$this->supportsWaitForMessage()) { 219 return false; 220 } 221 222 return (bool)$target->getDetail('builtin.wait-for-message'); 223 } 224 225 protected function shouldAbort( 226 HarbormasterBuild $build, 227 HarbormasterBuildTarget $target) { 228 229 return $build->getBuildGeneration() !== $target->getBuildGeneration(); 230 } 231 232 protected function resolveFuture( 233 HarbormasterBuild $build, 234 HarbormasterBuildTarget $target, 235 Future $future) { 236 237 $futures = Futures(array($future)); 238 foreach ($futures->setUpdateInterval(5) as $key => $future) { 239 if ($future === null) { 240 $build->reload(); 241 if ($this->shouldAbort($build, $target)) { 242 throw new HarbormasterBuildAbortedException(); 243 } 244 } else { 245 return $future->resolve(); 246 } 247 } 248 } 249 250 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |