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:
parent
de969ab540
commit
270c8d27ab
6 changed files with 144 additions and 5 deletions
|
@ -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',
|
||||
),
|
||||
));
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -53,7 +53,7 @@ abstract class BuildStepImplementation {
|
|||
/**
|
||||
* Validate the current settings of this build step.
|
||||
*/
|
||||
public function validate() {
|
||||
public function validateSettings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue