Page MenuHomePhabricator

D20252.diff
No OneTemporary

D20252.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1443,6 +1443,7 @@
'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php',
'HarbormasterQueryBuildsSearchEngineAttachment' => 'applications/harbormaster/engineextension/HarbormasterQueryBuildsSearchEngineAttachment.php',
'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php',
+ 'HarbormasterRestartException' => 'applications/harbormaster/exception/HarbormasterRestartException.php',
'HarbormasterRunBuildPlansHeraldAction' => 'applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php',
'HarbormasterSchemaSpec' => 'applications/harbormaster/storage/HarbormasterSchemaSpec.php',
'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php',
@@ -7093,6 +7094,7 @@
'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod',
'HarbormasterQueryBuildsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'HarbormasterRemarkupRule' => 'PhabricatorObjectRemarkupRule',
+ 'HarbormasterRestartException' => 'Exception',
'HarbormasterRunBuildPlansHeraldAction' => 'HeraldAction',
'HarbormasterSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'HarbormasterScratchTable' => 'HarbormasterDAO',
diff --git a/src/applications/harbormaster/constants/HarbormasterBuildStatus.php b/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
--- a/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
+++ b/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
@@ -52,6 +52,10 @@
return ($this->key === self::STATUS_PASSED);
}
+ public function isFailed() {
+ return ($this->key === self::STATUS_FAILED);
+ }
+
/**
* Get a human readable name for a build status constant.
diff --git a/src/applications/harbormaster/controller/HarbormasterBuildActionController.php b/src/applications/harbormaster/controller/HarbormasterBuildActionController.php
--- a/src/applications/harbormaster/controller/HarbormasterBuildActionController.php
+++ b/src/applications/harbormaster/controller/HarbormasterBuildActionController.php
@@ -64,19 +64,13 @@
'restart. Side effects of the build will occur again. Really '.
'restart build?');
$submit = pht('Restart Build');
- } else if (!$build->getBuildPlan()->canRestartBuildPlan()) {
- $title = pht('Not Restartable');
- $body = pht(
- 'The build plan for this build is not restartable, so you '.
- 'can not restart the build.');
} else {
- $title = pht('Unable to Restart Build');
- if ($build->isRestarting()) {
- $body = pht(
- 'This build is already restarting. You can not reissue a '.
- 'restart command to a restarting build.');
- } else {
- $body = pht('You can not restart this build.');
+ try {
+ $build->assertCanRestartBuild();
+ throw new Exception(pht('Expected to be unable to restart build.'));
+ } catch (HarbormasterRestartException $ex) {
+ $title = $ex->getTitle();
+ $body = $ex->getBody();
}
}
break;
diff --git a/src/applications/harbormaster/exception/HarbormasterRestartException.php b/src/applications/harbormaster/exception/HarbormasterRestartException.php
new file mode 100644
--- /dev/null
+++ b/src/applications/harbormaster/exception/HarbormasterRestartException.php
@@ -0,0 +1,33 @@
+<?php
+
+final class HarbormasterRestartException extends Exception {
+
+ private $title;
+ private $body = array();
+
+ public function __construct($title, $body = null) {
+ $this->setTitle($title);
+ $this->appendParagraph($body);
+
+ parent::__construct($title);
+ }
+
+ public function setTitle($title) {
+ $this->title = $title;
+ return $this;
+ }
+
+ public function getTitle() {
+ return $this->title;
+ }
+
+ public function appendParagraph($description) {
+ $this->body[] = $description;
+ return $this;
+ }
+
+ public function getBody() {
+ return $this->body;
+ }
+
+}
diff --git a/src/applications/harbormaster/plan/HarbormasterBuildPlanBehavior.php b/src/applications/harbormaster/plan/HarbormasterBuildPlanBehavior.php
--- a/src/applications/harbormaster/plan/HarbormasterBuildPlanBehavior.php
+++ b/src/applications/harbormaster/plan/HarbormasterBuildPlanBehavior.php
@@ -15,6 +15,7 @@
const BEHAVIOR_RESTARTABLE = 'restartable';
const RESTARTABLE_ALWAYS = 'always';
+ const RESTARTABLE_IF_FAILED = 'failed';
const RESTARTABLE_NEVER = 'never';
const BEHAVIOR_DRAFTS = 'hold-drafts';
@@ -251,6 +252,12 @@
->setIsDefault(true)
->setDescription(
pht('The build may be restarted.')),
+ id(new HarbormasterBuildPlanBehaviorOption())
+ ->setKey(self::RESTARTABLE_IF_FAILED)
+ ->setIcon('fa-times-circle-o yellow')
+ ->setName(pht('If Failed'))
+ ->setDescription(
+ pht('The build may be restarted if it has failed.')),
id(new HarbormasterBuildPlanBehaviorOption())
->setKey(self::RESTARTABLE_NEVER)
->setIcon('fa-times red')
diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
--- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php
+++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
@@ -183,6 +183,10 @@
return $this->getBuildStatusObject()->isPassed();
}
+ public function isFailed() {
+ return $this->getBuildStatusObject()->isFailed();
+ }
+
public function getURI() {
$id = $this->getID();
return "/harbormaster/build/{$id}/";
@@ -211,16 +215,60 @@
}
public function canRestartBuild() {
- if ($this->isAutobuild()) {
+ try {
+ $this->assertCanRestartBuild();
+ return true;
+ } catch (HarbormasterRestartException $ex) {
return false;
}
+ }
+
+ public function assertCanRestartBuild() {
+ if ($this->isAutobuild()) {
+ throw new HarbormasterRestartException(
+ pht('Can Not Restart Autobuild'),
+ pht(
+ 'This build can not be restarted because it is an automatic '.
+ 'build.'));
+ }
+ $restartable = HarbormasterBuildPlanBehavior::BEHAVIOR_RESTARTABLE;
$plan = $this->getBuildPlan();
- if (!$plan->canRestartBuildPlan()) {
- return false;
+
+ $option = HarbormasterBuildPlanBehavior::getBehavior($restartable)
+ ->getPlanOption($plan);
+ $option_key = $option->getKey();
+
+ $never_restartable = HarbormasterBuildPlanBehavior::RESTARTABLE_NEVER;
+ $is_never = ($option_key === $never_restartable);
+ if ($is_never) {
+ throw new HarbormasterRestartException(
+ pht('Build Plan Prevents Restart'),
+ pht(
+ 'This build can not be restarted because the build plan is '.
+ 'configured to prevent the build from restarting.'));
+ }
+
+ $failed_restartable = HarbormasterBuildPlanBehavior::RESTARTABLE_IF_FAILED;
+ $is_failed = ($option_key === $failed_restartable);
+ if ($is_failed) {
+ if (!$this->isFailed()) {
+ throw new HarbormasterRestartException(
+ pht('Only Restartable if Failed'),
+ pht(
+ 'This build can not be restarted because the build plan is '.
+ 'configured to prevent the build from restarting unless it '.
+ 'has failed, and it has not failed.'));
+ }
}
- return !$this->isRestarting();
+ if ($this->isRestarting()) {
+ throw new HarbormasterRestartException(
+ pht('Already Restarting'),
+ pht(
+ 'This build is already restarting. You can not reissue a restart '.
+ 'command to a restarting build.'));
+ }
}
public function canPauseBuild() {
diff --git a/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php b/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php
--- a/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php
+++ b/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php
@@ -175,16 +175,6 @@
$capability);
}
- public function canRestartBuildPlan() {
- $restartable = HarbormasterBuildPlanBehavior::BEHAVIOR_RESTARTABLE;
- $is_restartable = HarbormasterBuildPlanBehavior::RESTARTABLE_ALWAYS;
-
- $option = HarbormasterBuildPlanBehavior::getBehavior($restartable)
- ->getPlanOption($this);
-
- return ($option->getKey() === $is_restartable);
- }
-
/* -( PhabricatorSubscribableInterface )----------------------------------- */

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 24, 8:53 PM (4 h, 56 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7191552
Default Alt Text
D20252.diff (8 KB)

Event Timeline