[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
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 }
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 |