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

View file

@ -41,13 +41,47 @@ final class HarbormasterBuildViewController
id(new PhabricatorCrumbView()) id(new PhabricatorCrumbView())
->setName($title)); ->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( return $this->buildApplicationPage(
array( array(
$crumbs, $crumbs,
$box, $box,
$logs $targets
), ),
array( array(
'title' => $title, '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(); $request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$limit = $request->getInt('l', 25); $limit = $request->getInt('l', 25);
$logs = id(new HarbormasterBuildLogQuery()) $logs = id(new HarbormasterBuildLogQuery())
->setViewer($viewer) ->setViewer($viewer)
->withBuildPHIDs(array($build->getPHID())) ->withBuildTargetPHIDs(array($build_target->getPHID()))
->execute(); ->execute();
$log_boxes = array(); $log_boxes = array();

View file

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

View file

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

View file

@ -5,6 +5,7 @@ final class HarbormasterBuildTargetQuery
private $ids; private $ids;
private $phids; private $phids;
private $buildPHIDs;
public function withIDs(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
@ -16,6 +17,11 @@ final class HarbormasterBuildTargetQuery
return $this; return $this;
} }
public function withBuildPHIDs(array $build_phids) {
$this->buildPHIDs = $build_phids;
return $this;
}
protected function loadPage() { protected function loadPage() {
$table = new HarbormasterBuildTarget(); $table = new HarbormasterBuildTarget();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');
@ -48,11 +54,43 @@ final class HarbormasterBuildTargetQuery
$this->phids); $this->phids);
} }
if ($this->buildPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildPHID in (%Ls)',
$this->buildPHIDs);
}
$where[] = $this->buildPagingClause($conn_r); $where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where); 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() { public function getQueryApplicationClass() {
return 'PhabricatorApplicationHarbormaster'; 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( abstract public function execute(
HarbormasterBuild $build, HarbormasterBuild $build,
HarbormasterBuildStep $build_step); HarbormasterBuildTarget $build_target);
/** /**
* Gets the settings for this build step. * 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->settings = array();
$this->validateSettingDefinitions(); $this->validateSettingDefinitions();
foreach ($this->getSettingDefinitions() as $name => $opt) { foreach ($this->getSettingDefinitions() as $name => $opt) {
$this->settings[$name] = $build_step->getDetail($name); $this->settings[$name] = $build_target->getDetail($name);
} }
return $this->settings; return $this->settings;
} }

View file

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

View file

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

View file

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

View file

@ -2,41 +2,6 @@
abstract class VariableBuildStepImplementation extends BuildStepImplementation { 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: * 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); 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() { public function getSettingRemarkupInstructions() {
$text = ''; $text = '';
$text .= pht('The following variables are available: ')."\n"; $text .= pht('The following variables are available: ')."\n";

View file

@ -95,11 +95,11 @@ final class HarbormasterBuild extends HarbormasterDAO
} }
public function createLog( public function createLog(
HarbormasterBuildStep $build_step, HarbormasterBuildTarget $build_target,
$log_source, $log_source,
$log_type) { $log_type) {
$log = HarbormasterBuildLog::initializeNewBuildLog($this, $build_step); $log = HarbormasterBuildLog::initializeNewBuildLog($build_target);
$log->setLogSource($log_source); $log->setLogSource($log_source);
$log->setLogType($log_type); $log->setLogType($log_type);
$log->save(); $log->save();
@ -125,6 +125,57 @@ final class HarbormasterBuild extends HarbormasterDAO
return false; 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 )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -3,15 +3,13 @@
final class HarbormasterBuildLog extends HarbormasterDAO final class HarbormasterBuildLog extends HarbormasterDAO
implements PhabricatorPolicyInterface { implements PhabricatorPolicyInterface {
protected $buildPHID; protected $buildTargetPHID;
protected $buildStepPHID;
protected $logSource; protected $logSource;
protected $logType; protected $logType;
protected $duration; protected $duration;
protected $live; protected $live;
private $build = self::ATTACHABLE; private $buildTarget = self::ATTACHABLE;
private $buildStep = self::ATTACHABLE;
const CHUNK_BYTE_LIMIT = 102400; const CHUNK_BYTE_LIMIT = 102400;
@ -21,12 +19,10 @@ final class HarbormasterBuildLog extends HarbormasterDAO
const ENCODING_TEXT = 'text'; const ENCODING_TEXT = 'text';
public static function initializeNewBuildLog( public static function initializeNewBuildLog(
HarbormasterBuild $build, HarbormasterBuildTarget $build_target) {
HarbormasterBuildStep $build_step) {
return id(new HarbormasterBuildLog()) return id(new HarbormasterBuildLog())
->setBuildPHID($build->getPHID()) ->setBuildTargetPHID($build_target->getPHID())
->setBuildStepPHID($build_step->getPHID())
->setDuration(null) ->setDuration(null)
->setLive(0); ->setLive(0);
} }
@ -42,29 +38,19 @@ final class HarbormasterBuildLog extends HarbormasterDAO
HarbormasterPHIDTypeBuildLog::TYPECONST); HarbormasterPHIDTypeBuildLog::TYPECONST);
} }
public function attachBuild(HarbormasterBuild $build) { public function attachBuildTarget(HarbormasterBuildTarget $build_target) {
$this->build = $build; $this->buildTarget = $build_target;
return $this; return $this;
} }
public function getBuild() { public function getBuildTarget() {
return $this->assertAttached($this->build); return $this->assertAttached($this->buildTarget);
} }
public function getName() { public function getName() {
return pht('Build Log'); 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() { public function start() {
if ($this->getLive()) { if ($this->getLive()) {
throw new Exception("Live logging has already started for this log."); throw new Exception("Live logging has already started for this log.");
@ -189,18 +175,18 @@ final class HarbormasterBuildLog extends HarbormasterDAO
} }
public function getPolicy($capability) { public function getPolicy($capability) {
return $this->getBuild()->getPolicy($capability); return $this->getBuildTarget()->getPolicy($capability);
} }
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getBuild()->hasAutomaticCapability( return $this->getBuildTarget()->hasAutomaticCapability(
$capability, $capability,
$viewer); $viewer);
} }
public function describeAutomaticCapability($capability) { public function describeAutomaticCapability($capability) {
return pht( 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 <?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() { public function getConfiguration() {
return array( return array(
self::CONFIG_AUX_PHID => true, self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
'variables' => self::SERIALIZATION_JSON,
)
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
@ -13,4 +39,85 @@ final class HarbormasterBuildTarget extends HarbormasterDAO {
HarbormasterPHIDTypeBuildTarget::TYPECONST); 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; 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 )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -45,12 +45,21 @@ final class HarbormasterBuildWorker extends PhabricatorWorker {
// Perform the build. // Perform the build.
foreach ($steps as $step) { 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()) { if (!$implementation->validateSettings()) {
$build->setBuildStatus(HarbormasterBuild::STATUS_ERROR); $build->setBuildStatus(HarbormasterBuild::STATUS_ERROR);
break; break;
} }
$implementation->execute($build, $step); $implementation->execute($build, $target);
if ($build->getBuildStatus() !== HarbormasterBuild::STATUS_BUILDING) { if ($build->getBuildStatus() !== HarbormasterBuild::STATUS_BUILDING) {
break; break;
} }

View file

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