mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-28 08:20:57 +01:00
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
This commit is contained in:
parent
5c0edc9351
commit
c514d34b94
8 changed files with 201 additions and 6 deletions
11
resources/sql/patches/20131105.buildstep.sql
Normal file
11
resources/sql/patches/20131105.buildstep.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
CREATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildstep (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||
buildPlanPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||
className VARCHAR(255) NOT NULL COLLATE utf8_bin,
|
||||
details LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
KEY `key_plan` (buildPlanPHID),
|
||||
UNIQUE KEY `key_phid` (phid)
|
||||
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
|
@ -91,6 +91,7 @@ phutil_register_library_map(array(
|
|||
'AphrontView' => 'view/AphrontView.php',
|
||||
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
|
||||
'AuditActionMenuEventListener' => 'applications/audit/events/AuditActionMenuEventListener.php',
|
||||
'BuildStepImplementation' => 'applications/harbormaster/step/BuildStepImplementation.php',
|
||||
'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php',
|
||||
'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php',
|
||||
'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php',
|
||||
|
@ -2195,6 +2196,7 @@ phutil_register_library_map(array(
|
|||
'ReleephStatusFieldSpecification' => 'applications/releeph/field/specification/ReleephStatusFieldSpecification.php',
|
||||
'ReleephSummaryFieldSpecification' => 'applications/releeph/field/specification/ReleephSummaryFieldSpecification.php',
|
||||
'ReleephUserView' => 'applications/releeph/view/user/ReleephUserView.php',
|
||||
'SleepBuildStepImplementation' => 'applications/harbormaster/step/SleepBuildStepImplementation.php',
|
||||
'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php',
|
||||
'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php',
|
||||
),
|
||||
|
@ -2872,7 +2874,11 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildPlanTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'HarbormasterBuildStep' => 'HarbormasterDAO',
|
||||
'HarbormasterBuildStep' =>
|
||||
array(
|
||||
0 => 'HarbormasterDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'HarbormasterBuildTarget' => 'HarbormasterDAO',
|
||||
'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
|
@ -4651,6 +4657,7 @@ phutil_register_library_map(array(
|
|||
'ReleephStatusFieldSpecification' => 'ReleephFieldSpecification',
|
||||
'ReleephSummaryFieldSpecification' => 'ReleephFieldSpecification',
|
||||
'ReleephUserView' => 'AphrontView',
|
||||
'SleepBuildStepImplementation' => 'BuildStepImplementation',
|
||||
'SlowvoteEmbedView' => 'AphrontView',
|
||||
'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject',
|
||||
),
|
||||
|
|
|
@ -5,6 +5,7 @@ final class HarbormasterBuildStepQuery
|
|||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $buildPlanPHIDs;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
|
@ -16,6 +17,11 @@ final class HarbormasterBuildStepQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withBuildPlanPHIDs(array $phids) {
|
||||
$this->buildPlanPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new HarbormasterBuildStep();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
@ -48,11 +54,43 @@ final class HarbormasterBuildStepQuery
|
|||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->buildPlanPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'buildPlanPHID in (%Ls)',
|
||||
$this->buildPlanPHIDs);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $page) {
|
||||
$plans = array();
|
||||
|
||||
$buildplan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
|
||||
if ($buildplan_phids) {
|
||||
$plans = id(new PhabricatorObjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($buildplan_phids)
|
||||
->setParentQuery($this)
|
||||
->execute();
|
||||
$plans = mpull($plans, null, 'getPHID');
|
||||
}
|
||||
|
||||
foreach ($page as $key => $build) {
|
||||
$buildable_phid = $build->getBuildPlanPHID();
|
||||
if (empty($plans[$buildable_phid])) {
|
||||
unset($page[$key]);
|
||||
continue;
|
||||
}
|
||||
$build->attachBuildPlan($plans[$buildable_phid]);
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorApplicationHarbormaster';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
abstract class BuildStepImplementation {
|
||||
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* The name of the implementation.
|
||||
*/
|
||||
abstract public function getName();
|
||||
|
||||
/**
|
||||
* The description of the implementation.
|
||||
*/
|
||||
public function getDescription() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the build step against the specified build.
|
||||
*/
|
||||
abstract public function execute(HarbormasterBuild $build);
|
||||
|
||||
/**
|
||||
* Gets the settings for this build step.
|
||||
*/
|
||||
protected function getSettings() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the settings for this build step implementation from the build step.
|
||||
*/
|
||||
public final function loadSettings(HarbormasterBuildStep $build_step) {
|
||||
$this->settings = array();
|
||||
foreach ($this->getSettingDefinitions() as $name => $opt) {
|
||||
$this->settings[$name] = $build_step->getDetail($name);
|
||||
}
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of settings for this step implementation.
|
||||
*/
|
||||
public function getSettingDefinitions() {
|
||||
return array();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
final class SleepBuildStepImplementation extends BuildStepImplementation {
|
||||
|
||||
public function getName() {
|
||||
return pht('Sleep');
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
return pht('Sleep for a specified number of seconds.');
|
||||
}
|
||||
|
||||
public function execute(HarbormasterBuild $build) {
|
||||
$settings = $this->getSettings();
|
||||
|
||||
sleep($settings['seconds']);
|
||||
}
|
||||
|
||||
public function getSettingDefinitions() {
|
||||
return array(
|
||||
'seconds' => array());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,20 @@
|
|||
<?php
|
||||
|
||||
final class HarbormasterBuildStep extends HarbormasterDAO {
|
||||
final class HarbormasterBuildStep extends HarbormasterDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $buildPlanPHID;
|
||||
protected $className;
|
||||
protected $details = array();
|
||||
|
||||
private $buildPlan = self::ATTACHABLE;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'details' => self::SERIALIZATION_JSON,
|
||||
)
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
|
@ -26,4 +32,47 @@ final class HarbormasterBuildStep extends HarbormasterDAO {
|
|||
return $this->assertAttached($this->buildPlan);
|
||||
}
|
||||
|
||||
public function getDetail($key, $default = null) {
|
||||
return idx($this->details, $key, $default);
|
||||
}
|
||||
|
||||
public function setDetail($key, $value) {
|
||||
$this->details[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStepImplementation() {
|
||||
if ($this->className === null) {
|
||||
throw new Exception("No implementation set for the given step.");
|
||||
}
|
||||
|
||||
// TODO: We should look up the class in phutil's system to ensure
|
||||
// that it actually extends BuildStepImplementation.
|
||||
$class = $this->className;
|
||||
$implementation = newv($class, array());
|
||||
$implementation->loadSettings($this);
|
||||
return $implementation;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return $this->getBuildPlan()->getPolicy($capability);
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return $this->getBuildPlan()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('A build step has the same policies as its build plan.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,25 @@ final class HarbormasterBuildWorker extends PhabricatorWorker {
|
|||
$buildable = $build->getBuildable();
|
||||
$plan = $build->getBuildPlan();
|
||||
|
||||
// TODO: Do the actual build here.
|
||||
sleep(15);
|
||||
$steps = id(new HarbormasterBuildStepQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withBuildPlanPHIDs(array($plan->getPHID()))
|
||||
->execute();
|
||||
|
||||
// If we get to here, then the build has passed.
|
||||
$build->setBuildStatus(HarbormasterBuild::STATUS_PASSED);
|
||||
// Perform the build.
|
||||
foreach ($steps as $step) {
|
||||
$implementation = $step->getStepImplementation();
|
||||
$implementation->execute($build);
|
||||
if ($build->getBuildStatus() !== HarbormasterBuild::STATUS_BUILDING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get to here, then the build has finished. Set it to passed
|
||||
// if no build step explicitly set the status.
|
||||
if ($build->getBuildStatus() === HarbormasterBuild::STATUS_BUILDING) {
|
||||
$build->setBuildStatus(HarbormasterBuild::STATUS_PASSED);
|
||||
}
|
||||
$build->save();
|
||||
} catch (Exception $e) {
|
||||
// If any exception is raised, the build is marked as a failure and
|
||||
|
|
|
@ -1720,6 +1720,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131031.vcspassword.sql'),
|
||||
),
|
||||
'20131105.buildstep.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131105.buildstep.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue