[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/harbormaster/storage/build/ -> HarbormasterBuild.php (source)

   1  <?php
   2  
   3  final class HarbormasterBuild extends HarbormasterDAO
   4    implements PhabricatorPolicyInterface {
   5  
   6    protected $buildablePHID;
   7    protected $buildPlanPHID;
   8    protected $buildStatus;
   9    protected $buildGeneration;
  10  
  11    private $buildable = self::ATTACHABLE;
  12    private $buildPlan = self::ATTACHABLE;
  13    private $buildTargets = self::ATTACHABLE;
  14    private $unprocessedCommands = self::ATTACHABLE;
  15  
  16    /**
  17     * Not currently being built.
  18     */
  19    const STATUS_INACTIVE = 'inactive';
  20  
  21    /**
  22     * Pending pick up by the Harbormaster daemon.
  23     */
  24    const STATUS_PENDING = 'pending';
  25  
  26    /**
  27     * Current building the buildable.
  28     */
  29    const STATUS_BUILDING = 'building';
  30  
  31    /**
  32     * The build has passed.
  33     */
  34    const STATUS_PASSED = 'passed';
  35  
  36    /**
  37     * The build has failed.
  38     */
  39    const STATUS_FAILED = 'failed';
  40  
  41    /**
  42     * The build encountered an unexpected error.
  43     */
  44    const STATUS_ERROR = 'error';
  45  
  46    /**
  47     * The build has been stopped.
  48     */
  49    const STATUS_STOPPED = 'stopped';
  50  
  51    /**
  52     * The build has been deadlocked.
  53     */
  54    const STATUS_DEADLOCKED = 'deadlocked';
  55  
  56  
  57    /**
  58     * Get a human readable name for a build status constant.
  59     *
  60     * @param  const  Build status constant.
  61     * @return string Human-readable name.
  62     */
  63    public static function getBuildStatusName($status) {
  64      switch ($status) {
  65        case self::STATUS_INACTIVE:
  66          return pht('Inactive');
  67        case self::STATUS_PENDING:
  68          return pht('Pending');
  69        case self::STATUS_BUILDING:
  70          return pht('Building');
  71        case self::STATUS_PASSED:
  72          return pht('Passed');
  73        case self::STATUS_FAILED:
  74          return pht('Failed');
  75        case self::STATUS_ERROR:
  76          return pht('Unexpected Error');
  77        case self::STATUS_STOPPED:
  78          return pht('Paused');
  79        case self::STATUS_DEADLOCKED:
  80          return pht('Deadlocked');
  81        default:
  82          return pht('Unknown');
  83      }
  84    }
  85  
  86    public static function getBuildStatusIcon($status) {
  87      switch ($status) {
  88        case self::STATUS_INACTIVE:
  89        case self::STATUS_PENDING:
  90          return PHUIStatusItemView::ICON_OPEN;
  91        case self::STATUS_BUILDING:
  92          return PHUIStatusItemView::ICON_RIGHT;
  93        case self::STATUS_PASSED:
  94          return PHUIStatusItemView::ICON_ACCEPT;
  95        case self::STATUS_FAILED:
  96          return PHUIStatusItemView::ICON_REJECT;
  97        case self::STATUS_ERROR:
  98          return PHUIStatusItemView::ICON_MINUS;
  99        case self::STATUS_STOPPED:
 100          return PHUIStatusItemView::ICON_MINUS;
 101        case self::STATUS_DEADLOCKED:
 102          return PHUIStatusItemView::ICON_WARNING;
 103        default:
 104          return PHUIStatusItemView::ICON_QUESTION;
 105      }
 106    }
 107  
 108    public static function getBuildStatusColor($status) {
 109      switch ($status) {
 110        case self::STATUS_INACTIVE:
 111          return 'dark';
 112        case self::STATUS_PENDING:
 113        case self::STATUS_BUILDING:
 114          return 'blue';
 115        case self::STATUS_PASSED:
 116          return 'green';
 117        case self::STATUS_FAILED:
 118        case self::STATUS_ERROR:
 119        case self::STATUS_DEADLOCKED:
 120          return 'red';
 121        case self::STATUS_STOPPED:
 122          return 'dark';
 123        default:
 124          return 'bluegrey';
 125      }
 126    }
 127  
 128    public static function initializeNewBuild(PhabricatorUser $actor) {
 129      return id(new HarbormasterBuild())
 130        ->setBuildStatus(self::STATUS_INACTIVE)
 131        ->setBuildGeneration(0);
 132    }
 133  
 134    public function delete() {
 135      $this->openTransaction();
 136        $this->deleteUnprocessedCommands();
 137        $result = parent::delete();
 138      $this->saveTransaction();
 139  
 140      return $result;
 141    }
 142  
 143    public function getConfiguration() {
 144      return array(
 145        self::CONFIG_AUX_PHID => true,
 146        self::CONFIG_COLUMN_SCHEMA => array(
 147          'buildStatus' => 'text32',
 148          'buildGeneration' => 'uint32',
 149        ),
 150        self::CONFIG_KEY_SCHEMA => array(
 151          'key_buildable' => array(
 152            'columns' => array('buildablePHID'),
 153          ),
 154          'key_plan' => array(
 155            'columns' => array('buildPlanPHID'),
 156          ),
 157          'key_status' => array(
 158            'columns' => array('buildStatus'),
 159          ),
 160        ),
 161      ) + parent::getConfiguration();
 162    }
 163  
 164    public function generatePHID() {
 165      return PhabricatorPHID::generateNewPHID(
 166        HarbormasterBuildPHIDType::TYPECONST);
 167    }
 168  
 169    public function attachBuildable(HarbormasterBuildable $buildable) {
 170      $this->buildable = $buildable;
 171      return $this;
 172    }
 173  
 174    public function getBuildable() {
 175      return $this->assertAttached($this->buildable);
 176    }
 177  
 178    public function getName() {
 179      if ($this->getBuildPlan()) {
 180        return $this->getBuildPlan()->getName();
 181      }
 182      return pht('Build');
 183    }
 184  
 185    public function attachBuildPlan(
 186      HarbormasterBuildPlan $build_plan = null) {
 187      $this->buildPlan = $build_plan;
 188      return $this;
 189    }
 190  
 191    public function getBuildPlan() {
 192      return $this->assertAttached($this->buildPlan);
 193    }
 194  
 195    public function getBuildTargets() {
 196      return $this->assertAttached($this->buildTargets);
 197    }
 198  
 199    public function attachBuildTargets(array $targets) {
 200      $this->buildTargets = $targets;
 201      return $this;
 202    }
 203  
 204    public function isBuilding() {
 205      return $this->getBuildStatus() === self::STATUS_PENDING ||
 206        $this->getBuildStatus() === self::STATUS_BUILDING;
 207    }
 208  
 209    public function createLog(
 210      HarbormasterBuildTarget $build_target,
 211      $log_source,
 212      $log_type) {
 213  
 214      $log_source = id(new PhutilUTF8StringTruncator())
 215        ->setMaximumCodepoints(250)
 216        ->truncateString($log_source);
 217  
 218      $log = HarbormasterBuildLog::initializeNewBuildLog($build_target)
 219        ->setLogSource($log_source)
 220        ->setLogType($log_type)
 221        ->save();
 222  
 223      return $log;
 224    }
 225  
 226    public function createArtifact(
 227      HarbormasterBuildTarget $build_target,
 228      $artifact_key,
 229      $artifact_type) {
 230  
 231      $artifact =
 232        HarbormasterBuildArtifact::initializeNewBuildArtifact($build_target);
 233      $artifact->setArtifactKey(
 234        $this->getPHID(),
 235        $this->getBuildGeneration(),
 236        $artifact_key);
 237      $artifact->setArtifactType($artifact_type);
 238      $artifact->save();
 239      return $artifact;
 240    }
 241  
 242    public function loadArtifact($name) {
 243      $artifact = id(new HarbormasterBuildArtifactQuery())
 244        ->setViewer(PhabricatorUser::getOmnipotentUser())
 245        ->withArtifactKeys(
 246          $this->getPHID(),
 247          $this->getBuildGeneration(),
 248          array($name))
 249        ->executeOne();
 250      if ($artifact === null) {
 251        throw new Exception('Artifact not found!');
 252      }
 253      return $artifact;
 254    }
 255  
 256    public function retrieveVariablesFromBuild() {
 257      $results = array(
 258        'buildable.diff' => null,
 259        'buildable.revision' => null,
 260        'buildable.commit' => null,
 261        'repository.callsign' => null,
 262        'repository.vcs' => null,
 263        'repository.uri' => null,
 264        'step.timestamp' => null,
 265        'build.id' => null,
 266      );
 267  
 268      $buildable = $this->getBuildable();
 269      $object = $buildable->getBuildableObject();
 270  
 271      $object_variables = $object->getBuildVariables();
 272  
 273      $results = $object_variables + $results;
 274  
 275      $results['step.timestamp'] = time();
 276      $results['build.id'] = $this->getID();
 277  
 278      return $results;
 279    }
 280  
 281    public static function getAvailableBuildVariables() {
 282      $objects = id(new PhutilSymbolLoader())
 283        ->setAncestorClass('HarbormasterBuildableInterface')
 284        ->loadObjects();
 285  
 286      $variables = array();
 287      $variables[] = array(
 288        'step.timestamp' => pht('The current UNIX timestamp.'),
 289        'build.id' => pht('The ID of the current build.'),
 290        'target.phid' => pht('The PHID of the current build target.'),
 291      );
 292  
 293      foreach ($objects as $object) {
 294        $variables[] = $object->getAvailableBuildVariables();
 295      }
 296  
 297      $variables = array_mergev($variables);
 298      return $variables;
 299    }
 300  
 301    public function isComplete() {
 302      switch ($this->getBuildStatus()) {
 303        case self::STATUS_PASSED:
 304        case self::STATUS_FAILED:
 305        case self::STATUS_ERROR:
 306        case self::STATUS_STOPPED:
 307          return true;
 308      }
 309  
 310      return false;
 311    }
 312  
 313    public function isStopped() {
 314      return ($this->getBuildStatus() == self::STATUS_STOPPED);
 315    }
 316  
 317  
 318  /* -(  Build Commands  )----------------------------------------------------- */
 319  
 320  
 321    private function getUnprocessedCommands() {
 322      return $this->assertAttached($this->unprocessedCommands);
 323    }
 324  
 325    public function attachUnprocessedCommands(array $commands) {
 326      $this->unprocessedCommands = $commands;
 327      return $this;
 328    }
 329  
 330    public function canRestartBuild() {
 331      return !$this->isRestarting();
 332    }
 333  
 334    public function canStopBuild() {
 335      return !$this->isComplete() &&
 336             !$this->isStopped() &&
 337             !$this->isStopping();
 338    }
 339  
 340    public function canResumeBuild() {
 341      return $this->isStopped() &&
 342             !$this->isResuming();
 343    }
 344  
 345    public function isStopping() {
 346      $is_stopping = false;
 347      foreach ($this->getUnprocessedCommands() as $command_object) {
 348        $command = $command_object->getCommand();
 349        switch ($command) {
 350          case HarbormasterBuildCommand::COMMAND_STOP:
 351            $is_stopping = true;
 352            break;
 353          case HarbormasterBuildCommand::COMMAND_RESUME:
 354          case HarbormasterBuildCommand::COMMAND_RESTART:
 355            $is_stopping = false;
 356            break;
 357        }
 358      }
 359  
 360      return $is_stopping;
 361    }
 362  
 363    public function isResuming() {
 364      $is_resuming = false;
 365      foreach ($this->getUnprocessedCommands() as $command_object) {
 366        $command = $command_object->getCommand();
 367        switch ($command) {
 368          case HarbormasterBuildCommand::COMMAND_RESTART:
 369          case HarbormasterBuildCommand::COMMAND_RESUME:
 370            $is_resuming = true;
 371            break;
 372          case HarbormasterBuildCommand::COMMAND_STOP:
 373            $is_resuming = false;
 374            break;
 375        }
 376      }
 377  
 378      return $is_resuming;
 379    }
 380  
 381    public function isRestarting() {
 382      $is_restarting = false;
 383      foreach ($this->getUnprocessedCommands() as $command_object) {
 384        $command = $command_object->getCommand();
 385        switch ($command) {
 386          case HarbormasterBuildCommand::COMMAND_RESTART:
 387            $is_restarting = true;
 388            break;
 389        }
 390      }
 391  
 392      return $is_restarting;
 393    }
 394  
 395    public function deleteUnprocessedCommands() {
 396      foreach ($this->getUnprocessedCommands() as $key => $command_object) {
 397        $command_object->delete();
 398        unset($this->unprocessedCommands[$key]);
 399      }
 400  
 401      return $this;
 402    }
 403  
 404  
 405  /* -(  PhabricatorPolicyInterface  )----------------------------------------- */
 406  
 407  
 408    public function getCapabilities() {
 409      return array(
 410        PhabricatorPolicyCapability::CAN_VIEW,
 411        PhabricatorPolicyCapability::CAN_EDIT,
 412      );
 413    }
 414  
 415    public function getPolicy($capability) {
 416      return $this->getBuildable()->getPolicy($capability);
 417    }
 418  
 419    public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
 420      return $this->getBuildable()->hasAutomaticCapability(
 421        $capability,
 422        $viewer);
 423    }
 424  
 425    public function describeAutomaticCapability($capability) {
 426      return pht('A build inherits policies from its buildable.');
 427    }
 428  
 429  }


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