Page MenuHomePhabricator

D15363.id.diff
No OneTemporary

D15363.id.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,7 +7,7 @@
*/
return array(
'names' => array(
- 'core.pkg.css' => 'ecdca229',
+ 'core.pkg.css' => 'f7a91f6a',
'core.pkg.js' => '7d8faf57',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '2de124c9',
@@ -25,7 +25,7 @@
'rsrc/css/aphront/notification.css' => '7f684b62',
'rsrc/css/aphront/panel-view.css' => '8427b78d',
'rsrc/css/aphront/phabricator-nav-view.css' => 'ac79a758',
- 'rsrc/css/aphront/table-view.css' => '6d01d468',
+ 'rsrc/css/aphront/table-view.css' => 'ec078a76',
'rsrc/css/aphront/tokenizer.css' => '056da01b',
'rsrc/css/aphront/tooltip.css' => '1a07aea8',
'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c',
@@ -70,7 +70,7 @@
'rsrc/css/application/feed/feed.css' => 'ecd4ec57',
'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2',
'rsrc/css/application/flag/flag.css' => '5337623f',
- 'rsrc/css/application/harbormaster/harbormaster.css' => 'b0758ca5',
+ 'rsrc/css/application/harbormaster/harbormaster.css' => '834879db',
'rsrc/css/application/herald/herald-test.css' => 'a52e323e',
'rsrc/css/application/herald/herald.css' => '826075fa',
'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5',
@@ -523,7 +523,7 @@
'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => 'fd18389d',
'aphront-panel-view-css' => '8427b78d',
- 'aphront-table-view-css' => '6d01d468',
+ 'aphront-table-view-css' => 'ec078a76',
'aphront-tokenizer-control-css' => '056da01b',
'aphront-tooltip-css' => '1a07aea8',
'aphront-typeahead-control-css' => 'd4f16145',
@@ -558,7 +558,7 @@
'font-fontawesome' => 'c43323c5',
'font-lato' => 'c7ccd872',
'global-drag-and-drop-css' => '5c1b47c2',
- 'harbormaster-css' => 'b0758ca5',
+ 'harbormaster-css' => '834879db',
'herald-css' => '826075fa',
'herald-rule-editor' => '746ca158',
'herald-test-css' => 'a52e323e',
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
@@ -1145,7 +1145,8 @@
'HarbormasterThrowExceptionBuildStep' => 'applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php',
'HarbormasterUIEventListener' => 'applications/harbormaster/event/HarbormasterUIEventListener.php',
'HarbormasterURIArtifact' => 'applications/harbormaster/artifact/HarbormasterURIArtifact.php',
- 'HarbormasterUnitMessagesController' => 'applications/harbormaster/controller/HarbormasterUnitMessagesController.php',
+ 'HarbormasterUnitMessageListController' => 'applications/harbormaster/controller/HarbormasterUnitMessageListController.php',
+ 'HarbormasterUnitMessageViewController' => 'applications/harbormaster/controller/HarbormasterUnitMessageViewController.php',
'HarbormasterUnitPropertyView' => 'applications/harbormaster/view/HarbormasterUnitPropertyView.php',
'HarbormasterUnitStatus' => 'applications/harbormaster/constants/HarbormasterUnitStatus.php',
'HarbormasterUploadArtifactBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php',
@@ -5313,7 +5314,8 @@
'HarbormasterThrowExceptionBuildStep' => 'HarbormasterBuildStepImplementation',
'HarbormasterUIEventListener' => 'PhabricatorEventListener',
'HarbormasterURIArtifact' => 'HarbormasterArtifact',
- 'HarbormasterUnitMessagesController' => 'HarbormasterController',
+ 'HarbormasterUnitMessageListController' => 'HarbormasterController',
+ 'HarbormasterUnitMessageViewController' => 'HarbormasterController',
'HarbormasterUnitPropertyView' => 'AphrontView',
'HarbormasterUnitStatus' => 'Phobject',
'HarbormasterUploadArtifactBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
diff --git a/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php b/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
--- a/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
+++ b/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
@@ -85,7 +85,8 @@
'(?P<id>\d+)/' => 'HarbormasterPlanViewController',
),
'unit/' => array(
- '(?P<id>\d+)/' => 'HarbormasterUnitMessagesController',
+ '(?P<id>\d+)/' => 'HarbormasterUnitMessageListController',
+ 'view/(?P<id>\d+)/' => 'HarbormasterUnitMessageViewController',
),
'lint/' => array(
'(?P<id>\d+)/' => 'HarbormasterLintMessagesController',
diff --git a/src/applications/harbormaster/controller/HarbormasterUnitMessagesController.php b/src/applications/harbormaster/controller/HarbormasterUnitMessageListController.php
rename from src/applications/harbormaster/controller/HarbormasterUnitMessagesController.php
rename to src/applications/harbormaster/controller/HarbormasterUnitMessageListController.php
--- a/src/applications/harbormaster/controller/HarbormasterUnitMessagesController.php
+++ b/src/applications/harbormaster/controller/HarbormasterUnitMessageListController.php
@@ -1,6 +1,6 @@
<?php
-final class HarbormasterUnitMessagesController
+final class HarbormasterUnitMessageListController
extends HarbormasterController {
public function handleRequest(AphrontRequest $request) {
diff --git a/src/applications/harbormaster/controller/HarbormasterUnitMessageViewController.php b/src/applications/harbormaster/controller/HarbormasterUnitMessageViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/harbormaster/controller/HarbormasterUnitMessageViewController.php
@@ -0,0 +1,122 @@
+<?php
+
+final class HarbormasterUnitMessageViewController
+ extends HarbormasterController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+
+ $message_id = $request->getURIData('id');
+
+ $message = id(new HarbormasterBuildUnitMessage())->load($message_id);
+ if (!$message) {
+ return new Aphront404Response();
+ }
+
+ $build_target = id(new HarbormasterBuildTargetQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($message->getBuildTargetPHID()))
+ ->executeOne();
+ if (!$build_target) {
+ return new Aphront404Response();
+ }
+
+ $build = $build_target->getBuild();
+ $buildable = $build->getBuildable();
+ $buildable_id = $buildable->getID();
+
+ $id = $message->getID();
+ $display_name = $message->getUnitMessageDisplayName();
+
+ $status = $message->getResult();
+ $status_icon = HarbormasterUnitStatus::getUnitStatusIcon($status);
+ $status_color = HarbormasterUnitStatus::getUnitStatusColor($status);
+ $status_label = HarbormasterUnitStatus::getUnitStatusLabel($status);
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader($display_name)
+ ->setStatus($status_icon, $status_color, $status_label);
+
+ $properties = $this->buildPropertyListView($message);
+ $actions = $this->buildActionView($message, $build);
+
+ $properties->setActionList($actions);
+
+ $unit = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($properties);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $this->addBuildableCrumb($crumbs, $buildable);
+
+ $crumbs->addTextCrumb(
+ pht('Unit Tests'),
+ "/harbormaster/unit/{$buildable_id}/");
+
+ $crumbs->addTextCrumb(pht('Unit %d', $id));
+
+ $title = array(
+ $display_name,
+ $buildable->getMonogram(),
+ );
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->appendChild($unit);
+ }
+
+ private function buildPropertyListView(
+ HarbormasterBuildUnitMessage $message) {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $view = id(new PHUIPropertyListView())
+ ->setUser($viewer);
+
+ $view->addProperty(
+ pht('Run At'),
+ phabricator_datetime($message->getDateCreated(), $viewer));
+
+ $details = $message->getUnitMessageDetails();
+ if (strlen($details)) {
+ // TODO: Use the log view here, once it gets cleaned up.
+ $details = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'PhabricatorMonospaced',
+ 'style' =>
+ 'white-space: pre-wrap; '.
+ 'color: #666666; '.
+ 'overflow-x: auto;',
+ ),
+ $details);
+ } else {
+ $details = phutil_tag('em', array(), pht('No details provided.'));
+ }
+
+ $view->addSectionHeader(
+ pht('Details'),
+ PHUIPropertyListView::ICON_TESTPLAN);
+ $view->addTextContent($details);
+
+ return $view;
+ }
+
+ private function buildActionView(
+ HarbormasterBuildUnitMessage $message,
+ HarbormasterBuild $build) {
+ $viewer = $this->getViewer();
+
+ $view = id(new PhabricatorActionListView())
+ ->setUser($viewer);
+
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('View Build'))
+ ->setHref($build->getURI())
+ ->setIcon('fa-wrench'));
+
+ return $view;
+ }
+}
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
@@ -323,6 +323,11 @@
return ($this->getBuildStatus() == self::STATUS_PAUSED);
}
+ public function getURI() {
+ $id = $this->getID();
+ return "/harbormaster/build/{$id}/";
+ }
+
/* -( Build Commands )----------------------------------------------------- */
diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
--- a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
+++ b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
@@ -61,6 +61,11 @@
'description' => pht(
'Coverage information for this test.'),
),
+ 'details' => array(
+ 'type' => 'optional string',
+ 'description' => pht(
+ 'Additional human-readable information about the failure.'),
+ ),
);
}
@@ -94,6 +99,11 @@
$obj->setProperty('coverage', $coverage);
}
+ $details = idx($dict, 'details');
+ if ($details) {
+ $obj->setProperty('details', $details);
+ }
+
return $obj;
}
@@ -135,6 +145,30 @@
return $this;
}
+ public function getUnitMessageDetails() {
+ return $this->getProperty('details', '');
+ }
+
+ public function getUnitMessageDisplayName() {
+ $name = $this->getName();
+
+ $namespace = $this->getNamespace();
+ if (strlen($namespace)) {
+ $name = $namespace.'::'.$name;
+ }
+
+ $engine = $this->getEngine();
+ if (strlen($engine)) {
+ $name = $engine.' > '.$name;
+ }
+
+ if (!strlen($name)) {
+ return pht('Nameless Test (%d)', $this->getID());
+ }
+
+ return $name;
+ }
+
public function getSortKey() {
$status = $this->getResult();
$sort = HarbormasterUnitStatus::getUnitStatusSort($status);
diff --git a/src/applications/harbormaster/view/HarbormasterUnitPropertyView.php b/src/applications/harbormaster/view/HarbormasterUnitPropertyView.php
--- a/src/applications/harbormaster/view/HarbormasterUnitPropertyView.php
+++ b/src/applications/harbormaster/view/HarbormasterUnitPropertyView.php
@@ -29,6 +29,8 @@
}
public function render() {
+ require_celerity_resource('harbormaster-css');
+
$messages = $this->unitMessages;
$messages = msort($messages, 'getSortKey');
@@ -63,16 +65,22 @@
$duration = pht('%s ms', new PhutilNumber((int)(1000 * $duration)));
}
- $name = $message->getName();
-
- $namespace = $message->getNamespace();
- if (strlen($namespace)) {
- $name = $namespace.'::'.$name;
- }
+ $name = $message->getUnitMessageDisplayName();
+ $id = $message->getID();
- $engine = $message->getEngine();
- if (strlen($engine)) {
- $name = $engine.' > '.$name;
+ $name = phutil_tag(
+ 'a',
+ array(
+ 'href' => "/harbormaster/unit/view/{$id}/",
+ ),
+ $name);
+
+ $details = $message->getUnitMessageDetails();
+ if (strlen($details)) {
+ $name = array(
+ $name,
+ $this->renderUnitTestDetails($details),
+ );
}
$rows[] = array(
@@ -119,9 +127,14 @@
))
->setColumnClasses(
array(
- null,
- null,
- 'pri wide',
+ 'top',
+ 'top',
+ 'top wide',
+ ))
+ ->setColumnWidths(
+ array(
+ '32px',
+ '64px',
))
->setColumnVisibility(
array(
@@ -132,4 +145,25 @@
return $table;
}
+ private function renderUnitTestDetails($full_details) {
+ $details = id(new PhutilUTF8StringTruncator())
+ ->setMaximumBytes(2048)
+ ->truncateString($full_details);
+ $details = phutil_split_lines($details);
+
+ $limit = 3;
+ if (count($details) > $limit) {
+ $details = array_slice($details, 0, $limit);
+ }
+
+ $details = implode('', $details);
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'PhabricatorMonospaced harbormaster-unit-details',
+ ),
+ $details);
+ }
+
}
diff --git a/src/view/control/AphrontTableView.php b/src/view/control/AphrontTableView.php
--- a/src/view/control/AphrontTableView.php
+++ b/src/view/control/AphrontTableView.php
@@ -15,6 +15,8 @@
protected $columnVisibility = array();
private $deviceVisibility = array();
+ private $columnWidths = array();
+
protected $sortURI;
protected $sortParam;
protected $sortSelected;
@@ -46,6 +48,11 @@
return $this;
}
+ public function setColumnWidths(array $widths) {
+ $this->columnWidths = $widths;
+ return $this;
+ }
+
public function setNoDataString($no_data_string) {
$this->noDataString = $no_data_string;
return $this;
@@ -131,6 +138,8 @@
$visibility = array_values($this->columnVisibility);
$device_visibility = array_values($this->deviceVisibility);
+ $column_widths = $this->columnWidths;
+
$headers = $this->headers;
$short_headers = $this->shortHeaders;
$sort_values = $this->sortValues;
@@ -236,7 +245,18 @@
$header = hsprintf('%s %s', $header_nodevice, $header_device);
}
- $tr[] = phutil_tag('th', array('class' => $class), $header);
+ $style = null;
+ if (isset($column_widths[$col_num])) {
+ $style = 'width: '.$column_widths[$col_num].';';
+ }
+
+ $tr[] = phutil_tag(
+ 'th',
+ array(
+ 'class' => $class,
+ 'style' => $style,
+ ),
+ $header);
}
$table[] = phutil_tag('tr', array(), $tr);
}
@@ -283,7 +303,13 @@
if (!empty($this->cellClasses[$row_num][$col_num])) {
$class = trim($class.' '.$this->cellClasses[$row_num][$col_num]);
}
- $tr[] = phutil_tag('td', array('class' => $class), $value);
+
+ $tr[] = phutil_tag(
+ 'td',
+ array(
+ 'class' => $class,
+ ),
+ $value);
++$col_num;
}
@@ -315,10 +341,15 @@
if ($this->className !== null) {
$classes[] = $this->className;
}
+
if ($this->deviceReadyTable) {
$classes[] = 'aphront-table-view-device-ready';
}
+ if ($this->columnWidths) {
+ $classes[] = 'aphront-table-view-fixed';
+ }
+
$html = phutil_tag(
'table',
array(
diff --git a/webroot/rsrc/css/aphront/table-view.css b/webroot/rsrc/css/aphront/table-view.css
--- a/webroot/rsrc/css/aphront/table-view.css
+++ b/webroot/rsrc/css/aphront/table-view.css
@@ -15,6 +15,10 @@
border-bottom: 1px solid {$blueborder};
}
+.aphront-table-view-fixed {
+ table-layout: fixed;
+}
+
.aphront-table-view td.aphront-table-notice {
padding: 12px 16px;
font-size: {$normalfontsize};
diff --git a/webroot/rsrc/css/application/harbormaster/harbormaster.css b/webroot/rsrc/css/application/harbormaster/harbormaster.css
--- a/webroot/rsrc/css/application/harbormaster/harbormaster.css
+++ b/webroot/rsrc/css/application/harbormaster/harbormaster.css
@@ -20,3 +20,11 @@
padding: 12px;
color: {$darkgreytext};
}
+
+.harbormaster-unit-details {
+ margin: 8px 0 4px;
+ overflow: hidden;
+ white-space: pre;
+ text-overflow: ellipsis;
+ color: {$lightgreytext};
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 10:05 PM (9 h, 46 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6922174
Default Alt Text
D15363.id.diff (16 KB)

Event Timeline