Index: src/applications/harbormaster/application/PhabricatorApplicationHarbormaster.php =================================================================== --- src/applications/harbormaster/application/PhabricatorApplicationHarbormaster.php +++ src/applications/harbormaster/application/PhabricatorApplicationHarbormaster.php @@ -55,7 +55,7 @@ ), 'build/' => array( '(?:(?P\d+)/)?' => 'HarbormasterBuildViewController', - '(?Pstop|resume|restart)/(?:(?P\d+)/)?' + '(?Pstop|resume|restart)/(?P\d+)/(?:(?P[^/]+)/)?' => 'HarbormasterBuildActionController', ), 'plan/' => array( Index: src/applications/harbormaster/controller/HarbormasterBuildActionController.php =================================================================== --- src/applications/harbormaster/controller/HarbormasterBuildActionController.php +++ src/applications/harbormaster/controller/HarbormasterBuildActionController.php @@ -5,10 +5,12 @@ private $id; private $action; + private $via; public function willProcessRequest(array $data) { $this->id = $data['id']; $this->action = $data['action']; + $this->via = idx($data, 'via'); } public function processRequest() { @@ -38,7 +40,14 @@ return new Aphront400Response(); } - $build_uri = $this->getApplicationURI('/build/'.$build->getID().'/'); + switch ($this->via) { + case 'buildable': + $return_uri = $build->getBuildable()->getMonogram(); + break; + default: + $return_uri = $this->getApplicationURI('/build/'.$build->getID().'/'); + break; + } if ($request->isDialogFormPost() && $can_issue) { @@ -58,7 +67,7 @@ 'buildID' => $build->getID() )); - return id(new AphrontRedirectResponse())->setURI($build_uri); + return id(new AphrontRedirectResponse())->setURI($return_uri); } switch ($command) { @@ -134,7 +143,7 @@ ->setUser($viewer) ->setTitle($title) ->appendChild($body) - ->addCancelButton($build_uri); + ->addCancelButton($return_uri); if ($can_issue) { $dialog->addSubmitButton($submit); Index: src/applications/harbormaster/controller/HarbormasterBuildViewController.php =================================================================== --- src/applications/harbormaster/controller/HarbormasterBuildViewController.php +++ src/applications/harbormaster/controller/HarbormasterBuildViewController.php @@ -30,6 +30,14 @@ ->setUser($viewer) ->setPolicyObject($build); + if ($build->isRestarting()) { + $header->setStatus('warning', 'red', pht('Restarting')); + } else if ($build->isStopping()) { + $header->setStatus('warning', 'red', pht('Stopping')); + } else if ($build->isResuming()) { + $header->setStatus('warning', 'red', pht('Resuming')); + } + $box = id(new PHUIObjectBoxView()) ->setHeader($header); @@ -37,6 +45,9 @@ $this->buildPropertyLists($box, $build, $actions); $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb( + $build->getBuildable()->getMonogram(), + '/'.$build->getBuildable()->getMonogram()); $crumbs->addTextCrumb($title); $build_targets = id(new HarbormasterBuildTargetQuery()) Index: src/applications/harbormaster/controller/HarbormasterBuildableViewController.php =================================================================== --- src/applications/harbormaster/controller/HarbormasterBuildableViewController.php +++ src/applications/harbormaster/controller/HarbormasterBuildableViewController.php @@ -38,45 +38,81 @@ ->setObjectName(pht('Build %d', $build->getID())) ->setHeader($build->getName()) ->setHref($view_uri); - if ($build->isStopping()) { - $item->setBarColor('black'); - $item->addAttribute(pht('Stopping')); + + switch ($build->getBuildStatus()) { + case HarbormasterBuild::STATUS_INACTIVE: + $item->setBarColor('grey'); + $item->addAttribute(pht('Inactive')); + break; + case HarbormasterBuild::STATUS_PENDING: + $item->setBarColor('blue'); + $item->addAttribute(pht('Pending')); + break; + case HarbormasterBuild::STATUS_WAITING: + $item->setBarColor('violet'); + $item->addAttribute(pht('Waiting')); + break; + case HarbormasterBuild::STATUS_BUILDING: + $item->setBarColor('yellow'); + $item->addAttribute(pht('Building')); + break; + case HarbormasterBuild::STATUS_PASSED: + $item->setBarColor('green'); + $item->addAttribute(pht('Passed')); + break; + case HarbormasterBuild::STATUS_FAILED: + $item->setBarColor('red'); + $item->addAttribute(pht('Failed')); + break; + case HarbormasterBuild::STATUS_ERROR: + $item->setBarColor('red'); + $item->addAttribute(pht('Unexpected Error')); + break; + case HarbormasterBuild::STATUS_STOPPED: + $item->setBarColor('black'); + $item->addAttribute(pht('Stopped')); + break; + } + + if ($build->isRestarting()) { + $item->addIcon('backward', pht('Restarting')); + } else if ($build->isStopping()) { + $item->addIcon('stop', pht('Stopping')); + } else if ($build->isResuming()) { + $item->addIcon('play', pht('Resuming')); + } + + $build_id = $build->getID(); + + $restart_uri = "build/restart/{$build_id}/buildable/"; + $resume_uri = "build/resume/{$build_id}/buildable/"; + $stop_uri = "build/stop/{$build_id}/buildable/"; + + $item->addAction( + id(new PHUIListItemView()) + ->setIcon('backward') + ->setName(pht('Restart')) + ->setHref($this->getApplicationURI($restart_uri)) + ->setWorkflow(true) + ->setDisabled(!$build->canRestartBuild())); + + if ($build->canResumeBuild()) { + $item->addAction( + id(new PHUIListItemView()) + ->setIcon('play') + ->setName(pht('Resume')) + ->setHref($this->getApplicationURI($resume_uri)) + ->setWorkflow(true)); } else { - switch ($build->getBuildStatus()) { - case HarbormasterBuild::STATUS_INACTIVE: - $item->setBarColor('grey'); - $item->addAttribute(pht('Inactive')); - break; - case HarbormasterBuild::STATUS_PENDING: - $item->setBarColor('blue'); - $item->addAttribute(pht('Pending')); - break; - case HarbormasterBuild::STATUS_WAITING: - $item->setBarColor('violet'); - $item->addAttribute(pht('Waiting')); - break; - case HarbormasterBuild::STATUS_BUILDING: - $item->setBarColor('yellow'); - $item->addAttribute(pht('Building')); - break; - case HarbormasterBuild::STATUS_PASSED: - $item->setBarColor('green'); - $item->addAttribute(pht('Passed')); - break; - case HarbormasterBuild::STATUS_FAILED: - $item->setBarColor('red'); - $item->addAttribute(pht('Failed')); - break; - case HarbormasterBuild::STATUS_ERROR: - $item->setBarColor('red'); - $item->addAttribute(pht('Unexpected Error')); - break; - case HarbormasterBuild::STATUS_STOPPED: - $item->setBarColor('black'); - $item->addAttribute(pht('Stopped')); - break; - } + $item->addAction( + id(new PHUIListItemView()) + ->setIcon('stop') + ->setName(pht('Stop')) + ->setHref($this->getApplicationURI($stop_uri)) + ->setWorkflow(true) + ->setDisabled(!$build->canStopBuild())); } + $build_list->addItem($item); } Index: src/applications/harbormaster/storage/HarbormasterBuildable.php =================================================================== --- src/applications/harbormaster/storage/HarbormasterBuildable.php +++ src/applications/harbormaster/storage/HarbormasterBuildable.php @@ -26,6 +26,10 @@ ->setBuildableStatus(self::STATUS_WHATEVER); } + public function getMonogram() { + return 'B'.$this->getID(); + } + /** * Returns an existing buildable for the object's PHID or creates a * new buildable implicitly if needed.