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

[harbormaster/abort-builds] Support aborting builds in Harbormaster

Summary: Ref T1049. This adds support for aborting builds in Harbormaster.

Test Plan: Tested it in production.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: yelirekim, traviscline, joshuaspence, Korvin, epriestley

Projects: #harbormaster

Maniphest Tasks: T1049

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

authored by

June Rhodes and committed by
epriestley
d5dc4588 26552a58

+183 -68
+3 -2
src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
··· 65 65 'delete/(?:(?P<id>\d+)/)?' => 'HarbormasterStepDeleteController', 66 66 ), 67 67 'buildable/' => array( 68 - '(?P<id>\d+)/(?P<action>stop|resume|restart)/' 68 + '(?P<id>\d+)/(?P<action>pause|resume|restart|abort)/' 69 69 => 'HarbormasterBuildableActionController', 70 70 ), 71 71 'build/' => array( 72 72 '(?P<id>\d+)/' => 'HarbormasterBuildViewController', 73 - '(?P<action>stop|resume|restart)/(?P<id>\d+)/(?:(?P<via>[^/]+)/)?' 73 + '(?P<action>pause|resume|restart|abort)/'. 74 + '(?P<id>\d+)/(?:(?P<via>[^/]+)/)?' 74 75 => 'HarbormasterBuildActionController', 75 76 ), 76 77 'plan/' => array(
+22 -7
src/applications/harbormaster/controller/HarbormasterBuildActionController.php
··· 35 35 case HarbormasterBuildCommand::COMMAND_RESTART: 36 36 $can_issue = $build->canRestartBuild(); 37 37 break; 38 - case HarbormasterBuildCommand::COMMAND_STOP: 39 - $can_issue = $build->canStopBuild(); 38 + case HarbormasterBuildCommand::COMMAND_PAUSE: 39 + $can_issue = $build->canPauseBuild(); 40 40 break; 41 41 case HarbormasterBuildCommand::COMMAND_RESUME: 42 42 $can_issue = $build->canResumeBuild(); 43 + break; 44 + case HarbormasterBuildCommand::COMMAND_ABORT: 45 + $can_issue = $build->canAbortBuild(); 43 46 break; 44 47 default: 45 48 return new Aphront400Response(); ··· 90 93 } 91 94 } 92 95 break; 93 - case HarbormasterBuildCommand::COMMAND_STOP: 96 + case HarbormasterBuildCommand::COMMAND_ABORT: 97 + if ($can_issue) { 98 + $title = pht('Really abort build?'); 99 + $body = pht( 100 + 'Progress on this build will be discarded. Really '. 101 + 'abort build?'); 102 + $submit = pht('Abort Build'); 103 + } else { 104 + $title = pht('Unable to Abort Build'); 105 + $body = pht('You can not abort this build.'); 106 + } 107 + break; 108 + case HarbormasterBuildCommand::COMMAND_PAUSE: 94 109 if ($can_issue) { 95 110 $title = pht('Really pause build?'); 96 111 $body = pht( ··· 103 118 $body = pht( 104 119 'This build is already complete. You can not pause a completed '. 105 120 'build.'); 106 - } else if ($build->isStopped()) { 121 + } else if ($build->isPaused()) { 107 122 $body = pht( 108 123 'This build is already paused. You can not pause a build which '. 109 124 'has already been paused.'); 110 - } else if ($build->isStopping()) { 125 + } else if ($build->isPausing()) { 111 126 $body = pht( 112 127 'This build is already pausing. You can not reissue a pause '. 113 128 'command to a pausing build.'); ··· 129 144 $body = pht( 130 145 'This build is already resuming. You can not reissue a resume '. 131 146 'command to a resuming build.'); 132 - } else if (!$build->isStopped()) { 147 + } else if (!$build->isPaused()) { 133 148 $body = pht( 134 - 'This build is not stopped. You can only resume a stopped '. 149 + 'This build is not paused. You can only resume a paused '. 135 150 'build.'); 136 151 } 137 152 }
+16 -5
src/applications/harbormaster/controller/HarbormasterBuildViewController.php
··· 29 29 30 30 if ($build->isRestarting()) { 31 31 $header->setStatus('fa-exclamation-triangle', 'red', pht('Restarting')); 32 - } else if ($build->isStopping()) { 32 + } else if ($build->isPausing()) { 33 33 $header->setStatus('fa-exclamation-triangle', 'red', pht('Pausing')); 34 34 } else if ($build->isResuming()) { 35 35 $header->setStatus('fa-exclamation-triangle', 'red', pht('Resuming')); 36 + } else if ($build->isAborting()) { 37 + $header->setStatus('fa-exclamation-triangle', 'red', pht('Aborting')); 36 38 } 37 39 38 40 $box = id(new PHUIObjectBoxView()) ··· 447 449 ->setObjectURI("/build/{$id}"); 448 450 449 451 $can_restart = $build->canRestartBuild(); 450 - $can_stop = $build->canStopBuild(); 452 + $can_pause = $build->canPauseBuild(); 451 453 $can_resume = $build->canResumeBuild(); 454 + $can_abort = $build->canAbortBuild(); 452 455 453 456 $list->addAction( 454 457 id(new PhabricatorActionView()) ··· 471 474 id(new PhabricatorActionView()) 472 475 ->setName(pht('Pause Build')) 473 476 ->setIcon('fa-pause') 474 - ->setHref($this->getApplicationURI('/build/stop/'.$id.'/')) 475 - ->setDisabled(!$can_stop) 477 + ->setHref($this->getApplicationURI('/build/pause/'.$id.'/')) 478 + ->setDisabled(!$can_pause) 476 479 ->setWorkflow(true)); 477 480 } 481 + 482 + $list->addAction( 483 + id(new PhabricatorActionView()) 484 + ->setName(pht('Abort Build')) 485 + ->setIcon('fa-exclamation-triangle') 486 + ->setHref($this->getApplicationURI('/build/abort/'.$id.'/')) 487 + ->setDisabled(!$can_abort) 488 + ->setWorkflow(true)); 478 489 479 490 return $list; 480 491 } ··· 522 533 523 534 $item = new PHUIStatusItemView(); 524 535 525 - if ($build->isStopping()) { 536 + if ($build->isPausing()) { 526 537 $status_name = pht('Pausing'); 527 538 $icon = PHUIStatusItemView::ICON_RIGHT; 528 539 $color = 'dark';
+27 -10
src/applications/harbormaster/controller/HarbormasterBuildableActionController.php
··· 39 39 $issuable[] = $build; 40 40 } 41 41 break; 42 - case HarbormasterBuildCommand::COMMAND_STOP: 43 - if ($build->canStopBuild()) { 42 + case HarbormasterBuildCommand::COMMAND_PAUSE: 43 + if ($build->canPauseBuild()) { 44 44 $issuable[] = $build; 45 45 } 46 46 break; 47 47 case HarbormasterBuildCommand::COMMAND_RESUME: 48 48 if ($build->canResumeBuild()) { 49 + $issuable[] = $build; 50 + } 51 + break; 52 + case HarbormasterBuildCommand::COMMAND_ABORT: 53 + if ($build->canAbortBuild()) { 49 54 $issuable[] = $build; 50 55 } 51 56 break; ··· 94 99 'restart all builds?'); 95 100 $submit = pht('Restart All Builds'); 96 101 } else { 97 - $title = pht('Unable to Restart Build'); 102 + $title = pht('Unable to Restart Builds'); 98 103 $body = pht('No builds can be restarted.'); 99 104 } 100 105 break; 101 - case HarbormasterBuildCommand::COMMAND_STOP: 106 + case HarbormasterBuildCommand::COMMAND_PAUSE: 102 107 if ($issuable) { 103 - $title = pht('Really stop all builds?'); 108 + $title = pht('Really pause all builds?'); 104 109 $body = pht( 105 - 'If you stop all build, work will halt once the current steps '. 110 + 'If you pause all builds, work will halt once the current steps '. 106 111 'complete. You can resume the builds later.'); 107 - $submit = pht('Stop All Builds'); 112 + $submit = pht('Pause All Builds'); 108 113 } else { 109 - $title = pht('Unable to Stop Build'); 110 - $body = pht('No builds can be stopped.'); 114 + $title = pht('Unable to Pause Builds'); 115 + $body = pht('No builds can be paused.'); 116 + } 117 + break; 118 + case HarbormasterBuildCommand::COMMAND_ABORT: 119 + if ($issuable) { 120 + $title = pht('Really abort all builds?'); 121 + $body = pht( 122 + 'If you abort all builds, work will halt immediately. Work '. 123 + 'will be discarded, and builds must be completely restarted.'); 124 + $submit = pht('Abort All Builds'); 125 + } else { 126 + $title = pht('Unable to Abort Builds'); 127 + $body = pht('No builds can be aborted.'); 111 128 } 112 129 break; 113 130 case HarbormasterBuildCommand::COMMAND_RESUME: ··· 116 133 $body = pht('Work will continue on all builds. Really resume?'); 117 134 $submit = pht('Resume All Builds'); 118 135 } else { 119 - $title = pht('Unable to Resume Build'); 136 + $title = pht('Unable to Resume Builds'); 120 137 $body = pht('No builds can be resumed.'); 121 138 } 122 139 break;
+24 -10
src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
··· 84 84 85 85 $can_restart = false; 86 86 $can_resume = false; 87 - $can_stop = false; 87 + $can_pause = false; 88 + $can_abort = false; 88 89 89 90 foreach ($buildable->getBuilds() as $build) { 90 91 if ($build->canRestartBuild()) { ··· 93 94 if ($build->canResumeBuild()) { 94 95 $can_resume = true; 95 96 } 96 - if ($build->canStopBuild()) { 97 - $can_stop = true; 97 + if ($build->canPauseBuild()) { 98 + $can_pause = true; 99 + } 100 + if ($build->canAbortBuild()) { 101 + $can_abort = true; 98 102 } 99 103 } 100 104 101 105 $restart_uri = "buildable/{$id}/restart/"; 102 - $stop_uri = "buildable/{$id}/stop/"; 106 + $pause_uri = "buildable/{$id}/pause/"; 103 107 $resume_uri = "buildable/{$id}/resume/"; 108 + $abort_uri = "buildable/{$id}/abort/"; 104 109 105 110 $list->addAction( 106 111 id(new PhabricatorActionView()) ··· 114 119 id(new PhabricatorActionView()) 115 120 ->setIcon('fa-pause') 116 121 ->setName(pht('Pause All Builds')) 117 - ->setHref($this->getApplicationURI($stop_uri)) 122 + ->setHref($this->getApplicationURI($pause_uri)) 118 123 ->setWorkflow(true) 119 - ->setDisabled(!$can_stop || !$can_edit)); 124 + ->setDisabled(!$can_pause || !$can_edit)); 120 125 121 126 $list->addAction( 122 127 id(new PhabricatorActionView()) ··· 126 131 ->setWorkflow(true) 127 132 ->setDisabled(!$can_resume || !$can_edit)); 128 133 134 + $list->addAction( 135 + id(new PhabricatorActionView()) 136 + ->setIcon('fa-exclamation-triangle') 137 + ->setName(pht('Abort All Builds')) 138 + ->setHref($this->getApplicationURI($abort_uri)) 139 + ->setWorkflow(true) 140 + ->setDisabled(!$can_abort || !$can_edit)); 141 + 129 142 return $list; 130 143 } 131 144 ··· 181 194 182 195 if ($build->isRestarting()) { 183 196 $item->addIcon('fa-repeat', pht('Restarting')); 184 - } else if ($build->isStopping()) { 197 + } else if ($build->isPausing()) { 185 198 $item->addIcon('fa-pause', pht('Pausing')); 186 199 } else if ($build->isResuming()) { 187 200 $item->addIcon('fa-play', pht('Resuming')); ··· 191 204 192 205 $restart_uri = "build/restart/{$build_id}/buildable/"; 193 206 $resume_uri = "build/resume/{$build_id}/buildable/"; 194 - $stop_uri = "build/stop/{$build_id}/buildable/"; 207 + $pause_uri = "build/pause/{$build_id}/buildable/"; 208 + $abort_uri = "build/abort/{$build_id}/buildable/"; 195 209 196 210 $item->addAction( 197 211 id(new PHUIListItemView()) ··· 213 227 id(new PHUIListItemView()) 214 228 ->setIcon('fa-pause') 215 229 ->setName(pht('Pause')) 216 - ->setHref($this->getApplicationURI($stop_uri)) 230 + ->setHref($this->getApplicationURI($pause_uri)) 217 231 ->setWorkflow(true) 218 - ->setDisabled(!$build->canStopBuild())); 232 + ->setDisabled(!$build->canPauseBuild())); 219 233 } 220 234 221 235 $targets = $build->getBuildTargets();
+5 -2
src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php
··· 71 71 case HarbormasterBuildCommand::COMMAND_RESTART: 72 72 $issuable = $build->canRestartBuild(); 73 73 break; 74 - case HarbormasterBuildCommand::COMMAND_STOP: 75 - $issuable = $build->canStopBuild(); 74 + case HarbormasterBuildCommand::COMMAND_PAUSE: 75 + $issuable = $build->canPauseBuild(); 76 76 break; 77 77 case HarbormasterBuildCommand::COMMAND_RESUME: 78 78 $issuable = $build->canResumeBuild(); 79 + break; 80 + case HarbormasterBuildCommand::COMMAND_ABORT: 81 + $issuable = $build->canAbortBuild(); 79 82 break; 80 83 default: 81 84 throw new Exception(pht('Unknown command %s', $command));
+8 -2
src/applications/harbormaster/engine/HarbormasterBuildEngine.php
··· 98 98 } 99 99 100 100 private function updateBuild(HarbormasterBuild $build) { 101 + if ($build->isAborting()) { 102 + $this->releaseAllArtifacts($build); 103 + $build->setBuildStatus(HarbormasterBuild::STATUS_ABORTED); 104 + $build->save(); 105 + } 106 + 101 107 if (($build->getBuildStatus() == HarbormasterBuild::STATUS_PENDING) || 102 108 ($build->isRestarting())) { 103 109 $this->restartBuild($build); ··· 110 116 $build->save(); 111 117 } 112 118 113 - if ($build->isStopping() && !$build->isComplete()) { 114 - $build->setBuildStatus(HarbormasterBuild::STATUS_STOPPED); 119 + if ($build->isPausing() && !$build->isComplete()) { 120 + $build->setBuildStatus(HarbormasterBuild::STATUS_PAUSED); 115 121 $build->save(); 116 122 } 117 123
+2 -1
src/applications/harbormaster/storage/HarbormasterBuildCommand.php
··· 2 2 3 3 final class HarbormasterBuildCommand extends HarbormasterDAO { 4 4 5 - const COMMAND_STOP = 'stop'; 5 + const COMMAND_PAUSE = 'pause'; 6 6 const COMMAND_RESUME = 'resume'; 7 7 const COMMAND_RESTART = 'restart'; 8 + const COMMAND_ABORT = 'abort'; 8 9 9 10 protected $authorPHID; 10 11 protected $targetPHID;
+12 -5
src/applications/harbormaster/storage/HarbormasterBuildTransaction.php
··· 31 31 return pht( 32 32 '%s restarted this build.', 33 33 $this->renderHandleLink($author_phid)); 34 + case HarbormasterBuildCommand::COMMAND_ABORT: 35 + return pht( 36 + '%s aborted this build.', 37 + $this->renderHandleLink($author_phid)); 34 38 case HarbormasterBuildCommand::COMMAND_RESUME: 35 39 return pht( 36 40 '%s resumed this build.', 37 41 $this->renderHandleLink($author_phid)); 38 - case HarbormasterBuildCommand::COMMAND_STOP: 42 + case HarbormasterBuildCommand::COMMAND_PAUSE: 39 43 return pht( 40 - '%s stopped this build.', 44 + '%s paused this build.', 41 45 $this->renderHandleLink($author_phid)); 42 46 } 43 47 } ··· 59 63 return 'fa-backward'; 60 64 case HarbormasterBuildCommand::COMMAND_RESUME: 61 65 return 'fa-play'; 62 - case HarbormasterBuildCommand::COMMAND_STOP: 63 - return 'fa-stop'; 66 + case HarbormasterBuildCommand::COMMAND_PAUSE: 67 + return 'fa-pause'; 68 + case HarbormasterBuildCommand::COMMAND_ABORT: 69 + return 'fa-exclamation-triangle'; 64 70 } 65 71 } 66 72 ··· 78 84 return 'green'; 79 85 case self::TYPE_COMMAND: 80 86 switch ($new) { 81 - case HarbormasterBuildCommand::COMMAND_STOP: 87 + case HarbormasterBuildCommand::COMMAND_PAUSE: 88 + case HarbormasterBuildCommand::COMMAND_ABORT: 82 89 return 'red'; 83 90 } 84 91 }
+5 -5
src/applications/harbormaster/storage/HarbormasterBuildableTransaction.php
··· 35 35 return pht( 36 36 '%s resumed this buildable.', 37 37 $this->renderHandleLink($author_phid)); 38 - case HarbormasterBuildCommand::COMMAND_STOP: 38 + case HarbormasterBuildCommand::COMMAND_PAUSE: 39 39 return pht( 40 - '%s stopped this buildable.', 40 + '%s paused this buildable.', 41 41 $this->renderHandleLink($author_phid)); 42 42 } 43 43 } ··· 59 59 return 'fa-backward'; 60 60 case HarbormasterBuildCommand::COMMAND_RESUME: 61 61 return 'fa-play'; 62 - case HarbormasterBuildCommand::COMMAND_STOP: 63 - return 'fa-stop'; 62 + case HarbormasterBuildCommand::COMMAND_PAUSE: 63 + return 'fa-pause'; 64 64 } 65 65 } 66 66 ··· 78 78 return 'green'; 79 79 case self::TYPE_COMMAND: 80 80 switch ($new) { 81 - case HarbormasterBuildCommand::COMMAND_STOP: 81 + case HarbormasterBuildCommand::COMMAND_PAUSE: 82 82 return 'red'; 83 83 } 84 84 }
+58 -19
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 42 42 const STATUS_FAILED = 'failed'; 43 43 44 44 /** 45 + * The build has aborted. 46 + */ 47 + const STATUS_ABORTED = 'aborted'; 48 + 49 + /** 45 50 * The build encountered an unexpected error. 46 51 */ 47 52 const STATUS_ERROR = 'error'; 48 53 49 54 /** 50 - * The build has been stopped. 55 + * The build has been paused. 51 56 */ 52 - const STATUS_STOPPED = 'stopped'; 57 + const STATUS_PAUSED = 'paused'; 53 58 54 59 /** 55 60 * The build has been deadlocked. ··· 75 80 return pht('Passed'); 76 81 case self::STATUS_FAILED: 77 82 return pht('Failed'); 83 + case self::STATUS_ABORTED: 84 + return pht('Aborted'); 78 85 case self::STATUS_ERROR: 79 86 return pht('Unexpected Error'); 80 - case self::STATUS_STOPPED: 87 + case self::STATUS_PAUSED: 81 88 return pht('Paused'); 82 89 case self::STATUS_DEADLOCKED: 83 90 return pht('Deadlocked'); ··· 97 104 return PHUIStatusItemView::ICON_ACCEPT; 98 105 case self::STATUS_FAILED: 99 106 return PHUIStatusItemView::ICON_REJECT; 107 + case self::STATUS_ABORTED: 108 + return PHUIStatusItemView::ICON_MINUS; 100 109 case self::STATUS_ERROR: 101 110 return PHUIStatusItemView::ICON_MINUS; 102 - case self::STATUS_STOPPED: 111 + case self::STATUS_PAUSED: 103 112 return PHUIStatusItemView::ICON_MINUS; 104 113 case self::STATUS_DEADLOCKED: 105 114 return PHUIStatusItemView::ICON_WARNING; ··· 118 127 case self::STATUS_PASSED: 119 128 return 'green'; 120 129 case self::STATUS_FAILED: 130 + case self::STATUS_ABORTED: 121 131 case self::STATUS_ERROR: 122 132 case self::STATUS_DEADLOCKED: 123 133 return 'red'; 124 - case self::STATUS_STOPPED: 134 + case self::STATUS_PAUSED: 125 135 return 'dark'; 126 136 default: 127 137 return 'bluegrey'; ··· 284 294 switch ($this->getBuildStatus()) { 285 295 case self::STATUS_PASSED: 286 296 case self::STATUS_FAILED: 297 + case self::STATUS_ABORTED: 287 298 case self::STATUS_ERROR: 288 - case self::STATUS_STOPPED: 299 + case self::STATUS_PAUSED: 289 300 return true; 290 301 } 291 302 292 303 return false; 293 304 } 294 305 295 - public function isStopped() { 296 - return ($this->getBuildStatus() == self::STATUS_STOPPED); 306 + public function isPaused() { 307 + return ($this->getBuildStatus() == self::STATUS_PAUSED); 297 308 } 298 309 299 310 ··· 317 328 return !$this->isRestarting(); 318 329 } 319 330 320 - public function canStopBuild() { 331 + public function canPauseBuild() { 321 332 if ($this->isAutobuild()) { 322 333 return false; 323 334 } 324 335 325 336 return !$this->isComplete() && 326 - !$this->isStopped() && 327 - !$this->isStopping(); 337 + !$this->isPaused() && 338 + !$this->isPausing(); 339 + } 340 + 341 + public function canAbortBuild() { 342 + if ($this->isAutobuild()) { 343 + return false; 344 + } 345 + 346 + return !$this->isComplete(); 328 347 } 329 348 330 349 public function canResumeBuild() { ··· 332 351 return false; 333 352 } 334 353 335 - return $this->isStopped() && 354 + return $this->isPaused() && 336 355 !$this->isResuming(); 337 356 } 338 357 339 - public function isStopping() { 340 - $is_stopping = false; 358 + public function isPausing() { 359 + $is_pausing = false; 341 360 foreach ($this->getUnprocessedCommands() as $command_object) { 342 361 $command = $command_object->getCommand(); 343 362 switch ($command) { 344 - case HarbormasterBuildCommand::COMMAND_STOP: 345 - $is_stopping = true; 363 + case HarbormasterBuildCommand::COMMAND_PAUSE: 364 + $is_pausing = true; 346 365 break; 347 366 case HarbormasterBuildCommand::COMMAND_RESUME: 348 367 case HarbormasterBuildCommand::COMMAND_RESTART: 349 - $is_stopping = false; 368 + $is_pausing = false; 369 + break; 370 + case HarbormasterBuildCommand::COMMAND_ABORT: 371 + $is_pausing = true; 350 372 break; 351 373 } 352 374 } 353 375 354 - return $is_stopping; 376 + return $is_pausing; 355 377 } 356 378 357 379 public function isResuming() { ··· 363 385 case HarbormasterBuildCommand::COMMAND_RESUME: 364 386 $is_resuming = true; 365 387 break; 366 - case HarbormasterBuildCommand::COMMAND_STOP: 388 + case HarbormasterBuildCommand::COMMAND_PAUSE: 389 + $is_resuming = false; 390 + break; 391 + case HarbormasterBuildCommand::COMMAND_ABORT: 367 392 $is_resuming = false; 368 393 break; 369 394 } ··· 384 409 } 385 410 386 411 return $is_restarting; 412 + } 413 + 414 + public function isAborting() { 415 + $is_aborting = false; 416 + foreach ($this->getUnprocessedCommands() as $command_object) { 417 + $command = $command_object->getCommand(); 418 + switch ($command) { 419 + case HarbormasterBuildCommand::COMMAND_ABORT: 420 + $is_aborting = true; 421 + break; 422 + } 423 + } 424 + 425 + return $is_aborting; 387 426 } 388 427 389 428 public function deleteUnprocessedCommands() {
+1
src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php
··· 268 268 public function isFailed() { 269 269 switch ($this->getTargetStatus()) { 270 270 case self::STATUS_FAILED: 271 + case self::STATUS_ABORTED: 271 272 return true; 272 273 } 273 274