From 53250d84dfc5fce711d199b97b04c4527f64109d Mon Sep 17 00:00:00 2001 From: James Rhodes Date: Thu, 5 Dec 2013 12:01:12 +1100 Subject: [PATCH] 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 --- .../sql/patches/20131205.buildtargets.sql | 32 +++++ src/__phutil_library_map__.php | 10 +- .../HarbormasterBuildViewController.php | 45 +++++++- ...php => HarbormasterBuildArtifactQuery.php} | 34 +++--- .../query/HarbormasterBuildLogQuery.php | 28 ++--- .../query/HarbormasterBuildTargetQuery.php | 38 ++++++ .../step/BuildStepImplementation.php | 10 +- ...sterHTTPRequestBuildStepImplementation.php | 6 +- .../RemoteCommandBuildStepImplementation.php | 8 +- .../step/SleepBuildStepImplementation.php | 2 +- .../step/VariableBuildStepImplementation.php | 53 --------- .../storage/build/HarbormasterBuild.php | 55 ++++++++- .../storage/build/HarbormasterBuildLog.php | 36 ++---- .../storage/build/HarbormasterBuildTarget.php | 109 +++++++++++++++++- .../configuration/HarbormasterBuildStep.php | 20 ---- .../worker/HarbormasterBuildWorker.php | 13 ++- .../patch/PhabricatorBuiltinPatchList.php | 4 + 17 files changed, 349 insertions(+), 154 deletions(-) create mode 100644 resources/sql/patches/20131205.buildtargets.sql rename src/applications/harbormaster/query/{HarbormasterBuildableArtifactQuery.php => HarbormasterBuildArtifactQuery.php} (70%) diff --git a/resources/sql/patches/20131205.buildtargets.sql b/resources/sql/patches/20131205.buildtargets.sql new file mode 100644 index 0000000000..cf8e33af08 --- /dev/null +++ b/resources/sql/patches/20131205.buildtargets.sql @@ -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; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index b91987885a..9a1e72db10 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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( diff --git a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php index b5f39cbf76..07d2b6ffbc 100644 --- a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php +++ b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php @@ -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(); diff --git a/src/applications/harbormaster/query/HarbormasterBuildableArtifactQuery.php b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php similarity index 70% rename from src/applications/harbormaster/query/HarbormasterBuildableArtifactQuery.php rename to src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php index 901335a0ca..e3decf26ae 100644 --- a/src/applications/harbormaster/query/HarbormasterBuildableArtifactQuery.php +++ b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php @@ -1,10 +1,10 @@ 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) { diff --git a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php index 000b267f9f..f25597f48e 100644 --- a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php +++ b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php @@ -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); diff --git a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php index 2d7e1fa7d9..aff82090ba 100644 --- a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php +++ b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php @@ -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'; } diff --git a/src/applications/harbormaster/step/BuildStepImplementation.php b/src/applications/harbormaster/step/BuildStepImplementation.php index 8e1df82abf..6848605bcb 100644 --- a/src/applications/harbormaster/step/BuildStepImplementation.php +++ b/src/applications/harbormaster/step/BuildStepImplementation.php @@ -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; } diff --git a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php index c68dbe143a..ba6f3e6c7e 100644 --- a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php @@ -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)) diff --git a/src/applications/harbormaster/step/RemoteCommandBuildStepImplementation.php b/src/applications/harbormaster/step/RemoteCommandBuildStepImplementation.php index adc8be7c6e..3829cea406 100644 --- a/src/applications/harbormaster/step/RemoteCommandBuildStepImplementation.php +++ b/src/applications/harbormaster/step/RemoteCommandBuildStepImplementation.php @@ -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(); diff --git a/src/applications/harbormaster/step/SleepBuildStepImplementation.php b/src/applications/harbormaster/step/SleepBuildStepImplementation.php index 0c51eaa881..120732226d 100644 --- a/src/applications/harbormaster/step/SleepBuildStepImplementation.php +++ b/src/applications/harbormaster/step/SleepBuildStepImplementation.php @@ -18,7 +18,7 @@ final class SleepBuildStepImplementation extends BuildStepImplementation { public function execute( HarbormasterBuild $build, - HarbormasterBuildStep $build_step) { + HarbormasterBuildTarget $build_target) { $settings = $this->getSettings(); diff --git a/src/applications/harbormaster/step/VariableBuildStepImplementation.php b/src/applications/harbormaster/step/VariableBuildStepImplementation.php index c81983d631..b41471c231 100644 --- a/src/applications/harbormaster/step/VariableBuildStepImplementation.php +++ b/src/applications/harbormaster/step/VariableBuildStepImplementation.php @@ -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"; diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php index c6d1393a05..3d9cca6b5a 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php @@ -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 )----------------------------------------- */ diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildLog.php b/src/applications/harbormaster/storage/build/HarbormasterBuildLog.php index e692170db3..e998e82abb 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildLog.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildLog.php @@ -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.'); } diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php b/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php index 1eec81d2ea..e3e743b0a6 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php @@ -1,10 +1,36 @@ 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.'); + } + } diff --git a/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php index cb9310d2aa..ccf1e5470b 100644 --- a/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php +++ b/src/applications/harbormaster/storage/configuration/HarbormasterBuildStep.php @@ -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 )----------------------------------------- */ diff --git a/src/applications/harbormaster/worker/HarbormasterBuildWorker.php b/src/applications/harbormaster/worker/HarbormasterBuildWorker.php index f2c3cce6cc..141d5e17ab 100644 --- a/src/applications/harbormaster/worker/HarbormasterBuildWorker.php +++ b/src/applications/harbormaster/worker/HarbormasterBuildWorker.php @@ -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; } diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php index 12fd491a1b..68a3ebbd90 100644 --- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php +++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php @@ -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'), + ), ); } }