1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Introduce HarbormasterBuildTarget to snapshot build steps through a build

Summary: This implements build targets as outlined in D7582.  Build targets represent an instance of a build step particular to the build.  Logs and artifacts have been adjusted to attach to build targets instead of build / build step pairs.

Test Plan: Ran builds and clicked around the interface.  Everything seemed to work.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley

CC: Korvin, epriestley, aran

Maniphest Tasks: T4111, T1049

Differential Revision: https://secure.phabricator.com/D7703
This commit is contained in:
James Rhodes 2013-12-05 12:01:12 +11:00
parent 2aad7289fd
commit 53250d84df
17 changed files with 349 additions and 154 deletions

View file

@ -0,0 +1,32 @@
CREATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildtarget (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
buildPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
buildStepPHID 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,
variables LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
KEY `key_build` (buildPHID, buildStepPHID),
UNIQUE KEY `key_phid` (phid)
) ENGINE=InnoDB, COLLATE utf8_general_ci;
TRUNCATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildlog;
TRUNCATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildlogchunk;
TRUNCATE TABLE {$NAMESPACE}_harbormaster.harbormaster_buildartifact;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildlog
DROP COLUMN buildPHID;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildlog
DROP COLUMN buildStepPHID;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildartifact
DROP COLUMN buildablePHID;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildlog
ADD COLUMN buildTargetPHID VARCHAR(64) NOT NULL COLLATE utf8_bin;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildartifact
ADD COLUMN buildTargetPHID VARCHAR(64) NOT NULL COLLATE utf8_bin;

View file

