@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add build step implementation infrastructure and sleep build step.

Summary:
Depends on D7498.

This implements support for a "build step implementation". Build steps have an associated class name (which makes the class in PHP) and a details field, which is serialized JSON (same as PhabricatorRepository).

This also implements a SleepBuildStepImplementation which just pauses the build for a specified period of seconds.

Test Plan:
Inserted a build step with `insert into harbormaster_buildstep (phid, buildPlanPHID, className, details, dateCreated, dateModified) values ('', 'PHID-HMCP-zkh5w6czfbfpk2gxwdeo', 'SleepBuildStepImplementation', '{"seconds":5}', NOW(), NOW());` (adjusting the build plan PHID as appropriate).

Started the daemon and applied the build plan to a buildable, and saw the daemon take a 5 second delay after creating `SleepBuildStepImplementation`.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley

CC: Korvin, epriestley, aran, chad

Maniphest Tasks: T1049

Differential Revision: https://secure.phabricator.com/D7499

authored by

James Rhodes and committed by
epriestley
c514d34b 5c0edc93

+201 -6
+11
resources/sql/patches/20131105.buildstep.sql
··· 1 + CREATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildstep ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, 4 + buildPlanPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 5 + className VARCHAR(255) NOT NULL COLLATE utf8_bin, 6 + details LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 7 + dateCreated INT UNSIGNED NOT NULL, 8 + dateModified INT UNSIGNED NOT NULL, 9 + KEY `key_plan` (buildPlanPHID), 10 + UNIQUE KEY `key_phid` (phid) 11 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+8 -1
src/__phutil_library_map__.php
··· 91 91 'AphrontView' => 'view/AphrontView.php', 92 92 'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', 93 93 'AuditActionMenuEventListener' => 'applications/audit/events/AuditActionMenuEventListener.php', 94 + 'BuildStepImplementation' => 'applications/harbormaster/step/BuildStepImplementation.php', 94 95 'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php', 95 96 'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php', 96 97 'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php', ··· 2195 2196 'ReleephStatusFieldSpecification' => 'applications/releeph/field/specification/ReleephStatusFieldSpecification.php', 2196 2197 'ReleephSummaryFieldSpecification' => 'applications/releeph/field/specification/ReleephSummaryFieldSpecification.php', 2197 2198 'ReleephUserView' => 'applications/releeph/view/user/ReleephUserView.php', 2199 + 'SleepBuildStepImplementation' => 'applications/harbormaster/step/SleepBuildStepImplementation.php', 2198 2200 'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php', 2199 2201 'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php', 2200 2202 ), ··· 2872 2874 'HarbormasterBuildPlanTransactionComment' => 'PhabricatorApplicationTransactionComment', 2873 2875 'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 2874 2876 'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2875 - 'HarbormasterBuildStep' => 'HarbormasterDAO', 2877 + 'HarbormasterBuildStep' => 2878 + array( 2879 + 0 => 'HarbormasterDAO', 2880 + 1 => 'PhabricatorPolicyInterface', 2881 + ), 2876 2882 'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2877 2883 'HarbormasterBuildTarget' => 'HarbormasterDAO', 2878 2884 'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', ··· 4651 4657 'ReleephStatusFieldSpecification' => 'ReleephFieldSpecification', 4652 4658 'ReleephSummaryFieldSpecification' => 'ReleephFieldSpecification', 4653 4659 'ReleephUserView' => 'AphrontView', 4660 + 'SleepBuildStepImplementation' => 'BuildStepImplementation', 4654 4661 'SlowvoteEmbedView' => 'AphrontView', 4655 4662 'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject', 4656 4663 ),
+38
src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
··· 5 5 6 6 private $ids; 7 7 private $phids; 8 + private $buildPlanPHIDs; 8 9 9 10 public function withIDs(array $ids) { 10 11 $this->ids = $ids; ··· 13 14 14 15 public function withPHIDs(array $phids) { 15 16 $this->phids = $phids; 17 + return $this; 18 + } 19 + 20 + public function withBuildPlanPHIDs(array $phids) { 21 + $this->buildPlanPHIDs = $phids; 16 22 return $this; 17 23 } 18 24 ··· 48 54 $this->phids); 49 55 } 50 56 57 + if ($this->buildPlanPHIDs) { 58 + $where[] = qsprintf( 59 + $conn_r, 60 + 'buildPlanPHID in (%Ls)', 61 + $this->buildPlanPHIDs); 62 + } 63 + 51 64 $where[] = $this->buildPagingClause($conn_r); 52 65 53 66 return $this->formatWhereClause($where); 67 + } 68 + 69 + protected function willFilterPage(array $page) { 70 + $plans = array(); 71 + 72 + $buildplan_phids = array_filter(mpull($page, 'getBuildPlanPHID')); 73 + if ($buildplan_phids) { 74 + $plans = id(new PhabricatorObjectQuery()) 75 + ->setViewer($this->getViewer()) 76 + ->withPHIDs($buildplan_phids) 77 + ->setParentQuery($this) 78 + ->execute(); 79 + $plans = mpull($plans, null, 'getPHID'); 80 + } 81 + 82 + foreach ($page as $key => $build) { 83 + $buildable_phid = $build->getBuildPlanPHID(); 84 + if (empty($plans[$buildable_phid])) { 85 + unset($page[$key]); 86 + continue; 87 + } 88 + $build->attachBuildPlan($plans[$buildable_phid]); 89 + } 90 + 91 + return $page; 54 92 } 55 93 56 94 public function getQueryApplicationClass() {
+48
src/applications/harbormaster/step/BuildStepImplementation.php
··· 1 + <?php 2 + 3 + abstract class BuildStepImplementation { 4 + 5 + private $settings; 6 + 7 + /** 8 + * The name of the implementation. 9 + */ 10 + abstract public function getName(); 11 + 12 + /** 13 + * The description of the implementation. 14 + */ 15 + public function getDescription() { 16 + return ''; 17 + } 18 + 19 + /** 20 + * Run the build step against the specified build. 21 + */ 22 + abstract public function execute(HarbormasterBuild $build); 23 + 24 + /** 25 + * Gets the settings for this build step. 26 + */ 27 + protected function getSettings() { 28 + return $this->settings; 29 + } 30 + 31 + /** 32 + * Loads the settings for this build step implementation from the build step. 33 + */ 34 + public final function loadSettings(HarbormasterBuildStep $build_step) { 35 + $this->settings = array(); 36 + foreach ($this->getSettingDefinitions() as $name => $opt) { 37 + $this->settings[$name] = $build_step->getDetail($name); 38 + } 39 + return $this->settings; 40 + } 41 + 42 + /** 43 + * Return an array of settings for this step implementation. 44 + */ 45 + public function getSettingDefinitions() { 46 + return array(); 47 + } 48 + }
+24
src/applications/harbormaster/step/SleepBuildStepImplementation.php
··· 1 + <?php 2 + 3 + final class SleepBuildStepImplementation extends BuildStepImplementation { 4 + 5 + public function getName() { 6 + return pht('Sleep'); 7 + } 8 + 9 + public function getDescription() { 10 + return pht('Sleep for a specified number of seconds.'); 11 + } 12 + 13 + public function execute(HarbormasterBuild $build) { 14 + $settings = $this->getSettings(); 15 + 16 + sleep($settings['seconds']); 17 + } 18 + 19 + public function getSettingDefinitions() { 20 + return array( 21 + 'seconds' => array()); 22 + } 23 + 24 + }
+50 -1
src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php
··· 1 1 <?php 2 2 3 - final class HarbormasterBuildStep extends HarbormasterDAO { 3 + final class HarbormasterBuildStep extends HarbormasterDAO 4 + implements PhabricatorPolicyInterface { 4 5 5 6 protected $buildPlanPHID; 7 + protected $className; 8 + protected $details = array(); 6 9 7 10 private $buildPlan = self::ATTACHABLE; 8 11 9 12 public function getConfiguration() { 10 13 return array( 11 14 self::CONFIG_AUX_PHID => true, 15 + self::CONFIG_SERIALIZATION => array( 16 + 'details' => self::SERIALIZATION_JSON, 17 + ) 12 18 ) + parent::getConfiguration(); 13 19 } 14 20 ··· 26 32 return $this->assertAttached($this->buildPlan); 27 33 } 28 34 35 + public function getDetail($key, $default = null) { 36 + return idx($this->details, $key, $default); 37 + } 38 + 39 + public function setDetail($key, $value) { 40 + $this->details[$key] = $value; 41 + return $this; 42 + } 43 + 44 + public function getStepImplementation() { 45 + if ($this->className === null) { 46 + throw new Exception("No implementation set for the given step."); 47 + } 48 + 49 + // TODO: We should look up the class in phutil's system to ensure 50 + // that it actually extends BuildStepImplementation. 51 + $class = $this->className; 52 + $implementation = newv($class, array()); 53 + $implementation->loadSettings($this); 54 + return $implementation; 55 + } 56 + 57 + 58 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 59 + 60 + 61 + public function getCapabilities() { 62 + return array( 63 + PhabricatorPolicyCapability::CAN_VIEW, 64 + ); 65 + } 66 + 67 + public function getPolicy($capability) { 68 + return $this->getBuildPlan()->getPolicy($capability); 69 + } 70 + 71 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 72 + return $this->getBuildPlan()->hasAutomaticCapability($capability, $viewer); 73 + } 74 + 75 + public function describeAutomaticCapability($capability) { 76 + return pht('A build step has the same policies as its build plan.'); 77 + } 29 78 }
+18 -4
src/applications/harbormaster/worker/HarbormasterBuildWorker.php
··· 32 32 $buildable = $build->getBuildable(); 33 33 $plan = $build->getBuildPlan(); 34 34 35 - // TODO: Do the actual build here. 36 - sleep(15); 35 + $steps = id(new HarbormasterBuildStepQuery()) 36 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 37 + ->withBuildPlanPHIDs(array($plan->getPHID())) 38 + ->execute(); 37 39 38 - // If we get to here, then the build has passed. 39 - $build->setBuildStatus(HarbormasterBuild::STATUS_PASSED); 40 + // Perform the build. 41 + foreach ($steps as $step) { 42 + $implementation = $step->getStepImplementation(); 43 + $implementation->execute($build); 44 + if ($build->getBuildStatus() !== HarbormasterBuild::STATUS_BUILDING) { 45 + break; 46 + } 47 + } 48 + 49 + // If we get to here, then the build has finished. Set it to passed 50 + // if no build step explicitly set the status. 51 + if ($build->getBuildStatus() === HarbormasterBuild::STATUS_BUILDING) { 52 + $build->setBuildStatus(HarbormasterBuild::STATUS_PASSED); 53 + } 40 54 $build->save(); 41 55 } catch (Exception $e) { 42 56 // If any exception is raised, the build is marked as a failure and
+4
src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
··· 1720 1720 'type' => 'sql', 1721 1721 'name' => $this->getPatchPath('20131031.vcspassword.sql'), 1722 1722 ), 1723 + '20131105.buildstep.sql' => array( 1724 + 'type' => 'sql', 1725 + 'name' => $this->getPatchPath('20131105.buildstep.sql'), 1726 + ), 1723 1727 ); 1724 1728 } 1725 1729 }