1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-29 17:00:59 +01:00

Implement "Wait for Previous Builds" build step

Summary: This adds a build step which will block a build from continuing if there are previous builds of the build plan still running.

Test Plan: Configured a build plan with a wait of 60 seconds and a "wait for previous builds", then started a build.  While that was still building, reconfigured the plan to have a wait time of 3 seconds, started it, and saw it move into the "Waiting" status.  When the 60 second build finished, both builds passed.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley

CC: Korvin, epriestley, aran

Maniphest Tasks: T1049

Differential Revision: https://secure.phabricator.com/D7745
This commit is contained in:
James Rhodes 2013-12-10 11:02:34 +11:00
parent de969ab540
commit 270c8d27ab
6 changed files with 144 additions and 5 deletions

View file

@ -2366,6 +2366,7 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'UploadArtifactBuildStepImplementation' => 'VariableBuildStepImplementation',
'VariableBuildStepImplementation' => 'BuildStepImplementation',
'WaitForPreviousBuildStepImplementation' => 'BuildStepImplementation',
),
));

View file

@ -49,7 +49,10 @@ final class HarbormasterBuildViewController
$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 @@ final class HarbormasterBuildViewController
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:

View file

@ -52,8 +52,8 @@ final class HarbormasterBuildableViewController
$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');

View file

@ -53,7 +53,7 @@ abstract class BuildStepImplementation {
/**
* Validate the current settings of this build step.
*/
public function validate() {
public function validateSettings() {
return true;
}

View file

@ -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 the current plan '.
'before continuing.');
}
public function getDescription() {
return pht(
'Wait for previous commits to finish building the current plan '.
'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;
}
}

View file

@ -94,6 +94,13 @@ final class HarbormasterBuild extends HarbormasterDAO
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,