1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 16:22:43 +01:00

Implement build generations in Harbormaster

Summary:
Ref T5932.  Ref T5936.  This implements build generations in Harbormaster, which provides the infrastructure required to both show users the previous states of restarted builds and to allow users to forcefully abort builds (and their targets).

You can view previous generations of a build by adding `?g=<n>` to the URI, but this isn't exposed in the UI anywhere yet.

Test Plan: Ran a build plan with a Sleep step in it.  Reconfigured it for various sleep times and viewed previous generations of the build after restarting it.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: epriestley, Korvin

Maniphest Tasks: T5932, T5936

Differential Revision: https://secure.phabricator.com/D10321
This commit is contained in:
James Rhodes 2014-08-21 22:55:24 +10:00
parent a2a0f002f0
commit efadfbbc97
7 changed files with 54 additions and 26 deletions

View file

@ -0,0 +1,5 @@
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_build
ADD COLUMN `buildGeneration` INT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildtarget
ADD COLUMN `buildGeneration` INT UNSIGNED NOT NULL DEFAULT 0;

View file

@ -14,6 +14,7 @@ final class HarbormasterBuildViewController
$viewer = $request->getUser();
$id = $this->id;
$generation = $request->getInt('g');
$build = id(new HarbormasterBuildQuery())
->setViewer($viewer)
@ -52,13 +53,18 @@ final class HarbormasterBuildViewController
'/'.$build->getBuildable()->getMonogram());
$crumbs->addTextCrumb($title);
if ($generation === null || $generation > $build->getBuildGeneration() ||
$generation < 0) {
$generation = $build->getBuildGeneration();
}
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($viewer)
->needBuildSteps(true)
->withBuildPHIDs(array($build->getPHID()))
->withBuildGenerations(array($generation))
->execute();
if ($build_targets) {
$messages = id(new HarbormasterBuildMessageQuery())
->setViewer($viewer)
@ -434,10 +440,13 @@ final class HarbormasterBuildViewController
pht('Build Plan'),
$handles[$build->getBuildPlanPHID()]->renderLink());
$properties->addProperty(
pht('Restarts'),
$build->getBuildGeneration());
$properties->addProperty(
pht('Status'),
$this->getStatus($build));
}
private function getStatus(HarbormasterBuild $build) {

View file

@ -100,7 +100,7 @@ final class HarbormasterBuildEngine extends Phobject {
private function updateBuild(HarbormasterBuild $build) {
if (($build->getBuildStatus() == HarbormasterBuild::STATUS_PENDING) ||
($build->isRestarting())) {
$this->destroyBuildTargets($build);
$this->restartBuild($build);
$build->setBuildStatus(HarbormasterBuild::STATUS_BUILDING);
$build->save();
}
@ -122,38 +122,28 @@ final class HarbormasterBuildEngine extends Phobject {
}
}
private function destroyBuildTargets(HarbormasterBuild $build) {
private function restartBuild(HarbormasterBuild $build) {
// We're restarting the build, so release all previous artifacts.
$this->releaseAllArtifacts($build);
$targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withBuildPHIDs(array($build->getPHID()))
->execute();
// Increment the build generation counter on the build.
$build->setBuildGeneration($build->getBuildGeneration() + 1);
if (!$targets) {
return;
}
// TODO: Currently running targets should periodically check their build
// generation (which won't have changed) against the build's generation.
// If it is different, they should automatically stop what they're doing
// and abort.
$target_phids = mpull($targets, 'getPHID');
$artifacts = id(new HarbormasterBuildArtifactQuery())
->setViewer($this->getViewer())
->withBuildTargetPHIDs($target_phids)
->execute();
foreach ($artifacts as $artifact) {
$artifact->delete();
}
foreach ($targets as $target) {
$target->delete();
}
// Previously we used to delete targets, logs and artifacts here. Instead
// leave them around so users can view previous generations of this build.
}
private function updateBuildSteps(HarbormasterBuild $build) {
$targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withBuildPHIDs(array($build->getPHID()))
->withBuildGenerations(array($build->getBuildGeneration()))
->execute();
$this->updateWaitingTargets($targets);
@ -454,6 +444,7 @@ final class HarbormasterBuildEngine extends Phobject {
$targets = id(new HarbormasterBuildTargetQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withBuildPHIDs(array($build->getPHID()))
->withBuildGenerations(array($build->getBuildGeneration()))
->execute();
if (count($targets) === 0) {

View file

@ -122,6 +122,13 @@ final class HarbormasterBuildQuery
$targets = mgroup($targets, 'getBuildPHID');
foreach ($page as $build) {
$build_targets = idx($targets, $build->getPHID(), array());
foreach ($build_targets as $phid => $target) {
if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
unset($build_targets[$phid]);
}
}
$build->attachBuildTargets($build_targets);
}
}

View file

@ -6,6 +6,7 @@ final class HarbormasterBuildTargetQuery
private $ids;
private $phids;
private $buildPHIDs;
private $buildGenerations;
private $needBuildSteps;
public function withIDs(array $ids) {
@ -23,6 +24,11 @@ final class HarbormasterBuildTargetQuery
return $this;
}
public function withBuildGenerations(array $build_generations) {
$this->buildGenerations = $build_generations;
return $this;
}
public function needBuildSteps($need_build_steps) {
$this->needBuildSteps = $need_build_steps;
return $this;
@ -67,6 +73,13 @@ final class HarbormasterBuildTargetQuery
$this->buildPHIDs);
}
if ($this->buildGenerations) {
$where[] = qsprintf(
$conn_r,
'buildGeneration in (%Ld)',
$this->buildGenerations);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);

View file

@ -6,6 +6,7 @@ final class HarbormasterBuild extends HarbormasterDAO
protected $buildablePHID;
protected $buildPlanPHID;
protected $buildStatus;
protected $buildGeneration;
private $buildable = self::ATTACHABLE;
private $buildPlan = self::ATTACHABLE;

View file

@ -12,6 +12,7 @@ final class HarbormasterBuildTarget extends HarbormasterDAO
protected $targetStatus;
protected $dateStarted;
protected $dateCompleted;
protected $buildGeneration;
const STATUS_PENDING = 'target/pending';
const STATUS_BUILDING = 'target/building';
@ -82,7 +83,8 @@ final class HarbormasterBuildTarget extends HarbormasterDAO
->setClassName($build_step->getClassName())
->setDetails($build_step->getDetails())
->setTargetStatus(self::STATUS_PENDING)
->setVariables($variables);
->setVariables($variables)
->setBuildGeneration($build->getBuildGeneration());
}
public function getConfiguration() {