@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve lint/unit limit, sort, view all, collapse behaviors

Summary:
Ref T8096. Various tweaks here:

- Sort result lists by importance (even lint -- "errors first" seems better than "alphabetical by file", I think?).
- Do sane stuff with display limits.
- Add a "view all" view.
- Don't show a huge table of passing tests in Differential.
- Link to full results.

Test Plan: See screenshots.

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T8096

Differential Revision: https://secure.phabricator.com/D13407

+340 -19
+3 -3
resources/celerity/map.php
··· 10 10 'core.pkg.css' => 'eb51e6dc', 11 11 'core.pkg.js' => '711e63c0', 12 12 'darkconsole.pkg.js' => 'e7393ebb', 13 - 'differential.pkg.css' => '1ca3c116', 13 + 'differential.pkg.css' => '7b52b9be', 14 14 'differential.pkg.js' => 'ebef29b1', 15 15 'diffusion.pkg.css' => '591664fa', 16 16 'diffusion.pkg.js' => '0115b37c', ··· 64 64 'rsrc/css/application/differential/revision-comment.css' => '14b8565a', 65 65 'rsrc/css/application/differential/revision-history.css' => '0e8eb855', 66 66 'rsrc/css/application/differential/revision-list.css' => 'f3c47d33', 67 - 'rsrc/css/application/differential/table-of-contents.css' => '63f3ef4a', 67 + 'rsrc/css/application/differential/table-of-contents.css' => 'ae4b7a55', 68 68 'rsrc/css/application/diffusion/diffusion-icons.css' => '9c5828da', 69 69 'rsrc/css/application/diffusion/diffusion-readme.css' => '2106ea08', 70 70 'rsrc/css/application/diffusion/diffusion-source.css' => '66fdf661', ··· 515 515 'differential-revision-comment-css' => '14b8565a', 516 516 'differential-revision-history-css' => '0e8eb855', 517 517 'differential-revision-list-css' => 'f3c47d33', 518 - 'differential-table-of-contents-css' => '63f3ef4a', 518 + 'differential-table-of-contents-css' => 'ae4b7a55', 519 519 'diffusion-icons-css' => '9c5828da', 520 520 'diffusion-readme-css' => '2106ea08', 521 521 'diffusion-source-css' => '66fdf661',
+4
src/__phutil_library_map__.php
··· 891 891 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', 892 892 'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php', 893 893 'HarbormasterLeaseHostBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php', 894 + 'HarbormasterLintMessagesController' => 'applications/harbormaster/controller/HarbormasterLintMessagesController.php', 894 895 'HarbormasterLintPropertyView' => 'applications/harbormaster/view/HarbormasterLintPropertyView.php', 895 896 'HarbormasterManagePlansCapability' => 'applications/harbormaster/capability/HarbormasterManagePlansCapability.php', 896 897 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php', ··· 919 920 'HarbormasterTargetWorker' => 'applications/harbormaster/worker/HarbormasterTargetWorker.php', 920 921 'HarbormasterThrowExceptionBuildStep' => 'applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php', 921 922 'HarbormasterUIEventListener' => 'applications/harbormaster/event/HarbormasterUIEventListener.php', 923 + 'HarbormasterUnitMessagesController' => 'applications/harbormaster/controller/HarbormasterUnitMessagesController.php', 922 924 'HarbormasterUnitPropertyView' => 'applications/harbormaster/view/HarbormasterUnitPropertyView.php', 923 925 'HarbormasterUploadArtifactBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php', 924 926 'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php', ··· 4357 4359 'HarbormasterDAO' => 'PhabricatorLiskDAO', 4358 4360 'HarbormasterHTTPRequestBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 4359 4361 'HarbormasterLeaseHostBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 4362 + 'HarbormasterLintMessagesController' => 'HarbormasterController', 4360 4363 'HarbormasterLintPropertyView' => 'AphrontView', 4361 4364 'HarbormasterManagePlansCapability' => 'PhabricatorPolicyCapability', 4362 4365 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow', ··· 4385 4388 'HarbormasterTargetWorker' => 'HarbormasterWorker', 4386 4389 'HarbormasterThrowExceptionBuildStep' => 'HarbormasterBuildStepImplementation', 4387 4390 'HarbormasterUIEventListener' => 'PhabricatorEventListener', 4391 + 'HarbormasterUnitMessagesController' => 'HarbormasterController', 4388 4392 'HarbormasterUnitPropertyView' => 'AphrontView', 4389 4393 'HarbormasterUploadArtifactBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 4390 4394 'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
+13 -2
src/applications/differential/customfield/DifferentialHarbormasterField.php
··· 81 81 $path_map[$path] = $href; 82 82 } 83 83 84 - $view = $this->newHarbormasterMessageView($messages) 85 - ->setPathURIMap($path_map); 84 + $view = $this->newHarbormasterMessageView($messages); 85 + if ($view) { 86 + $view->setPathURIMap($path_map); 87 + } 86 88 } else { 87 89 $view = null; 90 + } 91 + 92 + if ($view) { 93 + $view = phutil_tag( 94 + 'div', 95 + array( 96 + 'class' => 'differential-harbormaster-table-view', 97 + ), 98 + $view); 88 99 } 89 100 90 101 return array(
+1
src/applications/differential/customfield/DifferentialLintField.php
··· 50 50 51 51 protected function newHarbormasterMessageView(array $messages) { 52 52 return id(new HarbormasterLintPropertyView()) 53 + ->setLimit(25) 53 54 ->setLintMessages($messages); 54 55 } 55 56
+66 -2
src/applications/differential/customfield/DifferentialUnitField.php
··· 44 44 45 45 protected function loadHarbormasterTargetMessages(array $target_phids) { 46 46 return id(new HarbormasterBuildUnitMessage())->loadAllWhere( 47 - 'buildTargetPHID IN (%Ls) LIMIT 25', 47 + 'buildTargetPHID IN (%Ls)', 48 48 $target_phids); 49 49 } 50 50 ··· 55 55 } 56 56 57 57 protected function newHarbormasterMessageView(array $messages) { 58 + foreach ($messages as $key => $message) { 59 + if ($message->getResult() == ArcanistUnitTestResult::RESULT_PASS) { 60 + unset($messages[$key]); 61 + } 62 + } 63 + 64 + if (!$messages) { 65 + return null; 66 + } 67 + 58 68 return id(new HarbormasterUnitPropertyView()) 69 + ->setLimit(10) 70 + ->setHidePassingTests(true) 59 71 ->setUnitMessages($messages); 60 72 } 61 73 ··· 97 109 98 110 $message = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); 99 111 112 + $note = array(); 113 + 114 + $groups = mgroup($messages, 'getResult'); 115 + 116 + $groups = array_select_keys( 117 + $groups, 118 + array( 119 + ArcanistUnitTestResult::RESULT_FAIL, 120 + ArcanistUnitTestResult::RESULT_BROKEN, 121 + ArcanistUnitTestResult::RESULT_UNSOUND, 122 + ArcanistUnitTestResult::RESULT_SKIP, 123 + ArcanistUnitTestResult::RESULT_PASS, 124 + )) + $groups; 125 + 126 + foreach ($groups as $result => $group) { 127 + $count = new PhutilNumber(count($group)); 128 + switch ($result) { 129 + case ArcanistUnitTestResult::RESULT_PASS: 130 + $note[] = pht('%s Passed Test(s)', $count); 131 + break; 132 + case ArcanistUnitTestResult::RESULT_FAIL: 133 + $note[] = pht('%s Failed Test(s)', $count); 134 + break; 135 + case ArcanistUnitTestResult::RESULT_SKIP: 136 + $note[] = pht('%s Skipped Test(s)', $count); 137 + break; 138 + case ArcanistUnitTestResult::RESULT_BROKEN: 139 + $note[] = pht('%s Broken Test(s)', $count); 140 + break; 141 + case ArcanistUnitTestResult::RESULT_UNSOUND: 142 + $note[] = pht('%s Unsound Test(s)', $count); 143 + break; 144 + default: 145 + $note[] = pht('%s Other Test(s)', $count); 146 + break; 147 + } 148 + } 149 + 150 + $buildable = $diff->getBuildable(); 151 + if ($buildable) { 152 + $full_results = '/harbormaster/unit/'.$buildable->getID().'/'; 153 + $note[] = phutil_tag( 154 + 'a', 155 + array( 156 + 'href' => $full_results, 157 + ), 158 + pht('View Full Results')); 159 + } 160 + 100 161 $excuse = $diff->getProperty('arc:unit-excuse'); 101 162 if (strlen($excuse)) { 102 163 $excuse = array( ··· 104 165 ' ', 105 166 phutil_escape_html_newlines($excuse), 106 167 ); 168 + $note[] = $excuse; 107 169 } 108 170 171 + $note = phutil_implode_html(" \xC2\xB7 ", $note); 172 + 109 173 $status = id(new PHUIStatusListView()) 110 174 ->addItem( 111 175 id(new PHUIStatusItemView()) 112 176 ->setIcon(PHUIStatusItemView::ICON_STAR, $icon_color) 113 177 ->setTarget($message) 114 - ->setNote($excuse)); 178 + ->setNote($note)); 115 179 116 180 return $status; 117 181 }
+6
src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
··· 77 77 'run/(?P<id>\d+)/' => 'HarbormasterPlanRunController', 78 78 '(?P<id>\d+)/' => 'HarbormasterPlanViewController', 79 79 ), 80 + 'unit/' => array( 81 + '(?P<id>\d+)/' => 'HarbormasterUnitMessagesController', 82 + ), 83 + 'lint/' => array( 84 + '(?P<id>\d+)/' => 'HarbormasterLintMessagesController', 85 + ), 80 86 ), 81 87 ); 82 88 }
+33 -6
src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
··· 25 25 ->needBuildTargets(true) 26 26 ->execute(); 27 27 28 - list($lint, $unit) = $this->renderLintAndUnit($builds); 28 + list($lint, $unit) = $this->renderLintAndUnit($buildable, $builds); 29 29 30 30 $buildable->attachBuilds($builds); 31 31 $object = $buildable->getBuildableObject(); ··· 255 255 return $box; 256 256 } 257 257 258 - private function renderLintAndUnit(array $builds) { 258 + private function renderLintAndUnit( 259 + HarbormasterBuildable $buildable, 260 + array $builds) { 261 + 259 262 $viewer = $this->getViewer(); 260 263 261 264 $targets = array(); ··· 272 275 $target_phids = mpull($targets, 'getPHID'); 273 276 274 277 $lint_data = id(new HarbormasterBuildLintMessage())->loadAllWhere( 275 - 'buildTargetPHID IN (%Ls) LIMIT 25', 278 + 'buildTargetPHID IN (%Ls)', 276 279 $target_phids); 277 280 278 281 $unit_data = id(new HarbormasterBuildUnitMessage())->loadAllWhere( 279 - 'buildTargetPHID IN (%Ls) LIMIT 25', 282 + 'buildTargetPHID IN (%Ls)', 280 283 $target_phids); 281 284 282 285 if ($lint_data) { 283 286 $lint_table = id(new HarbormasterLintPropertyView()) 284 287 ->setUser($viewer) 288 + ->setLimit(10) 285 289 ->setLintMessages($lint_data); 286 290 291 + $lint_href = $this->getApplicationURI('lint/'.$buildable->getID().'/'); 292 + 293 + $lint_header = id(new PHUIHeaderView()) 294 + ->setHeader(pht('Lint Messages')) 295 + ->addActionLink( 296 + id(new PHUIButtonView()) 297 + ->setTag('a') 298 + ->setHref($lint_href) 299 + ->setIconFont('fa-list-ul') 300 + ->setText('View All')); 301 + 287 302 $lint = id(new PHUIObjectBoxView()) 288 - ->setHeaderText(pht('Lint Messages')) 303 + ->setHeader($lint_header) 289 304 ->appendChild($lint_table); 290 305 } else { 291 306 $lint = null; ··· 294 309 if ($unit_data) { 295 310 $unit_table = id(new HarbormasterUnitPropertyView()) 296 311 ->setUser($viewer) 312 + ->setLimit(25) 297 313 ->setUnitMessages($unit_data); 298 314 315 + $unit_href = $this->getApplicationURI('unit/'.$buildable->getID().'/'); 316 + 317 + $unit_header = id(new PHUIHeaderView()) 318 + ->setHeader(pht('Unit Tests')) 319 + ->addActionLink( 320 + id(new PHUIButtonView()) 321 + ->setTag('a') 322 + ->setHref($unit_href) 323 + ->setIconFont('fa-list-ul') 324 + ->setText('View All')); 325 + 299 326 $unit = id(new PHUIObjectBoxView()) 300 - ->setHeaderText(pht('Unit Tests')) 327 + ->setHeader($unit_header) 301 328 ->appendChild($unit_table); 302 329 } else { 303 330 $unit = null;
+64
src/applications/harbormaster/controller/HarbormasterLintMessagesController.php
··· 1 + <?php 2 + 3 + final class HarbormasterLintMessagesController 4 + extends HarbormasterController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + 9 + $buildable = id(new HarbormasterBuildableQuery()) 10 + ->setViewer($viewer) 11 + ->withIDs(array($request->getURIData('id'))) 12 + ->needBuilds(true) 13 + ->needTargets(true) 14 + ->executeOne(); 15 + if (!$buildable) { 16 + return new Aphront404Response(); 17 + } 18 + 19 + $id = $buildable->getID(); 20 + 21 + $target_phids = array(); 22 + foreach ($buildable->getBuilds() as $build) { 23 + foreach ($build->getBuildTargets() as $target) { 24 + $target_phids[] = $target->getPHID(); 25 + } 26 + } 27 + 28 + $lint_data = array(); 29 + if ($target_phids) { 30 + $lint_data = id(new HarbormasterBuildLintMessage())->loadAllWhere( 31 + 'buildTargetPHID IN (%Ls)', 32 + $target_phids); 33 + } else { 34 + $lint_data = array(); 35 + } 36 + 37 + $lint_table = id(new HarbormasterLintPropertyView()) 38 + ->setUser($viewer) 39 + ->setLintMessages($lint_data); 40 + 41 + $lint = id(new PHUIObjectBoxView()) 42 + ->setHeaderText(pht('Lint Messages')) 43 + ->appendChild($lint_table); 44 + 45 + $crumbs = $this->buildApplicationCrumbs(); 46 + $this->addBuildableCrumb($crumbs, $buildable); 47 + $crumbs->addTextCrumb(pht('Lint')); 48 + 49 + $title = array( 50 + $buildable->getMonogram(), 51 + pht('Lint'), 52 + ); 53 + 54 + return $this->buildApplicationPage( 55 + array( 56 + $crumbs, 57 + $lint, 58 + ), 59 + array( 60 + 'title' => $title, 61 + )); 62 + } 63 + 64 + }
+64
src/applications/harbormaster/controller/HarbormasterUnitMessagesController.php
··· 1 + <?php 2 + 3 + final class HarbormasterUnitMessagesController 4 + extends HarbormasterController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + 9 + $buildable = id(new HarbormasterBuildableQuery()) 10 + ->setViewer($viewer) 11 + ->withIDs(array($request->getURIData('id'))) 12 + ->needBuilds(true) 13 + ->needTargets(true) 14 + ->executeOne(); 15 + if (!$buildable) { 16 + return new Aphront404Response(); 17 + } 18 + 19 + $id = $buildable->getID(); 20 + 21 + $target_phids = array(); 22 + foreach ($buildable->getBuilds() as $build) { 23 + foreach ($build->getBuildTargets() as $target) { 24 + $target_phids[] = $target->getPHID(); 25 + } 26 + } 27 + 28 + $unit_data = array(); 29 + if ($target_phids) { 30 + $unit_data = id(new HarbormasterBuildUnitMessage())->loadAllWhere( 31 + 'buildTargetPHID IN (%Ls)', 32 + $target_phids); 33 + } else { 34 + $unit_data = array(); 35 + } 36 + 37 + $unit_table = id(new HarbormasterUnitPropertyView()) 38 + ->setUser($viewer) 39 + ->setUnitMessages($unit_data); 40 + 41 + $unit = id(new PHUIObjectBoxView()) 42 + ->setHeaderText(pht('Unit Tests')) 43 + ->appendChild($unit_table); 44 + 45 + $crumbs = $this->buildApplicationCrumbs(); 46 + $this->addBuildableCrumb($crumbs, $buildable); 47 + $crumbs->addTextCrumb(pht('Unit Tests')); 48 + 49 + $title = array( 50 + $buildable->getMonogram(), 51 + pht('Unit Tests'), 52 + ); 53 + 54 + return $this->buildApplicationPage( 55 + array( 56 + $crumbs, 57 + $unit, 58 + ), 59 + array( 60 + 'title' => $title, 61 + )); 62 + } 63 + 64 + }
+22
src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php
··· 95 95 return $this; 96 96 } 97 97 98 + public function getSortKey() { 99 + // TODO: Maybe use more numeric values after T6861. 100 + $map = array( 101 + ArcanistLintSeverity::SEVERITY_ERROR => 'A', 102 + ArcanistLintSeverity::SEVERITY_WARNING => 'B', 103 + ArcanistLintSeverity::SEVERITY_AUTOFIX => 'C', 104 + ArcanistLintSeverity::SEVERITY_ADVICE => 'Y', 105 + ArcanistLintSeverity::SEVERITY_DISABLED => 'Z', 106 + ); 107 + 108 + $severity = idx($map, $this->getSeverity(), 'N'); 109 + 110 + $parts = array( 111 + $severity, 112 + $this->getPath(), 113 + sprintf('%08d', $this->getLine()), 114 + $this->getCode(), 115 + ); 116 + 117 + return implode("\0", $parts); 118 + } 119 + 98 120 }
+22
src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
··· 97 97 return $this; 98 98 } 99 99 100 + public function getSortKey() { 101 + // TODO: Maybe use more numeric values after T6861. 102 + $map = array( 103 + ArcanistUnitTestResult::RESULT_FAIL => 'A', 104 + ArcanistUnitTestResult::RESULT_BROKEN => 'B', 105 + ArcanistUnitTestResult::RESULT_UNSOUND => 'C', 106 + ArcanistUnitTestResult::RESULT_PASS => 'Z', 107 + ); 108 + 109 + $result = idx($map, $this->getResult(), 'N'); 110 + 111 + $parts = array( 112 + $result, 113 + $this->getEngine(), 114 + $this->getNamespace(), 115 + $this->getName(), 116 + $this->getID(), 117 + ); 118 + 119 + return implode("\0", $parts); 120 + } 121 + 100 122 }
+17 -4
src/applications/harbormaster/view/HarbormasterLintPropertyView.php
··· 4 4 5 5 private $pathURIMap = array(); 6 6 private $lintMessages = array(); 7 + private $limit; 7 8 8 9 public function setPathURIMap(array $map) { 9 10 $this->pathURIMap = $map; ··· 16 17 return $this; 17 18 } 18 19 20 + public function setLimit($limit) { 21 + $this->limit = $limit; 22 + return $this; 23 + } 24 + 19 25 public function render() { 26 + $messages = $this->lintMessages; 27 + $messages = msort($messages, 'getSortKey'); 28 + 29 + if ($this->limit) { 30 + $messages = array_slice($messages, 0, $this->limit); 31 + } 32 + 20 33 $rows = array(); 21 - foreach ($this->lintMessages as $message) { 34 + foreach ($messages as $message) { 22 35 $path = $message->getPath(); 23 36 $line = $message->getLine(); 24 37 ··· 40 53 } 41 54 42 55 $rows[] = array( 43 - $location, 44 56 $severity, 57 + $location, 45 58 $message->getCode(), 46 59 $message->getName(), 47 60 ); ··· 50 63 $table = id(new AphrontTableView($rows)) 51 64 ->setHeaders( 52 65 array( 53 - pht('Location'), 54 66 pht('Severity'), 67 + pht('Location'), 55 68 pht('Code'), 56 69 pht('Message'), 57 70 )) 58 71 ->setColumnClasses( 59 72 array( 60 - 'pri', 61 73 null, 74 + 'pri', 62 75 null, 63 76 'wide', 64 77 ));
+13 -2
src/applications/harbormaster/view/HarbormasterUnitPropertyView.php
··· 4 4 5 5 private $pathURIMap = array(); 6 6 private $unitMessages = array(); 7 + private $limit; 7 8 8 9 public function setPathURIMap(array $map) { 9 10 $this->pathURIMap = $map; ··· 16 17 return $this; 17 18 } 18 19 20 + public function setLimit($limit) { 21 + $this->limit = $limit; 22 + return $this; 23 + } 24 + 19 25 public function render() { 26 + $messages = $this->unitMessages; 27 + $messages = msort($messages, 'getSortKey'); 28 + 29 + if ($this->limit) { 30 + $messages = array_slice($messages, 0, $this->limit); 31 + } 20 32 21 33 $rows = array(); 22 34 $any_duration = false; 23 - foreach ($this->unitMessages as $message) { 35 + foreach ($messages as $message) { 24 36 $result = $this->renderResult($message->getResult()); 25 37 26 38 $duration = $message->getDuration(); ··· 47 59 $name, 48 60 ); 49 61 } 50 - 51 62 52 63 $table = id(new AphrontTableView($rows)) 53 64 ->setHeaders(
+7
src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
··· 1170 1170 'This call takes %s parameters, but only %s are documented.', 1171 1171 ), 1172 1172 ), 1173 + 1174 + '%s Passed Test(s)' => '%s Passed', 1175 + '%s Failed Test(s)' => '%s Failed', 1176 + '%s Skipped Test(s)' => '%s Skipped', 1177 + '%s Broken Test(s)' => '%s Broken', 1178 + '%s Unsound Test(s)' => '%s Unsound', 1179 + '%s Other Test(s)' => '%s Other', 1173 1180 ); 1174 1181 } 1175 1182
+5
webroot/rsrc/css/application/differential/table-of-contents.css
··· 83 83 border-top: 1px solid {$thinblueborder}; 84 84 padding: 8px; 85 85 } 86 + 87 + .differential-harbormaster-table-view { 88 + margin: 4px 0; 89 + border: 1px solid {$thinblueborder}; 90 + }