Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php b/src/applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php
index a76f53a362..c4622a902c 100644
--- a/src/applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php
+++ b/src/applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php
@@ -1,76 +1,86 @@
<?php
final class HarbormasterQueryBuildsConduitAPIMethod
extends HarbormasterConduitAPIMethod {
public function getAPIMethodName() {
return 'harbormaster.querybuilds';
}
public function getMethodDescription() {
return pht('Query Harbormaster builds.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_DEPRECATED;
}
public function getMethodStatusDescription() {
return pht('Use %s instead.', 'harbormaster.build.search');
}
protected function defineParamTypes() {
return array(
'ids' => 'optional list<id>',
'phids' => 'optional list<phid>',
'buildStatuses' => 'optional list<string>',
'buildablePHIDs' => 'optional list<phid>',
'buildPlanPHIDs' => 'optional list<phid>',
) + self::getPagerParamTypes();
}
protected function defineReturnType() {
return 'wild';
}
protected function execute(ConduitAPIRequest $request) {
$viewer = $request->getUser();
$call = new ConduitCall(
'harbormaster.build.search',
array_filter(array(
'constraints' => array_filter(array(
'ids' => $request->getValue('ids'),
'phids' => $request->getValue('phids'),
'statuses' => $request->getValue('buildStatuses'),
'buildables' => $request->getValue('buildablePHIDs'),
'plans' => $request->getValue('buildPlanPHIDs'),
)),
'attachments' => array(
'querybuilds' => true,
),
'limit' => $request->getValue('limit'),
'before' => $request->getValue('before'),
'after' => $request->getValue('after'),
)));
$subsumption = $call->setUser($viewer)
->execute();
$data = array();
foreach ($subsumption['data'] as $build_data) {
$querybuilds = idxv(
$build_data,
array('attachments', 'querybuilds'),
array());
$fields = idx($build_data, 'fields', array());
unset($build_data['fields']);
unset($build_data['attachments']);
+
+ // To retain backward compatibility, remove newer keys from the
+ // result array.
+ $fields['buildStatus'] = array_select_keys(
+ $fields['buildStatus'],
+ array(
+ 'value',
+ 'name',
+ ));
+
$data[] = array_mergev(array($build_data, $querybuilds, $fields));
}
$subsumption['data'] = $data;
return $subsumption;
}
}
diff --git a/src/applications/harbormaster/constants/HarbormasterBuildStatus.php b/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
index a2cdba5b63..b0e3105d78 100644
--- a/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
+++ b/src/applications/harbormaster/constants/HarbormasterBuildStatus.php
@@ -1,145 +1,169 @@
<?php
final class HarbormasterBuildStatus extends Phobject {
/**
* Not currently being built.
*/
const STATUS_INACTIVE = 'inactive';
/**
* Pending pick up by the Harbormaster daemon.
*/
const STATUS_PENDING = 'pending';
/**
* Current building the buildable.
*/
const STATUS_BUILDING = 'building';
/**
* The build has passed.
*/
const STATUS_PASSED = 'passed';
/**
* The build has failed.
*/
const STATUS_FAILED = 'failed';
/**
* The build has aborted.
*/
const STATUS_ABORTED = 'aborted';
/**
* The build encountered an unexpected error.
*/
const STATUS_ERROR = 'error';
/**
* The build has been paused.
*/
const STATUS_PAUSED = 'paused';
/**
* The build has been deadlocked.
*/
const STATUS_DEADLOCKED = 'deadlocked';
/**
* Get a human readable name for a build status constant.
*
* @param const Build status constant.
* @return string Human-readable name.
*/
public static function getBuildStatusName($status) {
- $map = self::getBuildStatusMap();
- return idx($map, $status, pht('Unknown ("%s")', $status));
+ $spec = self::getBuildStatusSpec($status);
+ return idx($spec, 'name', pht('Unknown ("%s")', $status));
}
public static function getBuildStatusMap() {
- return array(
- self::STATUS_INACTIVE => pht('Inactive'),
- self::STATUS_PENDING => pht('Pending'),
- self::STATUS_BUILDING => pht('Building'),
- self::STATUS_PASSED => pht('Passed'),
- self::STATUS_FAILED => pht('Failed'),
- self::STATUS_ABORTED => pht('Aborted'),
- self::STATUS_ERROR => pht('Unexpected Error'),
- self::STATUS_PAUSED => pht('Paused'),
- self::STATUS_DEADLOCKED => pht('Deadlocked'),
- );
+ $specs = self::getBuildStatusSpecMap();
+ return ipull($specs, 'name');
}
public static function getBuildStatusIcon($status) {
- switch ($status) {
- case self::STATUS_INACTIVE:
- case self::STATUS_PENDING:
- return PHUIStatusItemView::ICON_OPEN;
- case self::STATUS_BUILDING:
- return PHUIStatusItemView::ICON_RIGHT;
- case self::STATUS_PASSED:
- return PHUIStatusItemView::ICON_ACCEPT;
- case self::STATUS_FAILED:
- return PHUIStatusItemView::ICON_REJECT;
- case self::STATUS_ABORTED:
- return PHUIStatusItemView::ICON_MINUS;
- case self::STATUS_ERROR:
- return PHUIStatusItemView::ICON_MINUS;
- case self::STATUS_PAUSED:
- return PHUIStatusItemView::ICON_MINUS;
- case self::STATUS_DEADLOCKED:
- return PHUIStatusItemView::ICON_WARNING;
- default:
- return PHUIStatusItemView::ICON_QUESTION;
- }
+ $spec = self::getBuildStatusSpec($status);
+ return idx($spec, 'icon', 'fa-question-circle');
}
public static function getBuildStatusColor($status) {
- switch ($status) {
- case self::STATUS_INACTIVE:
- return 'dark';
- case self::STATUS_PENDING:
- case self::STATUS_BUILDING:
- return 'blue';
- case self::STATUS_PASSED:
- return 'green';
- case self::STATUS_FAILED:
- case self::STATUS_ABORTED:
- case self::STATUS_ERROR:
- case self::STATUS_DEADLOCKED:
- return 'red';
- case self::STATUS_PAUSED:
- return 'dark';
- default:
- return 'bluegrey';
- }
+ $spec = self::getBuildStatusSpec($status);
+ return idx($spec, 'color', 'bluegrey');
+ }
+
+ public static function getBuildStatusANSIColor($status) {
+ $spec = self::getBuildStatusSpec($status);
+ return idx($spec, 'color.ansi', 'magenta');
}
public static function getWaitingStatusConstants() {
return array(
self::STATUS_INACTIVE,
self::STATUS_PENDING,
);
}
public static function getActiveStatusConstants() {
return array(
self::STATUS_BUILDING,
self::STATUS_PAUSED,
);
}
public static function getCompletedStatusConstants() {
return array(
self::STATUS_PASSED,
self::STATUS_FAILED,
self::STATUS_ABORTED,
self::STATUS_ERROR,
self::STATUS_DEADLOCKED,
);
}
+ private static function getBuildStatusSpecMap() {
+ return array(
+ self::STATUS_INACTIVE => array(
+ 'name' => pht('Inactive'),
+ 'icon' => 'fa-circle-o',
+ 'color' => 'dark',
+ 'color.ansi' => 'yellow',
+ ),
+ self::STATUS_PENDING => array(
+ 'name' => pht('Pending'),
+ 'icon' => 'fa-circle-o',
+ 'color' => 'blue',
+ 'color.ansi' => 'yellow',
+ ),
+ self::STATUS_BUILDING => array(
+ 'name' => pht('Building'),
+ 'icon' => 'fa-chevron-circle-right',
+ 'color' => 'blue',
+ 'color.ansi' => 'yellow',
+ ),
+ self::STATUS_PASSED => array(
+ 'name' => pht('Passed'),
+ 'icon' => 'fa-check-circle',
+ 'color' => 'green',
+ 'color.ansi' => 'green',
+ ),
+ self::STATUS_FAILED => array(
+ 'name' => pht('Failed'),
+ 'icon' => 'fa-times-circle',
+ 'color' => 'red',
+ 'color.ansi' => 'red',
+ ),
+ self::STATUS_ABORTED => array(
+ 'name' => pht('Aborted'),
+ 'icon' => 'fa-minus-circle',
+ 'color' => 'red',
+ 'color.ansi' => 'red',
+ ),
+ self::STATUS_ERROR => array(
+ 'name' => pht('Unexpected Error'),
+ 'icon' => 'fa-minus-circle',
+ 'color' => 'red',
+ 'color.ansi' => 'red',
+ ),
+ self::STATUS_PAUSED => array(
+ 'name' => pht('Paused'),
+ 'icon' => 'fa-minus-circle',
+ 'color' => 'dark',
+ 'color.ansi' => 'yellow',
+ ),
+ self::STATUS_DEADLOCKED => array(
+ 'name' => pht('Deadlocked'),
+ 'icon' => 'fa-exclamation-circle',
+ 'color' => 'red',
+ 'color.ansi' => 'red',
+ ),
+ );
+ }
+
+ private static function getBuildStatusSpec($status) {
+ return idx(self::getBuildStatusSpecMap(), $status, array());
+ }
+
}
diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
index 958eaa1f2b..92d4293913 100644
--- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php
+++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
@@ -1,451 +1,453 @@
<?php
final class HarbormasterBuild extends HarbormasterDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorConduitResultInterface {
protected $buildablePHID;
protected $buildPlanPHID;
protected $buildStatus;
protected $buildGeneration;
protected $buildParameters = array();
protected $initiatorPHID;
protected $planAutoKey;
private $buildable = self::ATTACHABLE;
private $buildPlan = self::ATTACHABLE;
private $buildTargets = self::ATTACHABLE;
private $unprocessedCommands = self::ATTACHABLE;
public static function initializeNewBuild(PhabricatorUser $actor) {
return id(new HarbormasterBuild())
->setBuildStatus(HarbormasterBuildStatus::STATUS_INACTIVE)
->setBuildGeneration(0);
}
public function delete() {
$this->openTransaction();
$this->deleteUnprocessedCommands();
$result = parent::delete();
$this->saveTransaction();
return $result;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'buildParameters' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'buildStatus' => 'text32',
'buildGeneration' => 'uint32',
'planAutoKey' => 'text32?',
'initiatorPHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_buildable' => array(
'columns' => array('buildablePHID'),
),
'key_plan' => array(
'columns' => array('buildPlanPHID'),
),
'key_status' => array(
'columns' => array('buildStatus'),
),
'key_planautokey' => array(
'columns' => array('buildablePHID', 'planAutoKey'),
'unique' => true,
),
'key_initiator' => array(
'columns' => array('initiatorPHID'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
HarbormasterBuildPHIDType::TYPECONST);
}
public function attachBuildable(HarbormasterBuildable $buildable) {
$this->buildable = $buildable;
return $this;
}
public function getBuildable() {
return $this->assertAttached($this->buildable);
}
public function getName() {
if ($this->getBuildPlan()) {
return $this->getBuildPlan()->getName();
}
return pht('Build');
}
public function attachBuildPlan(
HarbormasterBuildPlan $build_plan = null) {
$this->buildPlan = $build_plan;
return $this;
}
public function getBuildPlan() {
return $this->assertAttached($this->buildPlan);
}
public function getBuildTargets() {
return $this->assertAttached($this->buildTargets);
}
public function attachBuildTargets(array $targets) {
$this->buildTargets = $targets;
return $this;
}
public function isBuilding() {
return
$this->getBuildStatus() === HarbormasterBuildStatus::STATUS_PENDING ||
$this->getBuildStatus() === HarbormasterBuildStatus::STATUS_BUILDING;
}
public function isAutobuild() {
return ($this->getPlanAutoKey() !== null);
}
public function retrieveVariablesFromBuild() {
$results = array(
'buildable.diff' => null,
'buildable.revision' => null,
'buildable.commit' => null,
'repository.callsign' => null,
'repository.phid' => null,
'repository.vcs' => null,
'repository.uri' => null,
'step.timestamp' => null,
'build.id' => null,
'initiator.phid' => null,
);
foreach ($this->getBuildParameters() as $key => $value) {
$results['build/'.$key] = $value;
}
$buildable = $this->getBuildable();
$object = $buildable->getBuildableObject();
$object_variables = $object->getBuildVariables();
$results = $object_variables + $results;
$results['step.timestamp'] = time();
$results['build.id'] = $this->getID();
$results['initiator.phid'] = $this->getInitiatorPHID();
return $results;
}
public static function getAvailableBuildVariables() {
$objects = id(new PhutilClassMapQuery())
->setAncestorClass('HarbormasterBuildableInterface')
->execute();
$variables = array();
$variables[] = array(
'step.timestamp' => pht('The current UNIX timestamp.'),
'build.id' => pht('The ID of the current build.'),
'target.phid' => pht('The PHID of the current build target.'),
'initiator.phid' => pht(
'The PHID of the user or Object that initiated the build, '.
'if applicable.'),
);
foreach ($objects as $object) {
$variables[] = $object->getAvailableBuildVariables();
}
$variables = array_mergev($variables);
return $variables;
}
public function isComplete() {
return in_array(
$this->getBuildStatus(),
HarbormasterBuildStatus::getCompletedStatusConstants());
}
public function isPaused() {
return ($this->getBuildStatus() == HarbormasterBuildStatus::STATUS_PAUSED);
}
public function getURI() {
$id = $this->getID();
return "/harbormaster/build/{$id}/";
}
/* -( Build Commands )----------------------------------------------------- */
private function getUnprocessedCommands() {
return $this->assertAttached($this->unprocessedCommands);
}
public function attachUnprocessedCommands(array $commands) {
$this->unprocessedCommands = $commands;
return $this;
}
public function canRestartBuild() {
if ($this->isAutobuild()) {
return false;
}
return !$this->isRestarting();
}
public function canPauseBuild() {
if ($this->isAutobuild()) {
return false;
}
return !$this->isComplete() &&
!$this->isPaused() &&
!$this->isPausing();
}
public function canAbortBuild() {
if ($this->isAutobuild()) {
return false;
}
return !$this->isComplete();
}
public function canResumeBuild() {
if ($this->isAutobuild()) {
return false;
}
return $this->isPaused() &&
!$this->isResuming();
}
public function isPausing() {
$is_pausing = false;
foreach ($this->getUnprocessedCommands() as $command_object) {
$command = $command_object->getCommand();
switch ($command) {
case HarbormasterBuildCommand::COMMAND_PAUSE:
$is_pausing = true;
break;
case HarbormasterBuildCommand::COMMAND_RESUME:
case HarbormasterBuildCommand::COMMAND_RESTART:
$is_pausing = false;
break;
case HarbormasterBuildCommand::COMMAND_ABORT:
$is_pausing = true;
break;
}
}
return $is_pausing;
}
public function isResuming() {
$is_resuming = false;
foreach ($this->getUnprocessedCommands() as $command_object) {
$command = $command_object->getCommand();
switch ($command) {
case HarbormasterBuildCommand::COMMAND_RESTART:
case HarbormasterBuildCommand::COMMAND_RESUME:
$is_resuming = true;
break;
case HarbormasterBuildCommand::COMMAND_PAUSE:
$is_resuming = false;
break;
case HarbormasterBuildCommand::COMMAND_ABORT:
$is_resuming = false;
break;
}
}
return $is_resuming;
}
public function isRestarting() {
$is_restarting = false;
foreach ($this->getUnprocessedCommands() as $command_object) {
$command = $command_object->getCommand();
switch ($command) {
case HarbormasterBuildCommand::COMMAND_RESTART:
$is_restarting = true;
break;
}
}
return $is_restarting;
}
public function isAborting() {
$is_aborting = false;
foreach ($this->getUnprocessedCommands() as $command_object) {
$command = $command_object->getCommand();
switch ($command) {
case HarbormasterBuildCommand::COMMAND_ABORT:
$is_aborting = true;
break;
}
}
return $is_aborting;
}
public function deleteUnprocessedCommands() {
foreach ($this->getUnprocessedCommands() as $key => $command_object) {
$command_object->delete();
unset($this->unprocessedCommands[$key]);
}
return $this;
}
public function canIssueCommand(PhabricatorUser $viewer, $command) {
try {
$this->assertCanIssueCommand($viewer, $command);
return true;
} catch (Exception $ex) {
return false;
}
}
public function assertCanIssueCommand(PhabricatorUser $viewer, $command) {
$need_edit = false;
switch ($command) {
case HarbormasterBuildCommand::COMMAND_RESTART:
break;
case HarbormasterBuildCommand::COMMAND_PAUSE:
case HarbormasterBuildCommand::COMMAND_RESUME:
case HarbormasterBuildCommand::COMMAND_ABORT:
$need_edit = true;
break;
default:
throw new Exception(
pht(
'Invalid Harbormaster build command "%s".',
$command));
}
// Issuing these commands requires that you be able to edit the build, to
// prevent enemy engineers from sabotaging your builds. See T9614.
if ($need_edit) {
PhabricatorPolicyFilter::requireCapability(
$viewer,
$this->getBuildPlan(),
PhabricatorPolicyCapability::CAN_EDIT);
}
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new HarbormasterBuildTransactionEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new HarbormasterBuildTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return $this->getBuildable()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getBuildable()->hasAutomaticCapability(
$capability,
$viewer);
}
public function describeAutomaticCapability($capability) {
return pht('A build inherits policies from its buildable.');
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('buildablePHID')
->setType('phid')
->setDescription(pht('PHID of the object this build is building.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('buildPlanPHID')
->setType('phid')
->setDescription(pht('PHID of the build plan being run.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('buildStatus')
->setType('map<string, wild>')
->setDescription(pht('The current status of this build.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('initiatorPHID')
->setType('phid')
->setDescription(pht('The person (or thing) that started this build.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of this build.')),
);
}
public function getFieldValuesForConduit() {
$status = $this->getBuildStatus();
return array(
'buildablePHID' => $this->getBuildablePHID(),
'buildPlanPHID' => $this->getBuildPlanPHID(),
'buildStatus' => array(
'value' => $status,
'name' => HarbormasterBuildStatus::getBuildStatusName($status),
+ 'color.ansi' =>
+ HarbormasterBuildStatus::getBuildStatusANSIColor($status),
),
'initiatorPHID' => nonempty($this->getInitiatorPHID(), null),
'name' => $this->getName(),
);
}
public function getConduitSearchAttachments() {
return array(
id(new HarbormasterQueryBuildsSearchEngineAttachment())
->setAttachmentKey('querybuilds'),
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Apr 30, 12:04 PM (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
108703
Default Alt Text
(22 KB)

Event Timeline