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

When a build is aborted, fail the buildable

Summary:
Ref T13054. Fixes T10746. Fixes T11154. This is really a one-line fix (include `ABORTED` in `BuildEngine->updateBuildable()`) but try to structure the code a little more clearly too and reduce (at least slightly) the number of random lists of status attributes spread throughout the codebase.

Also add a header tag for buildable status.

Test Plan: Aborted a build, saw buildable fail properly.

Subscribers: yelirekim, PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13054, T11154, T10746

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

+105 -53
+75 -40
src/applications/harbormaster/constants/HarbormasterBuildStatus.php
··· 2 2 3 3 final class HarbormasterBuildStatus extends Phobject { 4 4 5 - /** 6 - * Not currently being built. 7 - */ 8 5 const STATUS_INACTIVE = 'inactive'; 9 - 10 - /** 11 - * Pending pick up by the Harbormaster daemon. 12 - */ 13 6 const STATUS_PENDING = 'pending'; 14 - 15 - /** 16 - * Current building the buildable. 17 - */ 18 7 const STATUS_BUILDING = 'building'; 19 - 20 - /** 21 - * The build has passed. 22 - */ 23 8 const STATUS_PASSED = 'passed'; 24 - 25 - /** 26 - * The build has failed. 27 - */ 28 9 const STATUS_FAILED = 'failed'; 29 - 30 - /** 31 - * The build has aborted. 32 - */ 33 10 const STATUS_ABORTED = 'aborted'; 11 + const STATUS_ERROR = 'error'; 12 + const STATUS_PAUSED = 'paused'; 13 + const STATUS_DEADLOCKED = 'deadlocked'; 34 14 35 - /** 36 - * The build encountered an unexpected error. 37 - */ 38 - const STATUS_ERROR = 'error'; 15 + private $key; 16 + private $properties; 17 + 18 + public function __construct($key, array $properties) { 19 + $this->key = $key; 20 + $this->properties = $properties; 21 + } 22 + 23 + public static function newBuildStatusObject($status) { 24 + $spec = self::getBuildStatusSpec($status); 25 + return new self($status, $spec); 26 + } 27 + 28 + private function getProperty($key) { 29 + if (!array_key_exists($key, $this->properties)) { 30 + throw new Exception( 31 + pht( 32 + 'Attempting to access unknown build status property ("%s").', 33 + $key)); 34 + } 35 + 36 + return $this->properties[$key]; 37 + } 38 + 39 + public function isBuilding() { 40 + return $this->getProperty('isBuilding'); 41 + } 42 + 43 + public function isPaused() { 44 + return ($this->key === self::STATUS_PAUSED); 45 + } 39 46 40 - /** 41 - * The build has been paused. 42 - */ 43 - const STATUS_PAUSED = 'paused'; 47 + public function isComplete() { 48 + return $this->getProperty('isComplete'); 49 + } 44 50 45 - /** 46 - * The build has been deadlocked. 47 - */ 48 - const STATUS_DEADLOCKED = 'deadlocked'; 51 + public function isPassed() { 52 + return ($this->key === self::STATUS_PASSED); 53 + } 49 54 50 55 51 56 /** ··· 56 61 */ 57 62 public static function getBuildStatusName($status) { 58 63 $spec = self::getBuildStatusSpec($status); 59 - return idx($spec, 'name', pht('Unknown ("%s")', $status)); 64 + return $spec['name']; 60 65 } 61 66 62 67 public static function getBuildStatusMap() { ··· 66 71 67 72 public static function getBuildStatusIcon($status) { 68 73 $spec = self::getBuildStatusSpec($status); 69 - return idx($spec, 'icon', 'fa-question-circle'); 74 + return $spec['icon']; 70 75 } 71 76 72 77 public static function getBuildStatusColor($status) { 73 78 $spec = self::getBuildStatusSpec($status); 74 - return idx($spec, 'color', 'bluegrey'); 79 + return $spec['color']; 75 80 } 76 81 77 82 public static function getBuildStatusANSIColor($status) { 78 83 $spec = self::getBuildStatusSpec($status); 79 - return idx($spec, 'color.ansi', 'magenta'); 84 + return $spec['color.ansi']; 80 85 } 81 86 82 87 public static function getWaitingStatusConstants() { ··· 110 115 'icon' => 'fa-circle-o', 111 116 'color' => 'dark', 112 117 'color.ansi' => 'yellow', 118 + 'isBuilding' => false, 119 + 'isComplete' => false, 113 120 ), 114 121 self::STATUS_PENDING => array( 115 122 'name' => pht('Pending'), 116 123 'icon' => 'fa-circle-o', 117 124 'color' => 'blue', 118 125 'color.ansi' => 'yellow', 126 + 'isBuilding' => true, 127 + 'isComplete' => false, 119 128 ), 120 129 self::STATUS_BUILDING => array( 121 130 'name' => pht('Building'), 122 131 'icon' => 'fa-chevron-circle-right', 123 132 'color' => 'blue', 124 133 'color.ansi' => 'yellow', 134 + 'isBuilding' => true, 135 + 'isComplete' => false, 125 136 ), 126 137 self::STATUS_PASSED => array( 127 138 'name' => pht('Passed'), 128 139 'icon' => 'fa-check-circle', 129 140 'color' => 'green', 130 141 'color.ansi' => 'green', 142 + 'isBuilding' => false, 143 + 'isComplete' => true, 131 144 ), 132 145 self::STATUS_FAILED => array( 133 146 'name' => pht('Failed'), 134 147 'icon' => 'fa-times-circle', 135 148 'color' => 'red', 136 149 'color.ansi' => 'red', 150 + 'isBuilding' => false, 151 + 'isComplete' => true, 137 152 ), 138 153 self::STATUS_ABORTED => array( 139 154 'name' => pht('Aborted'), 140 155 'icon' => 'fa-minus-circle', 141 156 'color' => 'red', 142 157 'color.ansi' => 'red', 158 + 'isBuilding' => false, 159 + 'isComplete' => true, 143 160 ), 144 161 self::STATUS_ERROR => array( 145 162 'name' => pht('Unexpected Error'), 146 163 'icon' => 'fa-minus-circle', 147 164 'color' => 'red', 148 165 'color.ansi' => 'red', 166 + 'isBuilding' => false, 167 + 'isComplete' => true, 149 168 ), 150 169 self::STATUS_PAUSED => array( 151 170 'name' => pht('Paused'), 152 171 'icon' => 'fa-minus-circle', 153 172 'color' => 'dark', 154 173 'color.ansi' => 'yellow', 174 + 'isBuilding' => false, 175 + 'isComplete' => false, 155 176 ), 156 177 self::STATUS_DEADLOCKED => array( 157 178 'name' => pht('Deadlocked'), 158 179 'icon' => 'fa-exclamation-circle', 159 180 'color' => 'red', 160 181 'color.ansi' => 'red', 182 + 'isBuilding' => false, 183 + 'isComplete' => true, 161 184 ), 162 185 ); 163 186 } 164 187 165 188 private static function getBuildStatusSpec($status) { 166 - return idx(self::getBuildStatusSpecMap(), $status, array()); 189 + $map = self::getBuildStatusSpecMap(); 190 + if (isset($map[$status])) { 191 + return $map[$status]; 192 + } 193 + 194 + return array( 195 + 'name' => pht('Unknown ("%s")', $status), 196 + 'icon' => 'fa-question-circle', 197 + 'color' => 'bluegrey', 198 + 'color.ansi' => 'magenta', 199 + 'isBuilding' => false, 200 + 'isComplete' => false, 201 + ); 167 202 } 168 203 169 204 }
+4
src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
··· 36 36 ->setHeader($title) 37 37 ->setUser($viewer) 38 38 ->setPolicyObject($buildable) 39 + ->setStatus( 40 + $buildable->getStatusIcon(), 41 + $buildable->getStatusColor(), 42 + $buildable->getStatusDisplayName()) 39 43 ->setHeaderIcon('fa-recycle'); 40 44 41 45 $timeline = $this->buildTransactionTimeline(
+2 -6
src/applications/harbormaster/engine/HarbormasterBuildEngine.php
··· 443 443 $all_pass = true; 444 444 $any_fail = false; 445 445 foreach ($buildable->getBuilds() as $build) { 446 - if ($build->getBuildStatus() != HarbormasterBuildStatus::STATUS_PASSED) { 446 + if (!$build->isPassed()) { 447 447 $all_pass = false; 448 448 } 449 - if (in_array($build->getBuildStatus(), array( 450 - HarbormasterBuildStatus::STATUS_FAILED, 451 - HarbormasterBuildStatus::STATUS_ERROR, 452 - HarbormasterBuildStatus::STATUS_DEADLOCKED, 453 - ))) { 454 449 450 + if ($build->isComplete() && !$build->isPassed()) { 455 451 $any_fail = true; 456 452 } 457 453 }
+12
src/applications/harbormaster/storage/HarbormasterBuildable.php
··· 58 58 } 59 59 } 60 60 61 + public function getStatusIcon() { 62 + return self::getBuildableStatusIcon($this->getBuildableStatus()); 63 + } 64 + 65 + public function getStatusDisplayName() { 66 + return self::getBuildableStatusName($this->getBuildableStatus()); 67 + } 68 + 69 + public function getStatusColor() { 70 + return self::getBuildableStatusColor($this->getBuildableStatus()); 71 + } 72 + 61 73 public static function initializeNewBuildable(PhabricatorUser $actor) { 62 74 return id(new HarbormasterBuildable()) 63 75 ->setIsManualBuildable(0)
+12 -7
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 108 108 } 109 109 110 110 public function isBuilding() { 111 - return 112 - $this->getBuildStatus() === HarbormasterBuildStatus::STATUS_PENDING || 113 - $this->getBuildStatus() === HarbormasterBuildStatus::STATUS_BUILDING; 111 + return $this->getBuildStatusObject()->isBuilding(); 114 112 } 115 113 116 114 public function isAutobuild() { ··· 173 171 } 174 172 175 173 public function isComplete() { 176 - return in_array( 177 - $this->getBuildStatus(), 178 - HarbormasterBuildStatus::getCompletedStatusConstants()); 174 + return $this->getBuildStatusObject()->isComplete(); 179 175 } 180 176 181 177 public function isPaused() { 182 - return ($this->getBuildStatus() == HarbormasterBuildStatus::STATUS_PAUSED); 178 + return $this->getBuildStatusObject()->isPaused(); 179 + } 180 + 181 + public function isPassed() { 182 + return $this->getBuildStatusObject()->isPassed(); 183 183 } 184 184 185 185 public function getURI() { 186 186 $id = $this->getID(); 187 187 return "/harbormaster/build/{$id}/"; 188 + } 189 + 190 + protected function getBuildStatusObject() { 191 + $status_key = $this->getBuildStatus(); 192 + return HarbormasterBuildStatus::newBuildStatusObject($status_key); 188 193 } 189 194 190 195