1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-28 09:42:41 +01:00
phorge-phorge/src/applications/harbormaster/artifact/HarbormasterDrydockLeaseArtifact.php
epriestley 4cf1270ecd In Harbormaster, make sure artifacts are destroyed even if a build is aborted
Summary:
Ref T9252. Currently, Harbormaster and Drydock work like this in some cases:

  # Queue a lease for activation.
  # Then, a little later, save the lease PHID somewhere.
  # When the target/resource is destroyed, destroy the lease.

However, something can happen between (1) and (2). In Drydock this window is very short and the "something" would have to be a lighting strike or something similar, but in Harbormaster we wait until the resource activates to do (2) so the window can be many minutes long. In particular, a user can use "Abort Build" during those many minutes.

If they do, the target is destroyed but it doesn't yet have a record of the artifact, so the artifact isn't cleaned up.

Make these things work like this instead:

  # Create a new lease and pre-generate a PHID for it.
  # Save that PHID as something that needs to be cleaned up.
  # Queue the lease for activation.
  # When the target/resource is destroyed, destroy the lease if it exists.

This makes sure there's no step in the process where we might lose track of a lease/resource.

Also, clean up and standardize some other stuff I hit.

Test Plan:
  - Stopped daemons.
  - Restarted a build in Harbormaster.
  - Stepped through the build one stage at a time using `bin/worker execute ...`.
  - After the lease was queued, but before it activated, aborted the build.
  - Processed the Harbormaster side of things only.
  - Saw the lease get destroyed properly.

Reviewers: chad, hach-que

Reviewed By: hach-que

Maniphest Tasks: T9252

Differential Revision: https://secure.phabricator.com/D14234
2015-10-05 05:58:53 -07:00

83 lines
2.2 KiB
PHP

<?php
abstract class HarbormasterDrydockLeaseArtifact
extends HarbormasterArtifact {
public function getArtifactParameterSpecification() {
return array(
'drydockLeasePHID' => 'string',
);
}
public function getArtifactParameterDescriptions() {
return array(
'drydockLeasePHID' => pht(
'Drydock working copy lease to create an artifact from.'),
);
}
public function getArtifactDataExample() {
return array(
'drydockLeasePHID' => 'PHID-DRYL-abcdefghijklmnopqrst',
);
}
public function renderArtifactSummary(PhabricatorUser $viewer) {
$artifact = $this->getBuildArtifact();
$lease_phid = $artifact->getProperty('drydockLeasePHID');
return $viewer->renderHandle($lease_phid);
}
public function willCreateArtifact(PhabricatorUser $actor) {
// We don't load the lease here because it's expected that artifacts are
// created before leases actually exist. This guarantees that the leases
// will be cleaned up.
}
public function loadArtifactLease(PhabricatorUser $viewer) {
$artifact = $this->getBuildArtifact();
$lease_phid = $artifact->getProperty('drydockLeasePHID');
$lease = id(new DrydockLeaseQuery())
->setViewer($viewer)
->withPHIDs(array($lease_phid))
->executeOne();
if (!$lease) {
throw new Exception(
pht(
'Drydock lease PHID "%s" does not correspond to a valid lease.',
$lease_phid));
}
return $lease;
}
public function releaseArtifact(PhabricatorUser $actor) {
try {
$lease = $this->loadArtifactLease($actor);
} catch (Exception $ex) {
// If we can't load the lease, treat it as already released. Artifacts
// are generated before leases are queued, so it's possible to arrive
// here under normal conditions.
return;
}
if (!$lease->canRelease()) {
return;
}
$author_phid = $actor->getPHID();
if (!$author_phid) {
$author_phid = id(new PhabricatorHarbormasterApplication())->getPHID();
}
$command = DrydockCommand::initializeNewCommand($actor)
->setTargetPHID($lease->getPHID())
->setAuthorPHID($author_phid)
->setCommand(DrydockCommand::COMMAND_RELEASE)
->save();
$lease->scheduleUpdate();
}
}