public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $id = $this->id;
     $generation = $request->getInt('g');
     $build = id(new HarbormasterBuildQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$build) {
         return new Aphront404Response();
     }
     require_celerity_resource('harbormaster-css');
     $title = pht('Build %d', $id);
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($build);
     if ($build->isRestarting()) {
         $header->setStatus('fa-exclamation-triangle', 'red', pht('Restarting'));
     } else {
         if ($build->isStopping()) {
             $header->setStatus('fa-exclamation-triangle', 'red', pht('Pausing'));
         } else {
             if ($build->isResuming()) {
                 $header->setStatus('fa-exclamation-triangle', 'red', pht('Resuming'));
             }
         }
     }
     $box = id(new PHUIObjectBoxView())->setHeader($header);
     $actions = $this->buildActionList($build);
     $this->buildPropertyLists($box, $build, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($build->getBuildable()->getMonogram(), '/' . $build->getBuildable()->getMonogram());
     $crumbs->addTextCrumb($title);
     if ($generation === null || $generation > $build->getBuildGeneration() || $generation < 0) {
         $generation = $build->getBuildGeneration();
     }
     $build_targets = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->needBuildSteps(true)->withBuildPHIDs(array($build->getPHID()))->withBuildGenerations(array($generation))->execute();
     if ($build_targets) {
         $messages = id(new HarbormasterBuildMessageQuery())->setViewer($viewer)->withBuildTargetPHIDs(mpull($build_targets, 'getPHID'))->execute();
         $messages = mgroup($messages, 'getBuildTargetPHID');
     } else {
         $messages = array();
     }
     $targets = array();
     foreach ($build_targets as $build_target) {
         $header = id(new PHUIHeaderView())->setHeader($build_target->getName())->setUser($viewer);
         $target_box = id(new PHUIObjectBoxView())->setHeader($header);
         $properties = new PHUIPropertyListView();
         $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());
         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()));
             }
         }
         $properties->addProperty(pht('Status'), $status_view);
         $target_box->addPropertyList($properties, pht('Overview'));
         $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.')));
         }
         $details = $build_target->getDetails();
         if ($details) {
             $properties = new PHUIPropertyListView();
             foreach ($details as $key => $value) {
                 $properties->addProperty($key, $value);
             }
             $target_box->addPropertyList($properties, pht('Configuration'));
         }
         $variables = $build_target->getVariables();
         if ($variables) {
             $properties = new PHUIPropertyListView();
             foreach ($variables as $key => $value) {
                 $properties->addProperty($key, $value);
             }
             $target_box->addPropertyList($properties, pht('Variables'));
         }
         $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'));
         }
         $properties = new PHUIPropertyListView();
         $properties->addProperty('Build Target ID', $build_target->getID());
         $target_box->addPropertyList($properties, pht('Metadata'));
         $targets[] = $target_box;
         $targets[] = $this->buildLog($build, $build_target);
     }
     $xactions = id(new HarbormasterBuildTransactionQuery())->setViewer($viewer)->withObjectPHIDs(array($build->getPHID()))->execute();
     $timeline = id(new PhabricatorApplicationTransactionView())->setUser($viewer)->setObjectPHID($build->getPHID())->setTransactions($xactions);
     return $this->buildApplicationPage(array($crumbs, $box, $targets, $timeline), array('title' => $title));
 }
 private function buildBuildList(HarbormasterBuildable $buildable)
 {
     $viewer = $this->getRequest()->getUser();
     $build_list = id(new PHUIObjectItemListView())->setUser($viewer);
     foreach ($buildable->getBuilds() as $build) {
         $view_uri = $this->getApplicationURI('/build/' . $build->getID() . '/');
         $item = id(new PHUIObjectItemView())->setObjectName(pht('Build %d', $build->getID()))->setHeader($build->getName())->setHref($view_uri);
         $status = $build->getBuildStatus();
         $item->setStatusIcon('fa-dot-circle-o ' . HarbormasterBuild::getBuildStatusColor($status), HarbormasterBuild::getBuildStatusName($status));
         $item->addAttribute(HarbormasterBuild::getBuildStatusName($status));
         if ($build->isRestarting()) {
             $item->addIcon('fa-repeat', pht('Restarting'));
         } else {
             if ($build->isPausing()) {
                 $item->addIcon('fa-pause', pht('Pausing'));
             } else {
                 if ($build->isResuming()) {
                     $item->addIcon('fa-play', pht('Resuming'));
                 }
             }
         }
         $build_id = $build->getID();
         $restart_uri = "build/restart/{$build_id}/buildable/";
         $resume_uri = "build/resume/{$build_id}/buildable/";
         $pause_uri = "build/pause/{$build_id}/buildable/";
         $abort_uri = "build/abort/{$build_id}/buildable/";
         $item->addAction(id(new PHUIListItemView())->setIcon('fa-repeat')->setName(pht('Restart'))->setHref($this->getApplicationURI($restart_uri))->setWorkflow(true)->setDisabled(!$build->canRestartBuild()));
         if ($build->canResumeBuild()) {
             $item->addAction(id(new PHUIListItemView())->setIcon('fa-play')->setName(pht('Resume'))->setHref($this->getApplicationURI($resume_uri))->setWorkflow(true));
         } else {
             $item->addAction(id(new PHUIListItemView())->setIcon('fa-pause')->setName(pht('Pause'))->setHref($this->getApplicationURI($pause_uri))->setWorkflow(true)->setDisabled(!$build->canPauseBuild()));
         }
         $targets = $build->getBuildTargets();
         if ($targets) {
             $target_list = id(new PHUIStatusListView());
             foreach ($targets as $target) {
                 $status = $target->getTargetStatus();
                 $icon = HarbormasterBuildTarget::getBuildTargetStatusIcon($status);
                 $color = HarbormasterBuildTarget::getBuildTargetStatusColor($status);
                 $status_name = HarbormasterBuildTarget::getBuildTargetStatusName($status);
                 $name = $target->getName();
                 $target_list->addItem(id(new PHUIStatusItemView())->setIcon($icon, $color, $status_name)->setTarget(pht('Target %d', $target->getID()))->setNote($name));
             }
             $target_box = id(new PHUIBoxView())->addPadding(PHUI::PADDING_SMALL)->appendChild($target_list);
             $item->appendChild($target_box);
         }
         $build_list->addItem($item);
     }
     $build_list->setFlush(true);
     $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Builds'))->appendChild($build_list);
     return $box;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $id = $request->getURIData('id');
     $generation = $request->getInt('g');
     $build = id(new HarbormasterBuildQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$build) {
         return new Aphront404Response();
     }
     require_celerity_resource('harbormaster-css');
     $title = pht('Build %d', $id);
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($build);
     if ($build->isRestarting()) {
         $header->setStatus('fa-exclamation-triangle', 'red', pht('Restarting'));
     } else {
         if ($build->isPausing()) {
             $header->setStatus('fa-exclamation-triangle', 'red', pht('Pausing'));
         } else {
             if ($build->isResuming()) {
                 $header->setStatus('fa-exclamation-triangle', 'red', pht('Resuming'));
             } else {
                 if ($build->isAborting()) {
                     $header->setStatus('fa-exclamation-triangle', 'red', pht('Aborting'));
                 }
             }
         }
     }
     $box = id(new PHUIObjectBoxView())->setHeader($header);
     $actions = $this->buildActionList($build);
     $this->buildPropertyLists($box, $build, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $this->addBuildableCrumb($crumbs, $build->getBuildable());
     $crumbs->addTextCrumb($title);
     if ($generation === null || $generation > $build->getBuildGeneration() || $generation < 0) {
         $generation = $build->getBuildGeneration();
     }
     $build_targets = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->needBuildSteps(true)->withBuildPHIDs(array($build->getPHID()))->withBuildGenerations(array($generation))->execute();
     if ($build_targets) {
         $messages = id(new HarbormasterBuildMessageQuery())->setViewer($viewer)->withBuildTargetPHIDs(mpull($build_targets, 'getPHID'))->execute();
         $messages = mgroup($messages, 'getBuildTargetPHID');
     } else {
         $messages = array();
     }
     if ($build_targets) {
         $artifacts = id(new HarbormasterBuildArtifactQuery())->setViewer($viewer)->withBuildTargetPHIDs(mpull($build_targets, 'getPHID'))->execute();
         $artifacts = msort($artifacts, 'getArtifactKey');
         $artifacts = mgroup($artifacts, 'getBuildTargetPHID');
     } else {
         $artifacts = array();
     }
     $targets = array();
     foreach ($build_targets as $build_target) {
         $header = id(new PHUIHeaderView())->setHeader($build_target->getName())->setUser($viewer);
         $target_box = id(new PHUIObjectBoxView())->setHeader($header);
         $properties = new PHUIPropertyListView();
         $target_artifacts = idx($artifacts, $build_target->getPHID(), array());
         $links = array();
         $type_uri = HarbormasterURIArtifact::ARTIFACTCONST;
         foreach ($target_artifacts as $artifact) {
             if ($artifact->getArtifactType() == $type_uri) {
                 $impl = $artifact->getArtifactImplementation();
                 if ($impl->isExternalLink()) {
                     $links[] = $impl->renderLink();
                 }
             }
         }
         if ($links) {
             $links = phutil_implode_html(phutil_tag('br'), $links);
             $properties->addProperty(pht('External Link'), $links);
         }
         $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);
         $when = array();
         $started = $build_target->getDateStarted();
         $now = PhabricatorTime::getNow();
         if ($started) {
             $ended = $build_target->getDateCompleted();
             if ($ended) {
                 $when[] = pht('Completed at %s', phabricator_datetime($started, $viewer));
                 $duration = $ended - $started;
                 if ($duration) {
                     $when[] = pht('Built for %s', phutil_format_relative_time_detailed($duration));
                 } else {
                     $when[] = pht('Built instantly');
                 }
             } else {
                 $when[] = pht('Started at %s', phabricator_datetime($started, $viewer));
                 $duration = $now - $started;
                 if ($duration) {
                     $when[] = pht('Running for %s', phutil_format_relative_time_detailed($duration));
                 }
             }
         } else {
             $created = $build_target->getDateCreated();
             $when[] = pht('Queued at %s', phabricator_datetime($started, $viewer));
             $duration = $now - $created;
             if ($duration) {
                 $when[] = pht('Waiting for %s', phutil_format_relative_time_detailed($duration));
             }
         }
         $properties->addProperty(pht('When'), phutil_implode_html(" · ", $when));
         $properties->addProperty(pht('Status'), $status_view);
         $target_box->addPropertyList($properties, pht('Overview'));
         $step = $build_target->getBuildStep();
         if ($step) {
             $description = $step->getDescription();
             if ($description) {
                 $description = new PHUIRemarkupView($viewer, $description);
                 $properties->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
                 $properties->addTextContent($description);
             }
         } else {
             $target_box->setFormErrors(array(pht('This build step has since been deleted on the build plan.  ' . 'Some information may be omitted.')));
         }
         $details = $build_target->getDetails();
         $properties = new PHUIPropertyListView();
         foreach ($details as $key => $value) {
             $properties->addProperty($key, $value);
         }
         $target_box->addPropertyList($properties, pht('Configuration'));
         $variables = $build_target->getVariables();
         $properties = new PHUIPropertyListView();
         $properties->addRawContent($this->buildProperties($variables));
         $target_box->addPropertyList($properties, pht('Variables'));
         $artifacts_tab = $this->buildArtifacts($build_target, $target_artifacts);
         $properties = new PHUIPropertyListView();
         $properties->addRawContent($artifacts_tab);
         $target_box->addPropertyList($properties, pht('Artifacts'));
         $build_messages = idx($messages, $build_target->getPHID(), array());
         $properties = new PHUIPropertyListView();
         $properties->addRawContent($this->buildMessages($build_messages));
         $target_box->addPropertyList($properties, pht('Messages'));
         $properties = new PHUIPropertyListView();
         $properties->addProperty(pht('Build Target ID'), $build_target->getID());
         $properties->addProperty(pht('Build Target PHID'), $build_target->getPHID());
         $target_box->addPropertyList($properties, pht('Metadata'));
         $targets[] = $target_box;
         $targets[] = $this->buildLog($build, $build_target);
     }
     $timeline = $this->buildTransactionTimeline($build, new HarbormasterBuildTransactionQuery());
     $timeline->setShouldTerminate(true);
     return $this->buildApplicationPage(array($crumbs, $box, $targets, $timeline), array('title' => $title));
 }