Path: blob/master/src/applications/harbormaster/storage/HarbormasterBuildable.php
12256 views
<?php12final class HarbormasterBuildable3extends HarbormasterDAO4implements5PhabricatorApplicationTransactionInterface,6PhabricatorPolicyInterface,7HarbormasterBuildableInterface,8PhabricatorConduitResultInterface,9PhabricatorDestructibleInterface {1011protected $buildablePHID;12protected $containerPHID;13protected $buildableStatus;14protected $isManualBuildable;1516private $buildableObject = self::ATTACHABLE;17private $containerObject = self::ATTACHABLE;18private $builds = self::ATTACHABLE;1920public static function initializeNewBuildable(PhabricatorUser $actor) {21return id(new HarbormasterBuildable())22->setIsManualBuildable(0)23->setBuildableStatus(HarbormasterBuildableStatus::STATUS_PREPARING);24}2526public function getMonogram() {27return 'B'.$this->getID();28}2930public function getURI() {31return '/'.$this->getMonogram();32}3334/**35* Returns an existing buildable for the object's PHID or creates a36* new buildable implicitly if needed.37*/38public static function createOrLoadExisting(39PhabricatorUser $actor,40$buildable_object_phid,41$container_object_phid) {4243$buildable = id(new HarbormasterBuildableQuery())44->setViewer($actor)45->withBuildablePHIDs(array($buildable_object_phid))46->withManualBuildables(false)47->setLimit(1)48->executeOne();49if ($buildable) {50return $buildable;51}52$buildable = self::initializeNewBuildable($actor)53->setBuildablePHID($buildable_object_phid)54->setContainerPHID($container_object_phid);55$buildable->save();56return $buildable;57}5859/**60* Start builds for a given buildable.61*62* @param phid PHID of the object to build.63* @param phid Container PHID for the buildable.64* @param list<HarbormasterBuildRequest> List of builds to perform.65* @return void66*/67public static function applyBuildPlans(68$phid,69$container_phid,70array $requests) {7172assert_instances_of($requests, 'HarbormasterBuildRequest');7374if (!$requests) {75return;76}7778// Skip all of this logic if the Harbormaster application79// isn't currently installed.8081$harbormaster_app = 'PhabricatorHarbormasterApplication';82if (!PhabricatorApplication::isClassInstalled($harbormaster_app)) {83return;84}8586$viewer = PhabricatorUser::getOmnipotentUser();8788$buildable = self::createOrLoadExisting(89$viewer,90$phid,91$container_phid);9293$plan_phids = mpull($requests, 'getBuildPlanPHID');94$plans = id(new HarbormasterBuildPlanQuery())95->setViewer($viewer)96->withPHIDs($plan_phids)97->execute();98$plans = mpull($plans, null, 'getPHID');99100foreach ($requests as $request) {101$plan_phid = $request->getBuildPlanPHID();102$plan = idx($plans, $plan_phid);103104if (!$plan) {105throw new Exception(106pht(107'Failed to load build plan ("%s").',108$plan_phid));109}110111if ($plan->isDisabled()) {112// TODO: This should be communicated more clearly -- maybe we should113// create the build but set the status to "disabled" or "derelict".114continue;115}116117$parameters = $request->getBuildParameters();118$buildable->applyPlan($plan, $parameters, $request->getInitiatorPHID());119}120}121122public function applyPlan(123HarbormasterBuildPlan $plan,124array $parameters,125$initiator_phid) {126127$viewer = PhabricatorUser::getOmnipotentUser();128$build = HarbormasterBuild::initializeNewBuild($viewer)129->setBuildablePHID($this->getPHID())130->setBuildPlanPHID($plan->getPHID())131->setBuildParameters($parameters)132->setBuildStatus(HarbormasterBuildStatus::STATUS_PENDING);133if ($initiator_phid) {134$build->setInitiatorPHID($initiator_phid);135}136137$auto_key = $plan->getPlanAutoKey();138if ($auto_key) {139$build->setPlanAutoKey($auto_key);140}141142$build->save();143144$steps = id(new HarbormasterBuildStepQuery())145->setViewer($viewer)146->withBuildPlanPHIDs(array($plan->getPHID()))147->execute();148149foreach ($steps as $step) {150$step->willStartBuild($viewer, $this, $build, $plan);151}152153PhabricatorWorker::scheduleTask(154'HarbormasterBuildWorker',155array(156'buildID' => $build->getID(),157),158array(159'objectPHID' => $build->getPHID(),160));161162return $build;163}164165protected function getConfiguration() {166return array(167self::CONFIG_AUX_PHID => true,168self::CONFIG_COLUMN_SCHEMA => array(169'containerPHID' => 'phid?',170'buildableStatus' => 'text32',171'isManualBuildable' => 'bool',172),173self::CONFIG_KEY_SCHEMA => array(174'key_buildable' => array(175'columns' => array('buildablePHID'),176),177'key_container' => array(178'columns' => array('containerPHID'),179),180'key_manual' => array(181'columns' => array('isManualBuildable'),182),183),184) + parent::getConfiguration();185}186187public function generatePHID() {188return PhabricatorPHID::generateNewPHID(189HarbormasterBuildablePHIDType::TYPECONST);190}191192public function attachBuildableObject($buildable_object) {193$this->buildableObject = $buildable_object;194return $this;195}196197public function getBuildableObject() {198return $this->assertAttached($this->buildableObject);199}200201public function attachContainerObject($container_object) {202$this->containerObject = $container_object;203return $this;204}205206public function getContainerObject() {207return $this->assertAttached($this->containerObject);208}209210public function attachBuilds(array $builds) {211assert_instances_of($builds, 'HarbormasterBuild');212$this->builds = $builds;213return $this;214}215216public function getBuilds() {217return $this->assertAttached($this->builds);218}219220221/* -( Status )------------------------------------------------------------- */222223224public function getBuildableStatusObject() {225$status = $this->getBuildableStatus();226return HarbormasterBuildableStatus::newBuildableStatusObject($status);227}228229public function getStatusIcon() {230return $this->getBuildableStatusObject()->getIcon();231}232233public function getStatusDisplayName() {234return $this->getBuildableStatusObject()->getDisplayName();235}236237public function getStatusColor() {238return $this->getBuildableStatusObject()->getColor();239}240241public function isPreparing() {242return $this->getBuildableStatusObject()->isPreparing();243}244245public function isBuilding() {246return $this->getBuildableStatusObject()->isBuilding();247}248249250/* -( Messages )----------------------------------------------------------- */251252253public function sendMessage(254PhabricatorUser $viewer,255$message_type,256$queue_update) {257258$message = HarbormasterBuildMessage::initializeNewMessage($viewer)259->setReceiverPHID($this->getPHID())260->setType($message_type)261->save();262263if ($queue_update) {264PhabricatorWorker::scheduleTask(265'HarbormasterBuildWorker',266array(267'buildablePHID' => $this->getPHID(),268),269array(270'objectPHID' => $this->getPHID(),271));272}273274return $message;275}276277278/* -( PhabricatorApplicationTransactionInterface )------------------------- */279280281public function getApplicationTransactionEditor() {282return new HarbormasterBuildableTransactionEditor();283}284285public function getApplicationTransactionTemplate() {286return new HarbormasterBuildableTransaction();287}288289290/* -( PhabricatorPolicyInterface )----------------------------------------- */291292293public function getCapabilities() {294return array(295PhabricatorPolicyCapability::CAN_VIEW,296PhabricatorPolicyCapability::CAN_EDIT,297);298}299300public function getPolicy($capability) {301return $this->getBuildableObject()->getPolicy($capability);302}303304public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {305return $this->getBuildableObject()->hasAutomaticCapability(306$capability,307$viewer);308}309310public function describeAutomaticCapability($capability) {311return pht('A buildable inherits policies from the underlying object.');312}313314315316/* -( HarbormasterBuildableInterface )------------------------------------- */317318319public function getHarbormasterBuildableDisplayPHID() {320return $this->getBuildableObject()->getHarbormasterBuildableDisplayPHID();321}322323public function getHarbormasterBuildablePHID() {324// NOTE: This is essentially just for convenience, as it allows you create325// a copy of a buildable by specifying `B123` without bothering to go326// look up the underlying object.327return $this->getBuildablePHID();328}329330public function getHarbormasterContainerPHID() {331return $this->getContainerPHID();332}333334public function getBuildVariables() {335return array();336}337338public function getAvailableBuildVariables() {339return array();340}341342public function newBuildableEngine() {343return $this->getBuildableObject()->newBuildableEngine();344}345346347/* -( PhabricatorConduitResultInterface )---------------------------------- */348349350public function getFieldSpecificationsForConduit() {351return array(352id(new PhabricatorConduitSearchFieldSpecification())353->setKey('objectPHID')354->setType('phid')355->setDescription(pht('PHID of the object that is built.')),356id(new PhabricatorConduitSearchFieldSpecification())357->setKey('containerPHID')358->setType('phid')359->setDescription(pht('PHID of the object containing this buildable.')),360id(new PhabricatorConduitSearchFieldSpecification())361->setKey('buildableStatus')362->setType('map<string, wild>')363->setDescription(pht('The current status of this buildable.')),364id(new PhabricatorConduitSearchFieldSpecification())365->setKey('isManual')366->setType('bool')367->setDescription(pht('True if this is a manual buildable.')),368id(new PhabricatorConduitSearchFieldSpecification())369->setKey('uri')370->setType('uri')371->setDescription(pht('View URI for the buildable.')),372);373}374375public function getFieldValuesForConduit() {376return array(377'objectPHID' => $this->getBuildablePHID(),378'containerPHID' => $this->getContainerPHID(),379'buildableStatus' => array(380'value' => $this->getBuildableStatus(),381),382'isManual' => (bool)$this->getIsManualBuildable(),383'uri' => PhabricatorEnv::getURI($this->getURI()),384);385}386387public function getConduitSearchAttachments() {388return array();389}390391392/* -( PhabricatorDestructibleInterface )----------------------------------- */393394395public function destroyObjectPermanently(396PhabricatorDestructionEngine $engine) {397$viewer = $engine->getViewer();398399$this->openTransaction();400$builds = id(new HarbormasterBuildQuery())401->setViewer($viewer)402->withBuildablePHIDs(array($this->getPHID()))403->execute();404foreach ($builds as $build) {405$engine->destroyObject($build);406}407408$messages = id(new HarbormasterBuildMessageQuery())409->setViewer($viewer)410->withReceiverPHIDs(array($this->getPHID()))411->execute();412foreach ($messages as $message) {413$engine->destroyObject($message);414}415416$this->delete();417$this->saveTransaction();418}419420}421422423