2013-11-08 18:09:03 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class HarbormasterBuildViewController
|
|
|
|
extends HarbormasterController {
|
|
|
|
|
|
|
|
private $id;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->id = $data['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $request->getUser();
|
|
|
|
|
|
|
|
$id = $this->id;
|
2014-08-21 22:55:24 +10:00
|
|
|
$generation = $request->getInt('g');
|
2013-11-08 18:09:03 -08:00
|
|
|
|
|
|
|
$build = id(new HarbormasterBuildQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withIDs(array($id))
|
|
|
|
->executeOne();
|
|
|
|
if (!$build) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
require_celerity_resource('harbormaster-css');
|
|
|
|
|
2014-06-09 11:36:49 -07:00
|
|
|
$title = pht('Build %d', $id);
|
2013-11-08 18:09:03 -08:00
|
|
|
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
|
|
->setHeader($title)
|
|
|
|
->setUser($viewer)
|
|
|
|
->setPolicyObject($build);
|
|
|
|
|
2014-01-06 14:12:05 -08:00
|
|
|
if ($build->isRestarting()) {
|
2014-05-18 16:10:54 -07:00
|
|
|
$header->setStatus('fa-exclamation-triangle', 'red', pht('Restarting'));
|
2014-01-06 14:12:05 -08:00
|
|
|
} else if ($build->isStopping()) {
|
2014-08-08 08:25:04 +10:00
|
|
|
$header->setStatus('fa-exclamation-triangle', 'red', pht('Pausing'));
|
2014-01-06 14:12:05 -08:00
|
|
|
} else if ($build->isResuming()) {
|
2014-05-18 16:10:54 -07:00
|
|
|
$header->setStatus('fa-exclamation-triangle', 'red', pht('Resuming'));
|
2014-01-06 14:12:05 -08:00
|
|
|
}
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
$box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeader($header);
|
|
|
|
|
|
|
|
$actions = $this->buildActionList($build);
|
|
|
|
$this->buildPropertyLists($box, $build, $actions);
|
|
|
|
|
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2014-01-06 14:12:05 -08:00
|
|
|
$crumbs->addTextCrumb(
|
|
|
|
$build->getBuildable()->getMonogram(),
|
|
|
|
'/'.$build->getBuildable()->getMonogram());
|
2013-12-18 17:47:34 -08:00
|
|
|
$crumbs->addTextCrumb($title);
|
2013-11-08 18:09:03 -08:00
|
|
|
|
2014-08-21 22:55:24 +10:00
|
|
|
if ($generation === null || $generation > $build->getBuildGeneration() ||
|
|
|
|
$generation < 0) {
|
|
|
|
$generation = $build->getBuildGeneration();
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:01:12 +11:00
|
|
|
$build_targets = id(new HarbormasterBuildTargetQuery())
|
|
|
|
->setViewer($viewer)
|
2014-08-01 08:09:15 +10:00
|
|
|
->needBuildSteps(true)
|
2013-12-05 12:01:12 +11:00
|
|
|
->withBuildPHIDs(array($build->getPHID()))
|
2014-08-21 22:55:24 +10:00
|
|
|
->withBuildGenerations(array($generation))
|
2013-12-05 12:01:12 +11:00
|
|
|
->execute();
|
|
|
|
|
2014-03-25 16:11:28 -07:00
|
|
|
if ($build_targets) {
|
|
|
|
$messages = id(new HarbormasterBuildMessageQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withBuildTargetPHIDs(mpull($build_targets, 'getPHID'))
|
|
|
|
->execute();
|
|
|
|
$messages = mgroup($messages, 'getBuildTargetPHID');
|
|
|
|
} else {
|
|
|
|
$messages = array();
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:01:12 +11:00
|
|
|
$targets = array();
|
|
|
|
foreach ($build_targets as $build_target) {
|
|
|
|
$header = id(new PHUIHeaderView())
|
2014-08-01 08:09:15 +10:00
|
|
|
->setHeader($build_target->getName())
|
2013-12-05 12:01:12 +11:00
|
|
|
->setUser($viewer);
|
2014-08-01 08:09:15 +10:00
|
|
|
|
|
|
|
$target_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeader($header);
|
|
|
|
|
2013-12-05 12:01:12 +11:00
|
|
|
$properties = new PHUIPropertyListView();
|
2014-08-01 08:09:15 +10:00
|
|
|
$status_view = new PHUIStatusListView();
|
|
|
|
|
|
|
|
$item = new PHUIStatusItemView();
|
|
|
|
|
|
|
|
$status = $build_target->getTargetStatus();
|
|
|
|
$status_name =
|
|
|
|
HarbormasterBuildTarget::getBuildTargetStatusName($status);
|
|
|
|
$icon = HarbormasterBuildTarget::getBuildTargetStatusIcon($status);
|
|
|
|
$color = HarbormasterBuildTarget::getBuildTargetStatusColor($status);
|
|
|
|
|
|
|
|
$item->setTarget($status_name);
|
|
|
|
$item->setIcon($icon, $color);
|
|
|
|
$status_view->addItem($item);
|
|
|
|
|
|
|
|
$properties->addProperty(pht('Name'), $build_target->getName());
|
2014-08-12 08:34:43 +10:00
|
|
|
|
|
|
|
if ($build_target->getDateStarted() !== null) {
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Started'),
|
|
|
|
phabricator_datetime($build_target->getDateStarted(), $viewer));
|
|
|
|
if ($build_target->isComplete()) {
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Completed'),
|
|
|
|
phabricator_datetime($build_target->getDateCompleted(), $viewer));
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Duration'),
|
|
|
|
phutil_format_relative_time_detailed(
|
|
|
|
$build_target->getDateCompleted() -
|
|
|
|
$build_target->getDateStarted()));
|
|
|
|
} else {
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Elapsed'),
|
|
|
|
phutil_format_relative_time_detailed(
|
|
|
|
time() - $build_target->getDateStarted()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 08:09:15 +10:00
|
|
|
$properties->addProperty(pht('Status'), $status_view);
|
|
|
|
|
|
|
|
$target_box->addPropertyList($properties, pht('Overview'));
|
|
|
|
|
2014-08-28 08:20:11 +10:00
|
|
|
$step = $build_target->getBuildStep();
|
|
|
|
|
|
|
|
if ($step) {
|
|
|
|
$description = $step->getDescription();
|
|
|
|
if ($description) {
|
|
|
|
$rendered = PhabricatorMarkupEngine::renderOneObject(
|
|
|
|
id(new PhabricatorMarkupOneOff())
|
|
|
|
->setContent($description)
|
|
|
|
->setPreserveLinebreaks(true),
|
|
|
|
'default',
|
|
|
|
$viewer);
|
|
|
|
|
|
|
|
$properties->addSectionHeader(pht('Description'));
|
|
|
|
$properties->addTextContent($rendered);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$target_box->setFormErrors(
|
|
|
|
array(
|
|
|
|
pht(
|
|
|
|
'This build step has since been deleted on the build plan. '.
|
|
|
|
'Some information may be omitted.'),
|
|
|
|
));
|
2014-08-01 08:09:15 +10:00
|
|
|
}
|
2013-12-05 12:01:12 +11:00
|
|
|
|
|
|
|
$details = $build_target->getDetails();
|
|
|
|
if ($details) {
|
2014-08-01 08:09:15 +10:00
|
|
|
$properties = new PHUIPropertyListView();
|
2013-12-05 12:01:12 +11:00
|
|
|
foreach ($details as $key => $value) {
|
|
|
|
$properties->addProperty($key, $value);
|
|
|
|
}
|
2014-08-01 08:09:15 +10:00
|
|
|
$target_box->addPropertyList($properties, pht('Configuration'));
|
2013-12-05 12:01:12 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
$variables = $build_target->getVariables();
|
|
|
|
if ($variables) {
|
2014-08-01 08:09:15 +10:00
|
|
|
$properties = new PHUIPropertyListView();
|
2013-12-05 12:01:12 +11:00
|
|
|
foreach ($variables as $key => $value) {
|
|
|
|
$properties->addProperty($key, $value);
|
|
|
|
}
|
2014-08-01 08:09:15 +10:00
|
|
|
$target_box->addPropertyList($properties, pht('Variables'));
|
2013-12-05 12:01:12 +11:00
|
|
|
}
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
$artifacts = $this->buildArtifacts($build_target);
|
|
|
|
if ($artifacts) {
|
|
|
|
$properties = new PHUIPropertyListView();
|
|
|
|
$properties->addRawContent($artifacts);
|
|
|
|
$target_box->addPropertyList($properties, pht('Artifacts'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$build_messages = idx($messages, $build_target->getPHID(), array());
|
|
|
|
if ($build_messages) {
|
|
|
|
$properties = new PHUIPropertyListView();
|
|
|
|
$properties->addRawContent($this->buildMessages($build_messages));
|
|
|
|
$target_box->addPropertyList($properties, pht('Messages'));
|
|
|
|
}
|
|
|
|
|
2014-08-01 08:09:15 +10:00
|
|
|
$properties = new PHUIPropertyListView();
|
|
|
|
$properties->addProperty('Build Target ID', $build_target->getID());
|
|
|
|
$target_box->addPropertyList($properties, pht('Metadata'));
|
|
|
|
|
|
|
|
$targets[] = $target_box;
|
2013-12-05 12:01:12 +11:00
|
|
|
|
|
|
|
$targets[] = $this->buildLog($build, $build_target);
|
|
|
|
}
|
|
|
|
|
2014-05-15 07:02:30 -07:00
|
|
|
$xactions = id(new HarbormasterBuildTransactionQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withObjectPHIDs(array($build->getPHID()))
|
|
|
|
->execute();
|
|
|
|
$timeline = id(new PhabricatorApplicationTransactionView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setObjectPHID($build->getPHID())
|
|
|
|
->setTransactions($xactions);
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
return $this->buildApplicationPage(
|
|
|
|
array(
|
|
|
|
$crumbs,
|
|
|
|
$box,
|
2014-05-15 07:02:30 -07:00
|
|
|
$targets,
|
|
|
|
$timeline,
|
2013-11-08 18:09:03 -08:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => $title,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
private function buildArtifacts(
|
|
|
|
HarbormasterBuildTarget $build_target) {
|
|
|
|
|
2013-12-05 14:06:22 +11:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $request->getUser();
|
|
|
|
|
|
|
|
$artifacts = id(new HarbormasterBuildArtifactQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withBuildTargetPHIDs(array($build_target->getPHID()))
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
if (count($artifacts) === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
$list = id(new PHUIObjectItemListView())
|
|
|
|
->setFlush(true);
|
2013-12-05 14:06:22 +11:00
|
|
|
|
|
|
|
foreach ($artifacts as $artifact) {
|
2014-08-12 08:34:43 +10:00
|
|
|
$item = $artifact->getObjectItemView($viewer);
|
|
|
|
if ($item !== null) {
|
|
|
|
$list->addItem($item);
|
|
|
|
}
|
2013-12-05 14:06:22 +11:00
|
|
|
}
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
return $list;
|
2013-12-05 14:06:22 +11:00
|
|
|
}
|
|
|
|
|
2013-12-05 12:01:12 +11:00
|
|
|
private function buildLog(
|
|
|
|
HarbormasterBuild $build,
|
|
|
|
HarbormasterBuildTarget $build_target) {
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $request->getUser();
|
|
|
|
$limit = $request->getInt('l', 25);
|
|
|
|
|
|
|
|
$logs = id(new HarbormasterBuildLogQuery())
|
|
|
|
->setViewer($viewer)
|
2013-12-05 12:01:12 +11:00
|
|
|
->withBuildTargetPHIDs(array($build_target->getPHID()))
|
2013-11-08 18:09:03 -08:00
|
|
|
->execute();
|
|
|
|
|
2014-08-06 10:28:13 +10:00
|
|
|
$empty_logs = array();
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
$log_boxes = array();
|
|
|
|
foreach ($logs as $log) {
|
|
|
|
$start = 1;
|
|
|
|
$lines = preg_split("/\r\n|\r|\n/", $log->getLogText());
|
|
|
|
if ($limit !== 0) {
|
|
|
|
$start = count($lines) - $limit;
|
|
|
|
if ($start >= 1) {
|
|
|
|
$lines = array_slice($lines, -$limit, $limit);
|
|
|
|
} else {
|
|
|
|
$start = 1;
|
|
|
|
}
|
|
|
|
}
|
2014-08-06 10:28:13 +10:00
|
|
|
|
|
|
|
$id = null;
|
|
|
|
$is_empty = false;
|
|
|
|
if (count($lines) === 1 && trim($lines[0]) === '') {
|
|
|
|
// Prevent Harbormaster from showing empty build logs.
|
|
|
|
$id = celerity_generate_unique_node_id();
|
|
|
|
$empty_logs[] = $id;
|
|
|
|
$is_empty = true;
|
|
|
|
}
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
$log_view = new ShellLogView();
|
|
|
|
$log_view->setLines($lines);
|
|
|
|
$log_view->setStart($start);
|
|
|
|
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
|
|
->setHeader(pht(
|
|
|
|
'Build Log %d (%s - %s)',
|
|
|
|
$log->getID(),
|
|
|
|
$log->getLogSource(),
|
|
|
|
$log->getLogType()))
|
|
|
|
->setSubheader($this->createLogHeader($build, $log))
|
|
|
|
->setUser($viewer);
|
|
|
|
|
2014-08-06 10:28:13 +10:00
|
|
|
$log_box = id(new PHUIObjectBoxView())
|
2013-11-08 18:09:03 -08:00
|
|
|
->setHeader($header)
|
|
|
|
->setForm($log_view);
|
2014-08-06 10:28:13 +10:00
|
|
|
|
|
|
|
if ($is_empty) {
|
|
|
|
$log_box = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'style' => 'display: none',
|
2014-10-08 00:01:04 +11:00
|
|
|
'id' => $id,
|
|
|
|
),
|
2014-08-06 10:28:13 +10:00
|
|
|
$log_box);
|
|
|
|
}
|
|
|
|
|
|
|
|
$log_boxes[] = $log_box;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($empty_logs) {
|
|
|
|
$hide_id = celerity_generate_unique_node_id();
|
|
|
|
|
|
|
|
Javelin::initBehavior('phabricator-reveal-content');
|
|
|
|
|
|
|
|
$expand = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'id' => $hide_id,
|
|
|
|
'class' => 'harbormaster-empty-logs-are-hidden mlr mlt mll',
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
pht(
|
|
|
|
'%s empty logs are hidden.',
|
|
|
|
new PhutilNumber(count($empty_logs))),
|
|
|
|
' ',
|
|
|
|
javelin_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#',
|
|
|
|
'sigil' => 'reveal-content',
|
|
|
|
'meta' => array(
|
|
|
|
'showIDs' => $empty_logs,
|
|
|
|
'hideIDs' => array($hide_id),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
pht('Show all logs.')),
|
|
|
|
));
|
|
|
|
|
|
|
|
array_unshift($log_boxes, $expand);
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return $log_boxes;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function createLogHeader($build, $log) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$limit = $request->getInt('l', 25);
|
|
|
|
|
|
|
|
$lines_25 = $this->getApplicationURI('/build/'.$build->getID().'/?l=25');
|
|
|
|
$lines_50 = $this->getApplicationURI('/build/'.$build->getID().'/?l=50');
|
|
|
|
$lines_100 =
|
|
|
|
$this->getApplicationURI('/build/'.$build->getID().'/?l=100');
|
|
|
|
$lines_0 = $this->getApplicationURI('/build/'.$build->getID().'/?l=0');
|
|
|
|
|
|
|
|
$link_25 = phutil_tag('a', array('href' => $lines_25), pht('25'));
|
|
|
|
$link_50 = phutil_tag('a', array('href' => $lines_50), pht('50'));
|
|
|
|
$link_100 = phutil_tag('a', array('href' => $lines_100), pht('100'));
|
|
|
|
$link_0 = phutil_tag('a', array('href' => $lines_0), pht('Unlimited'));
|
|
|
|
|
|
|
|
if ($limit === 25) {
|
|
|
|
$link_25 = phutil_tag('strong', array(), $link_25);
|
|
|
|
} else if ($limit === 50) {
|
|
|
|
$link_50 = phutil_tag('strong', array(), $link_50);
|
|
|
|
} else if ($limit === 100) {
|
|
|
|
$link_100 = phutil_tag('strong', array(), $link_100);
|
|
|
|
} else if ($limit === 0) {
|
|
|
|
$link_0 = phutil_tag('strong', array(), $link_0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return phutil_tag(
|
|
|
|
'span',
|
|
|
|
array(),
|
|
|
|
array(
|
|
|
|
$link_25,
|
|
|
|
' - ',
|
|
|
|
$link_50,
|
|
|
|
' - ',
|
|
|
|
$link_100,
|
|
|
|
' - ',
|
|
|
|
$link_0,
|
2014-10-08 00:01:04 +11:00
|
|
|
' Lines',
|
|
|
|
));
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private function buildActionList(HarbormasterBuild $build) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $request->getUser();
|
|
|
|
$id = $build->getID();
|
|
|
|
|
|
|
|
$list = id(new PhabricatorActionListView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setObject($build)
|
|
|
|
->setObjectURI("/build/{$id}");
|
|
|
|
|
Replace "Cancel Build" with "Stop", "Resume" and "Restart"
Summary:
Ref T1049. Currently you can cancel a build, but now that we're tracking a lot more state we can stop, resume, and restart builds.
When the user issues a command against a build, I'm writing it into an auxiliary queue (`HarbormasterBuildCommand`) and then reading them out in the worker. This is mostly to avoid race messes where we try to `save()` the object in multiple places: basically, the BuildEngine is the //only// thing that writes to Build objects, and it holds a lock while it does it.
Test Plan:
- Created a plan which runs "sleep 2" a bunch of times in a row.
- Stopped, resumed, and restarted it.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, chad
Maniphest Tasks: T1049
Differential Revision: https://secure.phabricator.com/D7892
2014-01-06 12:32:20 -08:00
|
|
|
$can_restart = $build->canRestartBuild();
|
|
|
|
$can_stop = $build->canStopBuild();
|
|
|
|
$can_resume = $build->canResumeBuild();
|
|
|
|
|
|
|
|
$list->addAction(
|
2013-11-08 18:09:03 -08:00
|
|
|
id(new PhabricatorActionView())
|
Replace "Cancel Build" with "Stop", "Resume" and "Restart"
Summary:
Ref T1049. Currently you can cancel a build, but now that we're tracking a lot more state we can stop, resume, and restart builds.
When the user issues a command against a build, I'm writing it into an auxiliary queue (`HarbormasterBuildCommand`) and then reading them out in the worker. This is mostly to avoid race messes where we try to `save()` the object in multiple places: basically, the BuildEngine is the //only// thing that writes to Build objects, and it holds a lock while it does it.
Test Plan:
- Created a plan which runs "sleep 2" a bunch of times in a row.
- Stopped, resumed, and restarted it.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, chad
Maniphest Tasks: T1049
Differential Revision: https://secure.phabricator.com/D7892
2014-01-06 12:32:20 -08:00
|
|
|
->setName(pht('Restart Build'))
|
2014-08-08 08:25:04 +10:00
|
|
|
->setIcon('fa-repeat')
|
Replace "Cancel Build" with "Stop", "Resume" and "Restart"
Summary:
Ref T1049. Currently you can cancel a build, but now that we're tracking a lot more state we can stop, resume, and restart builds.
When the user issues a command against a build, I'm writing it into an auxiliary queue (`HarbormasterBuildCommand`) and then reading them out in the worker. This is mostly to avoid race messes where we try to `save()` the object in multiple places: basically, the BuildEngine is the //only// thing that writes to Build objects, and it holds a lock while it does it.
Test Plan:
- Created a plan which runs "sleep 2" a bunch of times in a row.
- Stopped, resumed, and restarted it.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, chad
Maniphest Tasks: T1049
Differential Revision: https://secure.phabricator.com/D7892
2014-01-06 12:32:20 -08:00
|
|
|
->setHref($this->getApplicationURI('/build/restart/'.$id.'/'))
|
|
|
|
->setDisabled(!$can_restart)
|
|
|
|
->setWorkflow(true));
|
|
|
|
|
2014-08-08 08:25:04 +10:00
|
|
|
if ($build->canResumeBuild()) {
|
|
|
|
$list->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Resume Build'))
|
|
|
|
->setIcon('fa-play')
|
|
|
|
->setHref($this->getApplicationURI('/build/resume/'.$id.'/'))
|
|
|
|
->setDisabled(!$can_resume)
|
|
|
|
->setWorkflow(true));
|
|
|
|
} else {
|
|
|
|
$list->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Pause Build'))
|
|
|
|
->setIcon('fa-pause')
|
|
|
|
->setHref($this->getApplicationURI('/build/stop/'.$id.'/'))
|
|
|
|
->setDisabled(!$can_stop)
|
|
|
|
->setWorkflow(true));
|
|
|
|
}
|
2013-11-08 18:09:03 -08:00
|
|
|
|
|
|
|
return $list;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function buildPropertyLists(
|
|
|
|
PHUIObjectBoxView $box,
|
|
|
|
HarbormasterBuild $build,
|
|
|
|
PhabricatorActionListView $actions) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$viewer = $request->getUser();
|
|
|
|
|
|
|
|
$properties = id(new PHUIPropertyListView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setObject($build)
|
|
|
|
->setActionList($actions);
|
|
|
|
$box->addPropertyList($properties);
|
|
|
|
|
2013-11-09 15:02:07 -08:00
|
|
|
$handles = id(new PhabricatorHandleQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withPHIDs(array(
|
|
|
|
$build->getBuildablePHID(),
|
2014-10-08 00:01:04 +11:00
|
|
|
$build->getBuildPlanPHID(),
|
|
|
|
))
|
2013-11-09 15:02:07 -08:00
|
|
|
->execute();
|
|
|
|
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Buildable'),
|
|
|
|
$handles[$build->getBuildablePHID()]->renderLink());
|
|
|
|
|
|
|
|
$properties->addProperty(
|
|
|
|
pht('Build Plan'),
|
|
|
|
$handles[$build->getBuildPlanPHID()]->renderLink());
|
|
|
|
|
2014-08-21 22:55:24 +10:00
|
|
|
$properties->addProperty(
|
|
|
|
pht('Restarts'),
|
|
|
|
$build->getBuildGeneration());
|
|
|
|
|
2014-08-01 08:10:09 +10:00
|
|
|
$properties->addProperty(
|
|
|
|
pht('Status'),
|
|
|
|
$this->getStatus($build));
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private function getStatus(HarbormasterBuild $build) {
|
2014-08-01 08:09:32 +10:00
|
|
|
$status_view = new PHUIStatusListView();
|
|
|
|
|
|
|
|
$item = new PHUIStatusItemView();
|
|
|
|
|
Replace "Cancel Build" with "Stop", "Resume" and "Restart"
Summary:
Ref T1049. Currently you can cancel a build, but now that we're tracking a lot more state we can stop, resume, and restart builds.
When the user issues a command against a build, I'm writing it into an auxiliary queue (`HarbormasterBuildCommand`) and then reading them out in the worker. This is mostly to avoid race messes where we try to `save()` the object in multiple places: basically, the BuildEngine is the //only// thing that writes to Build objects, and it holds a lock while it does it.
Test Plan:
- Created a plan which runs "sleep 2" a bunch of times in a row.
- Stopped, resumed, and restarted it.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, chad
Maniphest Tasks: T1049
Differential Revision: https://secure.phabricator.com/D7892
2014-01-06 12:32:20 -08:00
|
|
|
if ($build->isStopping()) {
|
2014-08-08 08:25:04 +10:00
|
|
|
$status_name = pht('Pausing');
|
2014-08-01 08:09:32 +10:00
|
|
|
$icon = PHUIStatusItemView::ICON_RIGHT;
|
|
|
|
$color = 'dark';
|
|
|
|
} else {
|
|
|
|
$status = $build->getBuildStatus();
|
|
|
|
$status_name =
|
|
|
|
HarbormasterBuild::getBuildStatusName($status);
|
|
|
|
$icon = HarbormasterBuild::getBuildStatusIcon($status);
|
|
|
|
$color = HarbormasterBuild::getBuildStatusColor($status);
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|
2014-04-17 16:00:58 -07:00
|
|
|
|
2014-08-01 08:09:32 +10:00
|
|
|
$item->setTarget($status_name);
|
|
|
|
$item->setIcon($icon, $color);
|
|
|
|
$status_view->addItem($item);
|
|
|
|
|
|
|
|
return $status_view;
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|
|
|
|
|
2014-03-25 16:11:28 -07:00
|
|
|
private function buildMessages(array $messages) {
|
|
|
|
$viewer = $this->getRequest()->getUser();
|
|
|
|
|
|
|
|
if ($messages) {
|
|
|
|
$handles = id(new PhabricatorHandleQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withPHIDs(mpull($messages, 'getAuthorPHID'))
|
|
|
|
->execute();
|
|
|
|
} else {
|
|
|
|
$handles = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($messages as $message) {
|
|
|
|
$rows[] = array(
|
|
|
|
$message->getID(),
|
|
|
|
$handles[$message->getAuthorPHID()]->renderLink(),
|
|
|
|
$message->getType(),
|
|
|
|
$message->getIsConsumed() ? pht('Consumed') : null,
|
|
|
|
phabricator_datetime($message->getDateCreated(), $viewer),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new AphrontTableView($rows);
|
|
|
|
$table->setNoDataString(pht('No messages for this build target.'));
|
|
|
|
$table->setHeaders(
|
|
|
|
array(
|
|
|
|
pht('ID'),
|
|
|
|
pht('From'),
|
|
|
|
pht('Type'),
|
|
|
|
pht('Consumed'),
|
|
|
|
pht('Received'),
|
|
|
|
));
|
|
|
|
$table->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'',
|
|
|
|
'',
|
|
|
|
'wide',
|
|
|
|
'',
|
|
|
|
'date',
|
|
|
|
));
|
|
|
|
|
2014-08-06 10:34:39 +10:00
|
|
|
return $table;
|
2014-03-25 16:11:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-11-08 18:09:03 -08:00
|
|
|
}
|