[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/harbormaster/step/ -> HarbormasterBuildStepImplementation.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1