@ -677,6 +677,7 @@ phutil_register_library_map(array(
'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php',
'HarbormasterBuild' => 'applications/harbormaster/storage/build/HarbormasterBuild.php',
'HarbormasterBuildArtifact' => 'applications/harbormaster/storage/build/HarbormasterBuildArtifact.php',
'HarbormasterBuildArtifactQuery' => 'applications/harbormaster/query/HarbormasterBuildArtifactQuery.php',
'HarbormasterBuildCancelController' => 'applications/harbormaster/controller/HarbormasterBuildCancelController.php',
'HarbormasterBuildItem' => 'applications/harbormaster/storage/build/HarbormasterBuildItem.php',
'HarbormasterBuildItemQuery' => 'applications/harbormaster/query/HarbormasterBuildItemQuery.php',
@ -698,7 +699,6 @@ phutil_register_library_map(array(
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
'HarbormasterBuildableApplyController' => 'applications/harbormaster/controller/HarbormasterBuildableApplyController.php',
'HarbormasterBuildableArtifactQuery' => 'applications/harbormaster/query/HarbormasterBuildableArtifactQuery.php',
'HarbormasterBuildableEditController' => 'applications/harbormaster/controller/HarbormasterBuildableEditController.php',
'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php',
'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php',
@ -3023,6 +3023,7 @@ phutil_register_library_map(array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildArtifactQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildCancelController' => 'HarbormasterController',
'HarbormasterBuildItem' => 'HarbormasterDAO',
'HarbormasterBuildItemQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
@ -3051,7 +3052,11 @@ phutil_register_library_map(array(
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildTarget' => 'HarbormasterDAO',
'HarbormasterBuildTarget' =>
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildViewController' => 'HarbormasterController',
'HarbormasterBuildWorker' => 'PhabricatorWorker',
@ -3061,7 +3066,6 @@ phutil_register_library_map(array(
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildableApplyController' => 'HarbormasterController',
'HarbormasterBuildableArtifactQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildableEditController' => 'HarbormasterController',
'HarbormasterBuildableListController' =>
array(

View file

@ -41,13 +41,47 @@ final class HarbormasterBuildViewController
id(new PhabricatorCrumbView())
->setName($title));
$logs = $this->buildLog($build);
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($viewer)
->withBuildPHIDs(array($build->getPHID()))
->execute();
$targets = array();
foreach ($build_targets as $build_target) {
$header = id(new PHUIHeaderView())
->setHeader(pht('Build Target %d', $build_target->getID()))
->setUser($viewer);
$properties = new PHUIPropertyListView();
$details = $build_target->getDetails();
if ($details) {
$properties->addSectionHeader(pht('Configuration Details'));
foreach ($details as $key => $value) {
$properties->addProperty($key, $value);
}
}
$variables = $build_target->getVariables();
if ($variables) {
$properties->addSectionHeader(pht('Variables'));
foreach ($variables as $key => $value) {
$properties->addProperty($key, $value);
}
}
$targets[] = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$targets[] = $this->buildLog($build, $build_target);
}
return $this->buildApplicationPage(
array(
$crumbs,
$box,
$logs
$targets
),
array(
'title' => $title,
@ -55,14 +89,17 @@ final class HarbormasterBuildViewController
));
}
private function buildLog(HarbormasterBuild $build) {
private function buildLog(
HarbormasterBuild $build,
HarbormasterBuildTarget $build_target) {
$request = $this->getRequest();
$viewer = $request->getUser();
$limit = $request->getInt('l', 25);
$logs = id(new HarbormasterBuildLogQuery())
->setViewer($viewer)
->withBuildPHIDs(array($build->getPHID()))
->withBuildTargetPHIDs(array($build_target->getPHID()))
->execute();
$log_boxes = array();

View file

@ -1,10 +1,10 @@
<?php
final class HarbormasterBuildableArtifactQuery
final class HarbormasterBuildArtifactQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $buildablePHIDs;
private $buildTargetPHIDs;
private $artifactTypes;
private $artifactKeys;
@ -13,8 +13,8 @@ final class HarbormasterBuildableArtifactQuery
return $this;
}
public function withBuildablePHIDs(array $buildable_phids) {
$this->buildablePHIDs = $buildable_phids;
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
@ -44,25 +44,25 @@ final class HarbormasterBuildableArtifactQuery
}
protected function willFilterPage(array $page) {
$buildables = array();
$build_targets = array();
$buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($buildable_phids) {
$buildables = id(new PhabricatorObjectQuery())
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($buildable_phids)
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$buildables = mpull($buildables, null, 'getPHID');
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $artifact) {
$buildable_phid = $artifact->getBuildablePHID();
if (empty($buildables[$buildable_phid])) {
foreach ($page as $key => $build_log) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$artifact->attachBuildable($buildables[$buildable_phid]);
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
@ -78,11 +78,11 @@ final class HarbormasterBuildableArtifactQuery
$this->ids);
}
if ($this->buildablePHIDs) {
if ($this->buildTargetPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildablePHID IN (%Ls)',
$this->buildablePHIDs);
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
if ($this->artifactTypes) {

View file

@ -17,8 +17,8 @@ final class HarbormasterBuildLogQuery
return $this;
}
public function withBuildPHIDs(array $build_phids) {
$this->buildPHIDs = $build_phids;
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
@ -38,25 +38,25 @@ final class HarbormasterBuildLogQuery
}
protected function willFilterPage(array $page) {
$builds = array();
$build_targets = array();
$build_phids = array_filter(mpull($page, 'getBuildPHID'));
if ($build_phids) {
$builds = id(new HarbormasterBuildQuery())
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($build_phids)
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$builds = mpull($builds, null, 'getPHID');
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $build_log) {
$build_phid = $build_log->getBuildPHID();
if (empty($builds[$build_phid])) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$build_log->attachBuild($builds[$build_phid]);
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
@ -79,11 +79,11 @@ final class HarbormasterBuildLogQuery
$this->phids);
}
if ($this->buildPHIDs) {
if ($this->buildTargetPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildPHID IN (%Ls)',
$this->buildPHIDs);
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);

View file

@ -5,6 +5,7 @@ final class HarbormasterBuildTargetQuery
private $ids;
private $phids;
private $buildPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -16,6 +17,11 @@ final class HarbormasterBuildTargetQuery
return $this;
}
public function withBuildPHIDs(array $build_phids) {
$this->buildPHIDs = $build_phids;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildTarget();
$conn_r = $table->establishConnection('r');
@ -48,11 +54,43 @@ final class HarbormasterBuildTargetQuery
$this->phids);
}
if ($this->buildPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildPHID in (%Ls)',
$this->buildPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $page) {
$builds = array();
$build_phids = array_filter(mpull($page, 'getBuildPHID'));
if ($build_phids) {
$builds = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($build_phids)
->setParentQuery($this)
->execute();
$builds = mpull($builds, null, 'getPHID');
}
foreach ($page as $key => $build_target) {
$build_phid = $build_target->getBuildPHID();
if (empty($builds[$build_phid])) {
unset($page[$key]);
continue;
}
$build_target->attachBuild($builds[$build_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationHarbormaster';
}

View file

@ -36,11 +36,11 @@ abstract class BuildStepImplementation {
}
/**
* Run the build step against the specified build.
* Run the build target against the specified build.
*/
abstract public function execute(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step);
HarbormasterBuildTarget $build_target);
/**
* Gets the settings for this build step.
@ -57,13 +57,13 @@ abstract class BuildStepImplementation {
}
/**
* Loads the settings for this build step implementation from the build step.
* Loads the settings for this build step implementation from a build target.
*/
public final function loadSettings(HarbormasterBuildStep $build_step) {
public final function loadSettings(HarbormasterBuildTarget $build_target) {
$this->settings = array();
$this->validateSettingDefinitions();
foreach ($this->getSettingDefinitions() as $name => $opt) {
$this->settings[$name] = $build_step->getDetail($name);
$this->settings[$name] = $build_target->getDetail($name);
}
return $this->settings;
}

View file

@ -21,17 +21,17 @@ final class HarbormasterHTTPRequestBuildStepImplementation
public function execute(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step) {
HarbormasterBuildTarget $build_target) {
$settings = $this->getSettings();
$variables = $this->retrieveVariablesFromBuild($build);
$variables = $build_target->getVariables();
$uri = $this->mergeVariables(
'vurisprintf',
$settings['uri'],
$variables);
$log_body = $build->createLog($build_step, $uri, 'http-body');
$log_body = $build->createLog($build_target, $uri, 'http-body');
$start = $log_body->start();
list($status, $body, $headers) = id(new HTTPSFuture($uri))

View file

@ -22,10 +22,10 @@ final class RemoteCommandBuildStepImplementation
public function execute(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step) {
HarbormasterBuildTarget $build_target) {
$settings = $this->getSettings();
$variables = $this->retrieveVariablesFromBuild($build);
$variables = $build_target->getVariables();
$command = $this->mergeVariables(
'vcsprintf',
@ -48,8 +48,8 @@ final class RemoteCommandBuildStepImplementation
$command);
}
$log_stdout = $build->createLog($build_step, "remote", "stdout");
$log_stderr = $build->createLog($build_step, "remote", "stderr");
$log_stdout = $build->createLog($build_target, "remote", "stdout");
$log_stderr = $build->createLog($build_target, "remote", "stderr");
$start_stdout = $log_stdout->start();
$start_stderr = $log_stderr->start();

View file

@ -18,7 +18,7 @@ final class SleepBuildStepImplementation extends BuildStepImplementation {
public function execute(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step) {
HarbormasterBuildTarget $build_target) {
$settings = $this->getSettings();

View file

@ -2,41 +2,6 @@
abstract class VariableBuildStepImplementation extends BuildStepImplementation {
public function retrieveVariablesFromBuild(HarbormasterBuild $build) {
$results = array(
'buildable.diff' => null,
'buildable.revision' => null,
'buildable.commit' => null,
'repository.callsign' => null,
'repository.vcs' => null,
'repository.uri' => null,
'step.timestamp' => null,
'build.id' => null);
$buildable = $build->getBuildable();
$object = $buildable->getBuildableObject();
$repo = null;
if ($object instanceof DifferentialDiff) {
$results['buildable.diff'] = $object->getID();
$revision = $object->getRevision();
$results['buildable.revision'] = $revision->getID();
$repo = $revision->getRepository();
} else if ($object instanceof PhabricatorRepositoryCommit) {
$results['buildable.commit'] = $object->getCommitIdentifier();
$repo = $object->getRepository();
}
$results['repository.callsign'] = $repo->getCallsign();
$results['repository.vcs'] = $repo->getVersionControlSystem();
$results['repository.uri'] = $repo->getPublicRemoteURI();
$results['step.timestamp'] = time();
$results['build.id'] = $build->getID();
return $results;
}
/**
* Convert a user-provided string with variables in it, like:
*
@ -71,24 +36,6 @@ abstract class VariableBuildStepImplementation extends BuildStepImplementation {
return call_user_func($function, $pattern, $argv);
}
public function getAvailableVariables() {
return array(
'buildable.diff' =>
pht('The differential diff ID, if applicable.'),
'buildable.revision' =>
pht('The differential revision ID, if applicable.'),
'buildable.commit' => pht('The commit identifier, if applicable.'),
'repository.callsign' =>
pht('The callsign of the repository in Phabricator.'),
'repository.vcs' =>
pht('The version control system, either "svn", "hg" or "git".'),
'repository.uri' =>
pht('The URI to clone or checkout the repository from.'),
'step.timestamp' => pht('The current UNIX timestamp.'),
'build.id' => pht('The ID of the current build.'));
}
public function getSettingRemarkupInstructions() {
$text = '';
$text .= pht('The following variables are available: ')."\n";

View file

@ -95,11 +95,11 @@ final class HarbormasterBuild extends HarbormasterDAO
}
public function createLog(
HarbormasterBuildStep $build_step,
HarbormasterBuildTarget $build_target,
$log_source,
$log_type) {
$log = HarbormasterBuildLog::initializeNewBuildLog($this, $build_step);
$log = HarbormasterBuildLog::initializeNewBuildLog($build_target);
$log->setLogSource($log_source);
$log->setLogType($log_type);
$log->save();
@ -125,6 +125,57 @@ final class HarbormasterBuild extends HarbormasterDAO
return false;
}
public function retrieveVariablesFromBuild() {
$results = array(
'buildable.diff' => null,
'buildable.revision' => null,
'buildable.commit' => null,
'repository.callsign' => null,
'repository.vcs' => null,
'repository.uri' => null,
'step.timestamp' => null,
'build.id' => null);
$buildable = $this->getBuildable();
$object = $buildable->getBuildableObject();
$repo = null;
if ($object instanceof DifferentialDiff) {
$results['buildable.diff'] = $object->getID();
$revision = $object->getRevision();
$results['buildable.revision'] = $revision->getID();
$repo = $revision->getRepository();
} else if ($object instanceof PhabricatorRepositoryCommit) {
$results['buildable.commit'] = $object->getCommitIdentifier();
$repo = $object->getRepository();
}
$results['repository.callsign'] = $repo->getCallsign();
$results['repository.vcs'] = $repo->getVersionControlSystem();
$results['repository.uri'] = $repo->getPublicRemoteURI();
$results['step.timestamp'] = time();
$results['build.id'] = $this->getID();
return $results;
}
public function getAvailableBuildVariables() {
return array(
'buildable.diff' =>
pht('The differential diff ID, if applicable.'),
'buildable.revision' =>
pht('The differential revision ID, if applicable.'),
'buildable.commit' => pht('The commit identifier, if applicable.'),
'repository.callsign' =>
pht('The callsign of the repository in Phabricator.'),
'repository.vcs' =>
pht('The version control system, either "svn", "hg" or "git".'),
'repository.uri' =>
pht('The URI to clone or checkout the repository from.'),
'step.timestamp' => pht('The current UNIX timestamp.'),
'build.id' => pht('The ID of the current build.'));
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -3,15 +3,13 @@
final class HarbormasterBuildLog extends HarbormasterDAO
implements PhabricatorPolicyInterface {
protected $buildPHID;
protected $buildStepPHID;
protected $buildTargetPHID;
protected $logSource;
protected $logType;
protected $duration;
protected $live;
private $build = self::ATTACHABLE;
private $buildStep = self::ATTACHABLE;
private $buildTarget = self::ATTACHABLE;
const CHUNK_BYTE_LIMIT = 102400;
@ -21,12 +19,10 @@ final class HarbormasterBuildLog extends HarbormasterDAO
const ENCODING_TEXT = 'text';
public static function initializeNewBuildLog(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step) {
HarbormasterBuildTarget $build_target) {
return id(new HarbormasterBuildLog())
->setBuildPHID($build->getPHID())
->setBuildStepPHID($build_step->getPHID())
->setBuildTargetPHID($build_target->getPHID())
->setDuration(null)
->setLive(0);
}
@ -42,29 +38,19 @@ final class HarbormasterBuildLog extends HarbormasterDAO
HarbormasterPHIDTypeBuildLog::TYPECONST);
}
public function attachBuild(HarbormasterBuild $build) {
$this->build = $build;
public function attachBuildTarget(HarbormasterBuildTarget $build_target) {
$this->buildTarget = $build_target;
return $this;
}
public function getBuild() {
return $this->assertAttached($this->build);
public function getBuildTarget() {
return $this->assertAttached($this->buildTarget);
}
public function getName() {
return pht('Build Log');
}
public function attachBuildStep(
HarbormasterBuildStep $build_step = null) {
$this->buildStep = $build_step;
return $this;
}
public function getBuildStep() {
return $this->assertAttached($this->buildStep);
}
public function start() {
if ($this->getLive()) {
throw new Exception("Live logging has already started for this log.");
@ -189,18 +175,18 @@ final class HarbormasterBuildLog extends HarbormasterDAO
}
public function getPolicy($capability) {
return $this->getBuild()->getPolicy($capability);
return $this->getBuildTarget()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getBuild()->hasAutomaticCapability(
return $this->getBuildTarget()->hasAutomaticCapability(
$capability,
$viewer);
}
public function describeAutomaticCapability($capability) {
return pht(
'Users must be able to see a build to view it\'s build log.');
'Users must be able to see a build target to view it\'s build log.');
}

View file

@ -1,10 +1,36 @@
<?php
final class HarbormasterBuildTarget extends HarbormasterDAO {
final class HarbormasterBuildTarget extends HarbormasterDAO
implements PhabricatorPolicyInterface {
protected $buildPHID;
protected $buildStepPHID;
protected $className;
protected $details;
protected $variables;
private $build = self::ATTACHABLE;
private $buildStep = self::ATTACHABLE;
public static function initializeNewBuildTarget(
HarbormasterBuild $build,
HarbormasterBuildStep $build_step,
array $variables) {
return id(new HarbormasterBuildTarget())
->setBuildPHID($build->getPHID())
->setBuildStepPHID($build_step->getPHID())
->setClassName($build_step->getClassName())
->setDetails($build_step->getDetails())
->setVariables($variables);
}
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
'variables' => self::SERIALIZATION_JSON,
)
) + parent::getConfiguration();
}
@ -13,4 +39,85 @@ final class HarbormasterBuildTarget extends HarbormasterDAO {
HarbormasterPHIDTypeBuildTarget::TYPECONST);
}
public function attachBuild(HarbormasterBuild $build) {
$this->build = $build;
return $this;
}
public function getBuild() {
return $this->assertAttached($this->build);
}
public function attachBuildStep(HarbormasterBuildStep $step) {
$this->buildStep = $step;
return $this;
}
public function getBuildStep() {
return $this->assertAttached($this->buildStep);
}
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 getVariable($key, $default = null) {
return idx($this->variables, $key, $default);
}
public function setVariable($key, $value) {
$this->variables[$key] = $value;
return $this;
}
public function getImplementation() {
if ($this->className === null) {
throw new Exception("No implementation set for the given target.");
}
static $implementations = null;
if ($implementations === null) {
$implementations = BuildStepImplementation::getImplementations();
}
$class = $this->className;
if (!in_array($class, $implementations)) {
throw new Exception(
"Class name '".$class."' does not extend BuildStepImplementation.");
}
$implementation = newv($class, array());
$implementation->loadSettings($this);
return $implementation;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
return $this->getBuild()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getBuild()->hasAutomaticCapability(
$capability,
$viewer);
}
public function describeAutomaticCapability($capability) {
return pht(
'Users must be able to see a build to view its build targets.');
}
}

View file

@ -41,26 +41,6 @@ final class HarbormasterBuildStep extends HarbormasterDAO
return $this;
}
public function getStepImplementation() {
if ($this->className === null) {
throw new Exception("No implementation set for the given step.");
}
static $implementations = null;
if ($implementations === null) {
$implementations = BuildStepImplementation::getImplementations();
}
$class = $this->className;
if (!in_array($class, $implementations)) {
throw new Exception(
"Class name '".$class."' does not extend BuildStepImplementation.");
}
$implementation = newv($class, array());
$implementation->loadSettings($this);
return $implementation;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -45,12 +45,21 @@ final class HarbormasterBuildWorker extends PhabricatorWorker {
// Perform the build.
foreach ($steps as $step) {
$implementation = $step->getStepImplementation();
// Create the target at this step.
// TODO: Support variable artifacts.
$target = HarbormasterBuildTarget::initializeNewBuildTarget(
$build,
$step,
$build->retrieveVariablesFromBuild());
$target->save();
$implementation = $target->getImplementation();
if (!$implementation->validateSettings()) {
$build->setBuildStatus(HarbormasterBuild::STATUS_ERROR);
break;
}
$implementation->execute($build, $step);
$implementation->execute($build, $target);
if ($build->getBuildStatus() !== HarbormasterBuild::STATUS_BUILDING) {
break;
}

View file

@ -1796,6 +1796,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'sql',
'name' => $this->getPatchPath('20131129.drydockresourceblueprint.sql'),
),
'20131205.buildtargets.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131205.buildtargets.sql'),
),
);
}
}