4 * Execute a build target.
6 final class HarbormasterTargetWorker
extends HarbormasterWorker
{
8 public function getRequiredLeaseTime() {
9 // This worker performs actual build work, which may involve a long wait
10 // on external systems.
11 return phutil_units('24 hours in seconds');
14 public function renderForDisplay(PhabricatorUser
$viewer) {
16 $target = $this->loadBuildTarget();
17 } catch (Exception
$ex) {
21 return $viewer->renderHandle($target->getPHID());
24 private function loadBuildTarget() {
25 $data = $this->getTaskData();
26 $id = idx($data, 'targetID');
28 $target = id(new HarbormasterBuildTargetQuery())
30 ->setViewer($this->getViewer())
31 ->needBuildSteps(true)
35 throw new PhabricatorWorkerPermanentFailureException(
37 'Bad build target ID "%d".',
44 protected function doWork() {
45 $target = $this->loadBuildTarget();
46 $build = $target->getBuild();
47 $viewer = $this->getViewer();
49 // If this is the first time we're starting work on this target, mark the
50 // current time as the start time. If the target yields or waits, we may
51 // end up here again later, so we don't want to overwrite the start time if
52 // we already have a value.
53 if (!$target->getDateStarted()) {
54 $target->setDateStarted(PhabricatorTime
::getNow());
58 if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
59 throw new HarbormasterBuildAbortedException();
62 $status_pending = HarbormasterBuildTarget
::STATUS_PENDING
;
63 if ($target->getTargetStatus() == $status_pending) {
64 $target->setTargetStatus(HarbormasterBuildTarget
::STATUS_BUILDING
);
68 $implementation = $target->getImplementation();
69 $implementation->setCurrentWorkerTaskID($this->getCurrentWorkerTaskID());
70 $implementation->execute($build, $target);
72 $next_status = HarbormasterBuildTarget
::STATUS_PASSED
;
73 if ($implementation->shouldWaitForMessage($target)) {
74 $next_status = HarbormasterBuildTarget
::STATUS_WAITING
;
77 $target->setTargetStatus($next_status);
79 if ($target->isComplete()) {
80 $target->setDateCompleted(PhabricatorTime
::getNow());
84 } catch (PhabricatorWorkerYieldException
$ex) {
85 // If the target wants to yield, let that escape without further
86 // processing. We'll resume after the task retries.
88 } catch (HarbormasterBuildFailureException
$ex) {
89 // A build step wants to fail explicitly.
90 $target->setTargetStatus(HarbormasterBuildTarget
::STATUS_FAILED
);
91 $target->setDateCompleted(PhabricatorTime
::getNow());
93 } catch (HarbormasterBuildAbortedException
$ex) {
94 // A build step is aborting because the build has been restarted.
95 $target->setTargetStatus(HarbormasterBuildTarget
::STATUS_ABORTED
);
96 $target->setDateCompleted(PhabricatorTime
::getNow());
98 } catch (Exception
$ex) {
100 $log = $target->newLog('core', 'exception')
103 } catch (Exception
$log_ex) {
107 $target->setTargetStatus(HarbormasterBuildTarget
::STATUS_FAILED
);
108 $target->setDateCompleted(time());
112 id(new HarbormasterBuildEngine())