1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-19 16:58:48 +02: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:
James Rhodes 2013-11-05 13:34:14 -08:00 committed by epriestley
parent 5c0edc9351
commit c514d34b94
8 changed files with 201 additions and 6 deletions

View 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;

View file

@ -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',
),

View file

@ -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';
}

View file

@ -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();
}
}

View file

@ -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());
}
}

View file

@ -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.');
}
}

View file

@ -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

View file

@ -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'),
),
);
}
}