/* Decoded by unphp.net */ forceBuildableUpdate = $force_buildable_update; return $this; } public function shouldForceBuildableUpdate() { return $this->forceBuildableUpdate; } public function queueNewBuildTarget(HarbormasterBuildTarget $target) { $this->newBuildTargets[] = $target; return $this; } public function getNewBuildTargets() { return $this->newBuildTargets; } public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } public function getViewer() { return $this->viewer; } public function setBuild(HarbormasterBuild $build) { $this->build = $build; return $this; } public function getBuild() { return $this->build; } public function continueBuild() { $viewer = $this->getViewer(); $build = $this->getBuild(); $lock_key = "harbormaster.build:" . $build->getID(); $lock = PhabricatorGlobalLock::newLock($lock_key)->lock(15); $build->reload(); $old_status = $build->getBuildStatus(); try { $this->updateBuild($build); } catch (Exception $ex) { $build->setBuildStatus(HarbormasterBuildStatus::STATUS_ERROR); $build->save(); $lock->unlock(); $build->releaseAllArtifacts($viewer); throw $ex; } $lock->unlock(); foreach ($this->getNewBuildTargets() as $target) { $task = PhabricatorWorker::scheduleTask("HarbormasterTargetWorker", array("targetID" => $target->getID()), array("objectPHID" => $target->getPHID())); } $new_status = $build->getBuildStatus(); if ($new_status != $old_status || $this->shouldForceBuildableUpdate()) { $this->updateBuildable($build->getBuildable()); } $this->releaseQueuedArtifacts(); if (!$build->isBuilding()) { $build->releaseAllArtifacts($viewer); } } private function updateBuild(HarbormasterBuild $build) { $viewer = $this->getViewer(); $content_source = PhabricatorContentSource::newForSource(PhabricatorDaemonContentSource::SOURCECONST); $acting_phid = $viewer->getPHID(); if (!$acting_phid) { $acting_phid = id(new PhabricatorHarbormasterApplication())->getPHID(); } $editor = $build->getApplicationTransactionEditor()->setActor($viewer)->setActingAsPHID($acting_phid)->setContentSource($content_source)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); $messages = $build->getUnprocessedMessagesForApply(); foreach ($messages as $message) { $message_type = $message->getType(); $message_xaction = HarbormasterBuildMessageTransaction::getTransactionTypeForMessageType($message_type); if (!$message_xaction) { continue; } $xactions[] = $build->getApplicationTransactionTemplate()->setAuthorPHID($message->getAuthorPHID())->setTransactionType($message_xaction)->setNewValue($message_type); } if (!$xactions) { if ($build->isPending()) { $build->restartBuild($viewer); $build->setBuildStatus(HarbormasterBuildStatus::STATUS_BUILDING); $build->save(); } } if ($xactions) { $editor->applyTransactions($build, $xactions); $build->markUnprocessedMessagesAsProcessed(); } if ($build->getBuildStatus() == HarbormasterBuildStatus::STATUS_BUILDING) { $this->updateBuildSteps($build); } } private function updateBuildSteps(HarbormasterBuild $build) { $all_targets = id(new HarbormasterBuildTargetQuery())->setViewer($this->getViewer())->withBuildPHIDs(array($build->getPHID()))->withBuildGenerations(array($build->getBuildGeneration()))->execute(); $this->updateWaitingTargets($all_targets); $targets = mgroup($all_targets, "getBuildStepPHID"); $steps = id(new HarbormasterBuildStepQuery())->setViewer($this->getViewer())->withBuildPlanPHIDs(array($build->getBuildPlan()->getPHID()))->execute(); $steps = mpull($steps, null, "getPHID"); $queued = array(); $underway = array(); $waiting = array(); $complete = array(); $failed = array(); foreach ($steps as $step) { $step_targets = idx($targets, $step->getPHID(), array()); if ($step_targets) { $is_queued = false; $is_underway = false; foreach ($step_targets as $target) { if ($target->isUnderway()) { $is_underway = true; break; } } $is_waiting = false; foreach ($step_targets as $target) { if ($target->isWaiting()) { $is_waiting = true; break; } } $is_complete = true; foreach ($step_targets as $target) { if (!$target->isComplete()) { $is_complete = false; break; } } $is_failed = false; foreach ($step_targets as $target) { if ($target->isFailed()) { $is_failed = true; break; } } } else { $is_queued = true; $is_underway = false; $is_waiting = false; $is_complete = false; $is_failed = false; } if ($is_queued) { $queued[$step->getPHID()] = true; } if ($is_underway) { $underway[$step->getPHID()] = true; } if ($is_waiting) { $waiting[$step->getPHID()] = true; } if ($is_complete) { $complete[$step->getPHID()] = true; } if ($is_failed) { $failed[$step->getPHID()] = true; } } if (count($failed)) { $build->setBuildStatus(HarbormasterBuildStatus::STATUS_FAILED); $build->save(); return; } if (count($complete) == count($steps)) { $build->setBuildStatus(HarbormasterBuildStatus::STATUS_PASSED); $build->save(); return; } $ongoing_phids = array_keys($queued + $waiting + $underway); $ongoing_steps = array_select_keys($steps, $ongoing_phids); $this->releaseUnusedArtifacts($all_targets, $ongoing_steps); $runnable = array(); foreach ($steps as $step) { $dependencies = $step->getStepImplementation()->getDependencies($step); if (isset($queued[$step->getPHID()])) { $can_run = true; foreach ($dependencies as $dependency) { if (empty($complete[$dependency])) { $can_run = false; break; } } if ($can_run) { $runnable[] = $step; } } } if (!$runnable && !$waiting && !$underway) { $build->setBuildStatus(HarbormasterBuildStatus::STATUS_DEADLOCKED); $build->save(); return; } foreach ($runnable as $runnable_step) { $target = HarbormasterBuildTarget::initializeNewBuildTarget($build, $runnable_step, $build->retrieveVariablesFromBuild()); $target->save(); $this->queueNewBuildTarget($target); } } private function releaseUnusedArtifacts(array $targets, array $steps) { assert_instances_of($targets, "HarbormasterBuildTarget"); assert_instances_of($steps, "HarbormasterBuildStep"); if (!$targets || !$steps) { return; } $target_phids = mpull($targets, "getPHID"); $artifacts = id(new HarbormasterBuildArtifactQuery())->setViewer($this->getViewer())->withBuildTargetPHIDs($target_phids)->withIsReleased(false)->execute(); if (!$artifacts) { return; } $must_keep = array(); foreach ($steps as $step) { $inputs = $step->getStepImplementation()->getArtifactInputs(); foreach ($inputs as $input) { $artifact_key = $input["key"]; $must_keep[$artifact_key] = true; } } foreach ($artifacts as $artifact) { $key = $artifact->getArtifactKey(); if (isset($must_keep[$key])) { continue; } $this->artifactReleaseQueue[] = $artifact; } } private function updateWaitingTargets(array $targets) { assert_instances_of($targets, "HarbormasterBuildTarget"); $waiting_targets = array(); foreach ($targets as $target) { if ($target->isWaiting()) { $waiting_targets[$target->getPHID()] = $target; } } if (!$waiting_targets) { return; } $messages = id(new HarbormasterBuildMessageQuery())->setViewer($this->getViewer())->withReceiverPHIDs(array_keys($waiting_targets))->withConsumed(false)->execute(); foreach ($messages as $message) { $target = $waiting_targets[$message->getReceiverPHID()]; switch ($message->getType()) { case HarbormasterMessageType::MESSAGE_PASS: $new_status = HarbormasterBuildTarget::STATUS_PASSED; break; case HarbormasterMessageType::MESSAGE_FAIL: $new_status = HarbormasterBuildTarget::STATUS_FAILED; break; case HarbormasterMessageType::MESSAGE_WORK: default: $new_status = null; break; } if ($new_status !== null) { $message->setIsConsumed(true); $message->save(); $target->setTargetStatus($new_status); if ($target->isComplete()) { $target->setDateCompleted(PhabricatorTime::getNow()); } $target->save(); } } } public function updateBuildable(HarbormasterBuildable $buildable) { $viewer = $this->getViewer(); $lock_key = "harbormaster.buildable:" . $buildable->getID(); $lock = PhabricatorGlobalLock::newLock($lock_key)->lock(15); $buildable = id(new HarbormasterBuildableQuery())->setViewer($viewer)->withIDs(array($buildable->getID()))->needBuilds(true)->executeOne(); $messages = id(new HarbormasterBuildMessageQuery())->setViewer($viewer)->withReceiverPHIDs(array($buildable->getPHID()))->withConsumed(false)->execute(); $done_preparing = false; $update_container = false; foreach ($messages as $message) { switch ($message->getType()) { case HarbormasterMessageType::BUILDABLE_BUILD: $done_preparing = true; break; case HarbormasterMessageType::BUILDABLE_CONTAINER: $update_container = true; break; default: break; } $message->setIsConsumed(true)->save(); } if ($done_preparing) { if ($buildable->isPreparing()) { $buildable->setBuildableStatus(HarbormasterBuildableStatus::STATUS_BUILDING)->save(); } } if ($update_container) { $object = id(new PhabricatorObjectQuery())->setViewer($viewer)->withPHIDs(array($buildable->getBuildablePHID()))->executeOne(); if ($object) { $buildable->setContainerPHID($object->getHarbormasterContainerPHID())->save(); } } $old = clone $buildable; if (!$buildable->isPreparing()) { $behavior_key = HarbormasterBuildPlanBehavior::BEHAVIOR_BUILDABLE; $behavior = HarbormasterBuildPlanBehavior::getBehavior($behavior_key); $key_never = HarbormasterBuildPlanBehavior::BUILDABLE_NEVER; $key_building = HarbormasterBuildPlanBehavior::BUILDABLE_IF_BUILDING; $all_pass = true; $any_fail = false; foreach ($buildable->getBuilds() as $build) { $plan = $build->getBuildPlan(); $option = $behavior->getPlanOption($plan); $option_key = $option->getKey(); $is_never = $option_key === $key_never; $is_building = $option_key === $key_building; if ($is_never) { continue; } if ($is_building && $build->isComplete()) { continue; } if (!$build->isPassed()) { $all_pass = false; } if ($build->isComplete() && !$build->isPassed()) { $any_fail = true; } } if ($any_fail) { $new_status = HarbormasterBuildableStatus::STATUS_FAILED; } else { if ($all_pass) { $new_status = HarbormasterBuildableStatus::STATUS_PASSED; } else { $new_status = HarbormasterBuildableStatus::STATUS_BUILDING; } } $did_update = $old->getBuildableStatus() !== $new_status; if ($did_update) { $buildable->setBuildableStatus($new_status); $buildable->save(); } } $lock->unlock(); if ($buildable->isPreparing()) { return; } $this->publishBuildable($old, $buildable); } public function publishBuildable(HarbormasterBuildable $old, HarbormasterBuildable $new) { $viewer = $this->getViewer(); $object = id(new PhabricatorObjectQuery())->setViewer($viewer)->withPHIDs(array($new->getBuildablePHID()))->executeOne(); if (!$object) { return; } $engine = HarbormasterBuildableEngine::newForObject($object, $viewer); $daemon_source = PhabricatorContentSource::newForSource(PhabricatorDaemonContentSource::SOURCECONST); $harbormaster_phid = id(new PhabricatorHarbormasterApplication())->getPHID(); $engine->setActingAsPHID($harbormaster_phid)->setContentSource($daemon_source)->publishBuildable($old, $new); } private function releaseQueuedArtifacts() { foreach ($this->artifactReleaseQueue as $key => $artifact) { $artifact->releaseArtifact(); unset($this->artifactReleaseQueue[$key]); } } } ?>