Page MenuHomePhabricator

D7745.id17526.diff

D7745.id17526.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/query/HarbormasterBuildQuery.php b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
--- a/src/applications/harbormaster/query/HarbormasterBuildQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
@@ -8,6 +8,7 @@
private $buildStatuses;
private $buildablePHIDs;
private $buildPlanPHIDs;
+ private $idLessThan;
public function withIDs(array $ids) {
$this->ids = $ids;
@@ -34,6 +35,11 @@
return $this;
}
+ public function withIDLessThan($id) {
+ $this->idLessThan = $id;
+ return $this;
+ }
+
protected function loadPage() {
$table = new HarbormasterBuild();
$conn_r = $table->establishConnection('r');
@@ -133,6 +139,15 @@
$this->buildPlanPHIDs);
}
+ // This is probably susceptable to the odd / even ID situation. The
+ // only way to fix this would be to add a sequence column to build table.
+ if ($this->idLessThan) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'id < %d',
+ $this->idLessThan);
+ }
+
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
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/p3/be/nprygwnnlbjp6nvm
Default Alt Text
D7745.id17526.diff (8 KB)

Event Timeline