mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-20 18:58:56 +01:00
Add staging area support to Harbormaster/Drydock + various fixes
Summary: Ref T9252. This primarily allows Harbormaster to request (and Drydock to fulfill) working copies with a patch from a staging area. Doing this means we can do builds on in-review changes from `arc diff`. This is a little cobbled-together but should basically work. Also fix some other issues: - Yielded, awakend workers are fine to update but could complain. - We can't log slot lock failures to resources if we don't end up saving them. - Killing the transaction would wipe out the log. - Fix some TODOs, etc. Test Plan: Ran Harbormaster builds on a local revision. Reviewers: hach-que, chad Reviewed By: chad Maniphest Tasks: T9252 Differential Revision: https://secure.phabricator.com/D14214
This commit is contained in:
parent
d4a0b1c870
commit
4496176924
9 changed files with 130 additions and 43 deletions
|
@ -446,6 +446,13 @@ final class DifferentialDiff
|
|||
$results['repository.phid'] = $repo->getPHID();
|
||||
$results['repository.vcs'] = $repo->getVersionControlSystem();
|
||||
$results['repository.uri'] = $repo->getPublicCloneURI();
|
||||
|
||||
// TODO: We're just hoping to get lucky. Instead, `arc` should store
|
||||
// where it sent changes and we should only provide staging details
|
||||
// if we reasonably believe they are accurate.
|
||||
$staging_ref = 'refs/tags/phabricator/diff/'.$this->getID();
|
||||
$results['repository.staging.uri'] = $repo->getStagingURI();
|
||||
$results['repository.staging.ref'] = $staging_ref;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,6 +473,10 @@ final class DifferentialDiff
|
|||
pht('The version control system, either "svn", "hg" or "git".'),
|
||||
'repository.uri' =>
|
||||
pht('The URI to clone or checkout the repository from.'),
|
||||
'repository.staging.uri' =>
|
||||
pht('The URI of the staging repository.'),
|
||||
'repository.staging.ref' =>
|
||||
pht('The ref name for this change in the staging repository.'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -295,14 +295,18 @@ abstract class DrydockBlueprintImplementation extends Phobject {
|
|||
$lease_status = $lease->getStatus();
|
||||
|
||||
switch ($lease_status) {
|
||||
case DrydockLeaseStatus::STATUS_PENDING:
|
||||
case DrydockLeaseStatus::STATUS_ACQUIRED:
|
||||
// TODO: Temporary failure.
|
||||
throw new Exception(pht('Lease still activating.'));
|
||||
throw new PhabricatorWorkerYieldException(15);
|
||||
case DrydockLeaseStatus::STATUS_ACTIVE:
|
||||
return;
|
||||
default:
|
||||
// TODO: Permanent failure.
|
||||
throw new Exception(pht('Lease in bad state.'));
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Lease ("%s") is in bad state ("%s"), expected "%s".',
|
||||
$lease->getPHID(),
|
||||
$lease_status,
|
||||
DrydockLeaseStatus::STATUS_ACTIVE));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -216,6 +216,8 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
$commit = idx($spec, 'commit');
|
||||
$branch = idx($spec, 'branch');
|
||||
|
||||
$ref = idx($spec, 'ref');
|
||||
|
||||
if ($commit !== null) {
|
||||
$cmd[] = 'git reset --hard %s';
|
||||
$arg[] = $commit;
|
||||
|
@ -225,6 +227,20 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
|
||||
$cmd[] = 'git reset --hard origin/%s';
|
||||
$arg[] = $branch;
|
||||
} else if ($ref) {
|
||||
$ref_uri = $ref['uri'];
|
||||
$ref_ref = $ref['ref'];
|
||||
|
||||
$cmd[] = 'git fetch --no-tags -- %s +%s:%s';
|
||||
$arg[] = $ref_uri;
|
||||
$arg[] = $ref_ref;
|
||||
$arg[] = $ref_ref;
|
||||
|
||||
$cmd[] = 'git checkout %s';
|
||||
$arg[] = $ref_ref;
|
||||
|
||||
$cmd[] = 'git reset --hard %s';
|
||||
$arg[] = $ref_ref;
|
||||
} else {
|
||||
$cmd[] = 'git reset --hard HEAD';
|
||||
}
|
||||
|
|
|
@ -107,6 +107,17 @@ final class DrydockBlueprint extends DrydockDAO
|
|||
return $this->fields;
|
||||
}
|
||||
|
||||
public function logEvent($type, array $data = array()) {
|
||||
$log = id(new DrydockLog())
|
||||
->setEpoch(PhabricatorTime::getNow())
|
||||
->setType($type)
|
||||
->setData($data);
|
||||
|
||||
$log->setBlueprintPHID($this->getPHID());
|
||||
|
||||
return $log->save();
|
||||
}
|
||||
|
||||
|
||||
/* -( Allocating Resources )----------------------------------------------- */
|
||||
|
||||
|
|
|
@ -233,18 +233,21 @@ final class DrydockLease extends DrydockDAO
|
|||
|
||||
$this->openTransaction();
|
||||
try {
|
||||
try {
|
||||
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
|
||||
$this->slotLocks = array();
|
||||
} catch (DrydockSlotLockException $ex) {
|
||||
$this->logEvent(
|
||||
DrydockSlotLockFailureLogType::LOGCONST,
|
||||
array(
|
||||
'locks' => $ex->getLockMap(),
|
||||
));
|
||||
throw $ex;
|
||||
}
|
||||
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
|
||||
$this->slotLocks = array();
|
||||
} catch (DrydockSlotLockException $ex) {
|
||||
$this->killTransaction();
|
||||
|
||||
$this->logEvent(
|
||||
DrydockSlotLockFailureLogType::LOGCONST,
|
||||
array(
|
||||
'locks' => $ex->getLockMap(),
|
||||
));
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
try {
|
||||
$this
|
||||
->setResourcePHID($resource->getPHID())
|
||||
->attachResource($resource)
|
||||
|
|
|
@ -148,19 +148,25 @@ final class DrydockResource extends DrydockDAO
|
|||
}
|
||||
|
||||
$this->openTransaction();
|
||||
try {
|
||||
try {
|
||||
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
|
||||
$this->slotLocks = array();
|
||||
} catch (DrydockSlotLockException $ex) {
|
||||
$this->logEvent(
|
||||
DrydockSlotLockFailureLogType::LOGCONST,
|
||||
array(
|
||||
'locks' => $ex->getLockMap(),
|
||||
));
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
try {
|
||||
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
|
||||
$this->slotLocks = array();
|
||||
} catch (DrydockSlotLockException $ex) {
|
||||
$this->killTransaction();
|
||||
|
||||
// NOTE: We have to log this on the blueprint, as the resource is not
|
||||
// going to be saved so the PHID will vanish.
|
||||
$this->getBlueprint()->logEvent(
|
||||
DrydockSlotLockFailureLogType::LOGCONST,
|
||||
array(
|
||||
'locks' => $ex->getLockMap(),
|
||||
));
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
try {
|
||||
$this
|
||||
->setStatus($new_status)
|
||||
->save();
|
||||
|
@ -168,6 +174,7 @@ final class DrydockResource extends DrydockDAO
|
|||
$this->killTransaction();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$this->saveTransaction();
|
||||
|
||||
$this->isAllocated = true;
|
||||
|
|
|
@ -660,9 +660,10 @@ final class DrydockLeaseUpdateWorker extends DrydockWorker {
|
|||
$lease->logEvent(DrydockLeaseReleasedLogType::LOGCONST);
|
||||
|
||||
$resource = $lease->getResource();
|
||||
$blueprint = $resource->getBlueprint();
|
||||
|
||||
$blueprint->didReleaseLease($resource, $lease);
|
||||
if ($resource) {
|
||||
$blueprint = $resource->getBlueprint();
|
||||
$blueprint->didReleaseLease($resource, $lease);
|
||||
}
|
||||
|
||||
$this->destroyLease($lease);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,13 @@ final class HarbormasterLeaseWorkingCopyBuildStepImplementation
|
|||
$variables = $build_target->getVariables();
|
||||
|
||||
$repository_phid = idx($variables, 'repository.phid');
|
||||
if (!$repository_phid) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Unable to determine how to clone the repository for this '.
|
||||
'buildable: it is not associated with a tracked repository.'));
|
||||
}
|
||||
|
||||
$also_phids = $build_target->getFieldValue('repositoryPHIDs');
|
||||
|
||||
$all_phids = $also_phids;
|
||||
|
@ -133,8 +140,6 @@ final class HarbormasterLeaseWorkingCopyBuildStepImplementation
|
|||
}
|
||||
}
|
||||
|
||||
$commit = idx($variables, 'repository.commit');
|
||||
|
||||
$map = array();
|
||||
|
||||
foreach ($also_phids as $also_phid) {
|
||||
|
@ -147,12 +152,33 @@ final class HarbormasterLeaseWorkingCopyBuildStepImplementation
|
|||
|
||||
$repository = $repositories[$repository_phid];
|
||||
|
||||
$commit = idx($variables, 'repository.commit');
|
||||
$ref_uri = idx($variables, 'repository.staging.uri');
|
||||
$ref_ref = idx($variables, 'repository.staging.ref');
|
||||
if ($commit) {
|
||||
$spec = array(
|
||||
'commit' => $commit,
|
||||
);
|
||||
} else if ($ref_uri && $ref_ref) {
|
||||
$spec = array(
|
||||
'ref' => array(
|
||||
'uri' => $ref_uri,
|
||||
'ref' => $ref_ref,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Unable to determine how to fetch changes: this buildable does not '.
|
||||
'identify a commit or a staging ref. You may need to configure a '.
|
||||
'repository staging area.'));
|
||||
}
|
||||
|
||||
$directory = $repository->getCloneName();
|
||||
$map[$directory] = array(
|
||||
'phid' => $repository->getPHID(),
|
||||
'commit' => $commit,
|
||||
'default' => true,
|
||||
);
|
||||
) + $spec;
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
|
|
@ -86,15 +86,23 @@ final class PhabricatorWorkerActiveTask extends PhabricatorWorkerTask {
|
|||
}
|
||||
|
||||
protected function checkLease() {
|
||||
if ($this->leaseOwner) {
|
||||
$current_server_time = $this->serverTime + (time() - $this->localTime);
|
||||
if ($current_server_time >= $this->leaseExpires) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Trying to update Task %d (%s) after lease expiration!',
|
||||
$this->getID(),
|
||||
$this->getTaskClass()));
|
||||
}
|
||||
$owner = $this->leaseOwner;
|
||||
|
||||
if (!$owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($owner == PhabricatorWorker::YIELD_OWNER) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_server_time = $this->serverTime + (time() - $this->localTime);
|
||||
if ($current_server_time >= $this->leaseExpires) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Trying to update Task %d (%s) after lease expiration!',
|
||||
$this->getID(),
|
||||
$this->getTaskClass()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue