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

Allow entire buildables to restart/stop/resume

Summary: Ref T1049. Creates convenience actions at the Buildable level to stop, resume, or restart all builds.

Test Plan:

- Stopped all builds.
- Resumed all builds.
- Restarted all builds.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1049

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

+195 -13
+2
src/__phutil_library_map__.php
··· 728 728 'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php', 729 729 'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php', 730 730 'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php', 731 + 'HarbormasterBuildableActionController' => 'applications/harbormaster/controller/HarbormasterBuildableActionController.php', 731 732 'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php', 732 733 'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php', 733 734 'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php', ··· 3206 3207 1 => 'PhabricatorPolicyInterface', 3207 3208 2 => 'HarbormasterBuildableInterface', 3208 3209 ), 3210 + 'HarbormasterBuildableActionController' => 'HarbormasterController', 3209 3211 'HarbormasterBuildableListController' => 3210 3212 array( 3211 3213 0 => 'HarbormasterController',
+4
src/applications/harbormaster/application/PhabricatorApplicationHarbormaster.php
··· 53 53 'edit/(?:(?P<id>\d+)/)?' => 'HarbormasterStepEditController', 54 54 'delete/(?:(?P<id>\d+)/)?' => 'HarbormasterStepDeleteController', 55 55 ), 56 + 'buildable/' => array( 57 + '(?P<id>\d+)/(?P<action>stop|resume|restart)/' 58 + => 'HarbormasterBuildableActionController', 59 + ), 56 60 'build/' => array( 57 61 '(?:(?P<id>\d+)/)?' => 'HarbormasterBuildViewController', 58 62 '(?P<action>stop|resume|restart)/(?P<id>\d+)/(?:(?P<via>[^/]+)/)?'
+6 -1
src/applications/harbormaster/controller/HarbormasterBuildActionController.php
··· 21 21 $build = id(new HarbormasterBuildQuery()) 22 22 ->setViewer($viewer) 23 23 ->withIDs(array($this->id)) 24 + ->requireCapabilities( 25 + array( 26 + PhabricatorPolicyCapability::CAN_VIEW, 27 + PhabricatorPolicyCapability::CAN_EDIT, 28 + )) 24 29 ->executeOne(); 25 30 if (!$build) { 26 31 return new Aphront404Response(); ··· 42 47 43 48 switch ($this->via) { 44 49 case 'buildable': 45 - $return_uri = $build->getBuildable()->getMonogram(); 50 + $return_uri = '/'.$build->getBuildable()->getMonogram(); 46 51 break; 47 52 default: 48 53 $return_uri = $this->getApplicationURI('/build/'.$build->getID().'/');
+127
src/applications/harbormaster/controller/HarbormasterBuildableActionController.php
··· 1 + <?php 2 + 3 + final class HarbormasterBuildableActionController 4 + extends HarbormasterController { 5 + 6 + private $id; 7 + private $action; 8 + 9 + public function willProcessRequest(array $data) { 10 + $this->id = $data['id']; 11 + $this->action = $data['action']; 12 + } 13 + 14 + public function processRequest() { 15 + $request = $this->getRequest(); 16 + $viewer = $request->getUser(); 17 + $command = $this->action; 18 + 19 + $buildable = id(new HarbormasterBuildableQuery()) 20 + ->setViewer($viewer) 21 + ->withIDs(array($this->id)) 22 + ->needBuilds(true) 23 + ->requireCapabilities( 24 + array( 25 + PhabricatorPolicyCapability::CAN_VIEW, 26 + PhabricatorPolicyCapability::CAN_EDIT, 27 + )) 28 + ->executeOne(); 29 + if (!$buildable) { 30 + return new Aphront404Response(); 31 + } 32 + 33 + $issuable = array(); 34 + 35 + foreach ($buildable->getBuilds() as $build) { 36 + switch ($command) { 37 + case HarbormasterBuildCommand::COMMAND_RESTART: 38 + if ($build->canRestartBuild()) { 39 + $issuable[] = $build; 40 + } 41 + break; 42 + case HarbormasterBuildCommand::COMMAND_STOP: 43 + if ($build->canStopBuild()) { 44 + $issuable[] = $build; 45 + } 46 + break; 47 + case HarbormasterBuildCommand::COMMAND_RESUME: 48 + if ($build->canResumeBuild()) { 49 + $issuable[] = $build; 50 + } 51 + break; 52 + default: 53 + return new Aphront400Response(); 54 + } 55 + } 56 + 57 + $return_uri = $buildable->getMonogram(); 58 + if ($request->isDialogFormPost() && $issuable) { 59 + foreach ($issuable as $build) { 60 + id(new HarbormasterBuildCommand()) 61 + ->setAuthorPHID($viewer->getPHID()) 62 + ->setTargetPHID($build->getPHID()) 63 + ->setCommand($command) 64 + ->save(); 65 + 66 + PhabricatorWorker::scheduleTask( 67 + 'HarbormasterBuildWorker', 68 + array( 69 + 'buildID' => $build->getID() 70 + )); 71 + } 72 + 73 + return id(new AphrontRedirectResponse())->setURI($return_uri); 74 + } 75 + 76 + switch ($command) { 77 + case HarbormasterBuildCommand::COMMAND_RESTART: 78 + if ($issuable) { 79 + $title = pht('Really restart all builds?'); 80 + $body = pht( 81 + 'Progress on all builds will be discarded, and all builds will '. 82 + 'restart. Side effects of the builds will occur again. Really '. 83 + 'restart all builds?'); 84 + $submit = pht('Restart All Builds'); 85 + } else { 86 + $title = pht('Unable to Restart Build'); 87 + $body = pht('No builds can be restarted.'); 88 + } 89 + break; 90 + case HarbormasterBuildCommand::COMMAND_STOP: 91 + if ($issuable) { 92 + $title = pht('Really stop all builds?'); 93 + $body = pht( 94 + 'If you stop all build, work will halt once the current steps '. 95 + 'complete. You can resume the builds later.'); 96 + $submit = pht('Stop All Builds'); 97 + } else { 98 + $title = pht('Unable to Stop Build'); 99 + $body = pht('No builds can be stopped.'); 100 + } 101 + break; 102 + case HarbormasterBuildCommand::COMMAND_RESUME: 103 + if ($issuable) { 104 + $title = pht('Really resume all builds?'); 105 + $body = pht('Work will continue on all builds. Really resume?'); 106 + $submit = pht('Resume All Builds'); 107 + } else { 108 + $title = pht('Unable to Resume Build'); 109 + $body = pht('No builds can be resumed.'); 110 + } 111 + break; 112 + } 113 + 114 + $dialog = id(new AphrontDialogView()) 115 + ->setUser($viewer) 116 + ->setTitle($title) 117 + ->appendChild($body) 118 + ->addCancelButton($return_uri); 119 + 120 + if ($issuable) { 121 + $dialog->addSubmitButton($submit); 122 + } 123 + 124 + return id(new AphrontDialogResponse())->setDialog($dialog); 125 + } 126 + 127 + }
+52 -7
src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
··· 20 20 ->withIDs(array($id)) 21 21 ->needBuildableHandles(true) 22 22 ->needContainerHandles(true) 23 + ->needBuilds(true) 23 24 ->executeOne(); 24 25 if (!$buildable) { 25 26 return new Aphront404Response(); 26 27 } 27 28 28 - $builds = id(new HarbormasterBuildQuery()) 29 - ->setViewer($viewer) 30 - ->withBuildablePHIDs(array($buildable->getPHID())) 31 - ->execute(); 32 - 33 29 $build_list = id(new PHUIObjectItemListView()) 34 30 ->setUser($viewer); 35 - foreach ($builds as $build) { 31 + foreach ($buildable->getBuilds() as $build) { 36 32 $view_uri = $this->getApplicationURI('/build/'.$build->getID().'/'); 37 33 $item = id(new PHUIObjectItemView()) 38 34 ->setObjectName(pht('Build %d', $build->getID())) ··· 152 148 $list = id(new PhabricatorActionListView()) 153 149 ->setUser($viewer) 154 150 ->setObject($buildable) 155 - ->setObjectURI("/B{$id}"); 151 + ->setObjectURI($buildable->getMonogram()); 152 + 153 + $can_edit = PhabricatorPolicyFilter::hasCapability( 154 + $viewer, 155 + $buildable, 156 + PhabricatorPolicyCapability::CAN_EDIT); 157 + 158 + $can_restart = false; 159 + $can_resume = false; 160 + $can_stop = false; 161 + 162 + foreach ($buildable->getBuilds() as $build) { 163 + if ($build->canRestartBuild()) { 164 + $can_restart = true; 165 + } 166 + if ($build->canResumeBuild()) { 167 + $can_resume = true; 168 + } 169 + if ($build->canStopBuild()) { 170 + $can_stop = true; 171 + } 172 + } 173 + 174 + $restart_uri = "buildable/{$id}/restart/"; 175 + $stop_uri = "buildable/{$id}/stop/"; 176 + $resume_uri = "buildable/{$id}/resume/"; 177 + 178 + $list->addAction( 179 + id(new PhabricatorActionView()) 180 + ->setIcon('backward') 181 + ->setName(pht('Restart All Builds')) 182 + ->setHref($this->getApplicationURI($restart_uri)) 183 + ->setWorkflow(true) 184 + ->setDisabled(!$can_restart || !$can_edit)); 185 + 186 + $list->addAction( 187 + id(new PhabricatorActionView()) 188 + ->setIcon('stop') 189 + ->setName(pht('Stop All Builds')) 190 + ->setHref($this->getApplicationURI($stop_uri)) 191 + ->setWorkflow(true) 192 + ->setDisabled(!$can_stop || !$can_edit)); 193 + 194 + $list->addAction( 195 + id(new PhabricatorActionView()) 196 + ->setIcon('play') 197 + ->setName(pht('Resume All Builds')) 198 + ->setHref($this->getApplicationURI($resume_uri)) 199 + ->setWorkflow(true) 200 + ->setDisabled(!$can_resume || !$can_edit)); 156 201 157 202 return $list; 158 203 }
+2 -3
src/applications/harbormaster/storage/HarbormasterBuildable.php
··· 177 177 public function getCapabilities() { 178 178 return array( 179 179 PhabricatorPolicyCapability::CAN_VIEW, 180 + PhabricatorPolicyCapability::CAN_EDIT, 180 181 ); 181 182 } 182 183 ··· 191 192 } 192 193 193 194 public function describeAutomaticCapability($capability) { 194 - return pht( 195 - 'Users must be able to see the revision or repository to see a '. 196 - 'buildable.'); 195 + return pht('A buildable inherits policies from the underlying object.'); 197 196 } 198 197 199 198
+2 -2
src/applications/harbormaster/storage/build/HarbormasterBuild.php
··· 311 311 public function getCapabilities() { 312 312 return array( 313 313 PhabricatorPolicyCapability::CAN_VIEW, 314 + PhabricatorPolicyCapability::CAN_EDIT, 314 315 ); 315 316 } 316 317 ··· 325 326 } 326 327 327 328 public function describeAutomaticCapability($capability) { 328 - return pht( 329 - 'Users must be able to see a buildable to view its build plans.'); 329 + return pht('A build inherits policies from its buildable.'); 330 330 } 331 331 332 332 }