protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $build_target_phid = $request->getValue('buildTargetPHID');
     $message_type = $request->getValue('type');
     $build_target = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->withPHIDs(array($build_target_phid))->executeOne();
     if (!$build_target) {
         throw new Exception(pht('No such build target!'));
     }
     $save = array();
     $lint_messages = $request->getValue('lint', array());
     foreach ($lint_messages as $lint) {
         $save[] = HarbormasterBuildLintMessage::newFromDictionary($build_target, $lint);
     }
     $unit_messages = $request->getValue('unit', array());
     foreach ($unit_messages as $unit) {
         $save[] = HarbormasterBuildUnitMessage::newFromDictionary($build_target, $unit);
     }
     $save[] = HarbormasterBuildMessage::initializeNewMessage($viewer)->setBuildTargetPHID($build_target->getPHID())->setType($message_type);
     $build_target->openTransaction();
     foreach ($save as $object) {
         $object->save();
     }
     $build_target->saveTransaction();
     // If the build has completely paused because all steps are blocked on
     // waiting targets, this will resume it.
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build_target->getBuild()->getID()));
     return null;
 }
 private function buildPropertyListView(HarbormasterBuildUnitMessage $message)
 {
     $viewer = $this->getViewer();
     $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.
         // Shenanigans below.
         $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;
 }
 protected function newModernMessage(array $message)
 {
     return HarbormasterBuildUnitMessage::newFromDictionary(new HarbormasterBuildTarget(), $this->getModernUnitMessageDictionary($message));
 }
 protected function loadHarbormasterData(array $diffs)
 {
     $viewer = $this->getViewer();
     $diffs = mpull($diffs, null, 'getPHID');
     $buildables = id(new HarbormasterBuildableQuery())->setViewer($viewer)->withBuildablePHIDs(array_keys($diffs))->withManualBuildables(false)->needBuilds(true)->needTargets(true)->execute();
     $buildables = mpull($buildables, null, 'getBuildablePHID');
     foreach ($diffs as $phid => $diff) {
         $diff->attachBuildable(idx($buildables, $phid));
     }
     $target_map = array();
     foreach ($diffs as $phid => $diff) {
         $target_map[$phid] = $diff->getBuildTargetPHIDs();
     }
     $all_target_phids = array_mergev($target_map);
     if ($all_target_phids) {
         $unit_messages = id(new HarbormasterBuildUnitMessage())->loadAllWhere('buildTargetPHID IN (%Ls)', $all_target_phids);
         $unit_messages = mgroup($unit_messages, 'getBuildTargetPHID');
     } else {
         $unit_messages = array();
     }
     foreach ($diffs as $phid => $diff) {
         $target_phids = idx($target_map, $phid, array());
         $messages = array_select_keys($unit_messages, $target_phids);
         $messages = array_mergev($messages);
         $diff->attachUnitMessages($messages);
     }
     // For diffs with no messages, look for legacy unit messages stored on the
     // diff itself.
     foreach ($diffs as $phid => $diff) {
         if ($diff->getUnitMessages()) {
             continue;
         }
         if (!$diff->hasDiffProperty('arc:unit')) {
             continue;
         }
         $legacy_messages = $diff->getProperty('arc:unit');
         if (!$legacy_messages) {
             continue;
         }
         // Show the top 100 legacy lint messages. Previously, we showed some
         // by default and let the user toggle the rest. With modern messages,
         // we can send the user to the Harbormaster detail page. Just show
         // "a lot" of messages in legacy cases to try to strike a balance
         // between implementation simplicitly and compatibility.
         $legacy_messages = array_slice($legacy_messages, 0, 100);
         $messages = array();
         foreach ($legacy_messages as $message) {
             $messages[] = HarbormasterBuildUnitMessage::newFromDictionary(new HarbormasterBuildTarget(), $this->getModernUnitMessageDictionary($message));
         }
         $diff->attachUnitMessages($messages);
     }
 }
 private function loadHistoryDiffStatus(array $diffs)
 {
     assert_instances_of($diffs, 'DifferentialDiff');
     $diff_phids = mpull($diffs, 'getPHID');
     $bad_unit_status = array(ArcanistUnitTestResult::RESULT_FAIL, ArcanistUnitTestResult::RESULT_BROKEN);
     $message = new HarbormasterBuildUnitMessage();
     $target = new HarbormasterBuildTarget();
     $build = new HarbormasterBuild();
     $buildable = new HarbormasterBuildable();
     $broken_diffs = queryfx_all($message->establishConnection('r'), 'SELECT distinct a.buildablePHID
     FROM %T m
       JOIN %T t ON m.buildTargetPHID = t.phid
       JOIN %T b ON t.buildPHID = b.phid
       JOIN %T a ON b.buildablePHID = a.phid
     WHERE a.buildablePHID IN (%Ls)
       AND m.result in (%Ls)', $message->getTableName(), $target->getTableName(), $build->getTableName(), $buildable->getTableName(), $diff_phids, $bad_unit_status);
     $unit_status = array();
     foreach ($broken_diffs as $broken) {
         $phid = $broken['buildablePHID'];
         $unit_status[$phid] = DifferentialUnitStatus::UNIT_FAIL;
     }
     return $unit_status;
 }