Page MenuHomePhabricator

D7745.id17527.diff

D7745.id17527.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2366,6 +2366,7 @@
'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php',
'UploadArtifactBuildStepImplementation' => 'applications/harbormaster/step/UploadArtifactBuildStepImplementation.php',
'VariableBuildStepImplementation' => 'applications/harbormaster/step/VariableBuildStepImplementation.php',
+ 'WaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/WaitForPreviousBuildStepImplementation.php',
),
'function' =>
array(
@@ -5056,5 +5057,6 @@
'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'UploadArtifactBuildStepImplementation' => 'VariableBuildStepImplementation',
'VariableBuildStepImplementation' => 'BuildStepImplementation',
+ 'WaitForPreviousBuildStepImplementation' => 'BuildStepImplementation',
),
));
diff --git a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php
--- a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php
+++ b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php
@@ -49,7 +49,10 @@
$targets = array();
foreach ($build_targets as $build_target) {
$header = id(new PHUIHeaderView())
- ->setHeader(pht('Build Target %d', $build_target->getID()))
+ ->setHeader(pht(
+ 'Build Target %d (%s)',
+ $build_target->getID(),
+ $build_target->getImplementation()->getName()))
->setUser($viewer);
$properties = new PHUIPropertyListView();
@@ -280,7 +283,7 @@
case HarbormasterBuild::STATUS_PENDING:
return pht('Pending');
case HarbormasterBuild::STATUS_WAITING:
- return pht('Waiting on Resource');
+ return pht('Waiting');
case HarbormasterBuild::STATUS_BUILDING:
return pht('Building');
case HarbormasterBuild::STATUS_PASSED:
diff --git a/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
--- a/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
+++ b/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php
@@ -52,8 +52,8 @@
$item->addAttribute(pht('Pending'));
break;
case HarbormasterBuild::STATUS_WAITING:
- $item->setBarColor('blue');
- $item->addAttribute(pht('Waiting on Resource'));
+ $item->setBarColor('violet');
+ $item->addAttribute(pht('Waiting'));
break;
case HarbormasterBuild::STATUS_BUILDING:
$item->setBarColor('yellow');
diff --git a/src/applications/harbormaster/step/BuildStepImplementation.php b/src/applications/harbormaster/step/BuildStepImplementation.php
--- a/src/applications/harbormaster/step/BuildStepImplementation.php
+++ b/src/applications/harbormaster/step/BuildStepImplementation.php
@@ -53,7 +53,7 @@
/**
* Validate the current settings of this build step.
*/
- public function validate() {
+ public function validateSettings() {
return true;
}
diff --git a/src/applications/harbormaster/step/WaitForPreviousBuildStepImplementation.php b/src/applications/harbormaster/step/WaitForPreviousBuildStepImplementation.php
new file mode 100644
--- /dev/null
+++ b/src/applications/harbormaster/step/WaitForPreviousBuildStepImplementation.php
@@ -0,0 +1,127 @@
+<?php
+
+final class WaitForPreviousBuildStepImplementation
+ extends BuildStepImplementation {
+
+ public function getName() {
+ return pht('Wait for Previous Commits to Build');
+ }
+
+ public function getGenericDescription() {
+ return pht(
+ 'Wait for previous commits to finish building '.
+ 'before continuing.');
+ }
+
+ public function getDescription() {
+ return pht(
+ 'Wait for previous commits to finish building '.
+ 'before continuing.');
+ }
+
+ public function execute(
+ HarbormasterBuild $build,
+ HarbormasterBuildTarget $build_target) {
+
+ // We can only wait when building against commits.
+ $buildable = $build->getBuildable();
+ $object = $buildable->getBuildableObject();
+ if (!($object instanceof PhabricatorRepositoryCommit)) {
+ return;
+ }
+
+ // We are blocked until all previous builds finish.
+ $build->setBuildStatus(HarbormasterBuild::STATUS_WAITING);
+ $build->save();
+
+ // Block until all previous builds of the same build plan have
+ // finished.
+ $plan = $build->getBuildPlan();
+
+ $log = null;
+ $log_start = null;
+ $blockers = $this->getBlockers($object, $plan, $build);
+ while (count($blockers) > 0) {
+ if ($build->checkForCancellation()) {
+ if ($log !== null) {
+ $log->finalize($log_start);
+ }
+ return;
+ }
+
+ if ($log === null) {
+ $log = $build->createLog($build_target, "waiting", "blockers");
+ $log_start = $log->start();
+ }
+
+ $log->append("Blocked by: ".implode(",", $blockers)."\n");
+
+ sleep(1);
+ $blockers = $this->getBlockers($object, $plan, $build);
+ }
+ if ($log !== null) {
+ $log->finalize($log_start);
+ }
+
+ // Move back into building status.
+ $build->setBuildStatus(HarbormasterBuild::STATUS_BUILDING);
+ $build->save();
+ }
+
+ private function getBlockers(
+ PhabricatorRepositoryCommit $commit,
+ HarbormasterBuildPlan $plan,
+ HarbormasterBuild $source) {
+
+ $call = new ConduitCall(
+ 'diffusion.commitparentsquery',
+ array(
+ 'commit' => $commit->getCommitIdentifier(),
+ 'callsign' => $commit->getRepository()->getCallsign()
+ ));
+ $call->setUser(PhabricatorUser::getOmnipotentUser());
+ $parents = $call->execute();
+
+ $hashes = array();
+ foreach ($parents as $parent => $obj) {
+ $hashes[] = $parent;
+ }
+
+ $parents = id(new DiffusionCommitQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withRepository($commit->getRepository())
+ ->withIdentifiers($hashes)
+ ->execute();
+
+ $blockers = array();
+
+ $build_objects = array();
+ foreach ($parents as $parent) {
+ if (!$parent->isImported()) {
+ $blockers[] = pht('Commit %s', $parent->getCommitIdentifier());
+ } else {
+ $build_objects[] = $parent->getPHID();
+ }
+ }
+
+ $buildables = id(new HarbormasterBuildableQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withBuildablePHIDs($build_objects)
+ ->execute();
+ $buildable_phids = mpull($buildables, 'getPHID');
+
+ $builds = id(new HarbormasterBuildQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withBuildablePHIDs($buildable_phids)
+ ->withBuildPlanPHIDs(array($plan->getPHID()))
+ ->execute();
+
+ foreach ($builds as $build) {
+ if ($build->isBuilding()) {
+ $blockers[] = pht('Build %d', $build->getID());
+ }
+ }
+
+ return $blockers;
+ }
+}
diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
--- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php
+++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
@@ -94,6 +94,13 @@
return $this->assertAttached($this->buildPlan);
}
+ public function isBuilding() {
+ return $this->getBuildStatus() === self::STATUS_PENDING ||
+ $this->getBuildStatus() === self::STATUS_WAITING ||
+ $this->getBuildStatus() === self::STATUS_BUILDING ||
+ $this->getCancelRequested();
+ }
+
public function createLog(
HarbormasterBuildTarget $build_target,
$log_source,

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/27/7n/zp5ukv7zawciitmk
Default Alt Text
D7745.id17527.diff (7 KB)

Event Timeline