3 final class HarbormasterLeaseWorkingCopyBuildStepImplementation
4 extends HarbormasterBuildStepImplementation
{
6 public function getName() {
7 return pht('Lease Working Copy');
10 public function getGenericDescription() {
11 return pht('Build a working copy in Drydock.');
14 public function getBuildStepGroupKey() {
15 return HarbormasterDrydockBuildStepGroup
::GROUPKEY
;
18 public function execute(
19 HarbormasterBuild
$build,
20 HarbormasterBuildTarget
$build_target) {
21 $viewer = PhabricatorUser
::getOmnipotentUser();
23 $settings = $this->getSettings();
25 // TODO: We should probably have a separate temporary storage area for
26 // execution stuff that doesn't step on configuration state?
27 $lease_phid = $build_target->getDetail('exec.leasePHID');
30 $lease = id(new DrydockLeaseQuery())
32 ->withPHIDs(array($lease_phid))
35 throw new PhabricatorWorkerPermanentFailureException(
37 'Lease "%s" could not be loaded.',
41 $working_copy_type = id(new DrydockWorkingCopyBlueprintImplementation())
44 $allowed_phids = $build_target->getFieldValue('blueprintPHIDs');
45 if (!is_array($allowed_phids)) {
46 $allowed_phids = array();
48 $authorizing_phid = $build_target->getBuildStep()->getPHID();
50 $lease = DrydockLease
::initializeNewLease()
51 ->setResourceType($working_copy_type)
52 ->setOwnerPHID($build_target->getPHID())
53 ->setAuthorizingPHID($authorizing_phid)
54 ->setAllowedBlueprintPHIDs($allowed_phids);
56 $map = $this->buildRepositoryMap($build_target);
58 $lease->setAttribute('repositories.map', $map);
60 $task_id = $this->getCurrentWorkerTaskID();
62 $lease->setAwakenTaskIDs(array($task_id));
65 // TODO: Maybe add a method to mark artifacts like this as pending?
67 // Create the artifact now so that the lease is always disposed of, even
68 // if this target is aborted.
69 $build_target->createArtifact(
72 HarbormasterWorkingCopyArtifact
::ARTIFACTCONST
,
74 'drydockLeasePHID' => $lease->getPHID(),
77 $lease->queueForActivation();
80 ->setDetail('exec.leasePHID', $lease->getPHID())
84 if ($lease->isActivating()) {
85 // TODO: Smart backoff?
86 throw new PhabricatorWorkerYieldException(15);
89 if (!$lease->isActive()) {
90 // TODO: We could just forget about this lease and retry?
91 throw new PhabricatorWorkerPermanentFailureException(
93 'Lease "%s" never activated.',
98 public function getArtifactOutputs() {
101 'name' => pht('Working Copy'),
102 'key' => $this->getSetting('name'),
103 'type' => HarbormasterWorkingCopyArtifact
::ARTIFACTCONST
,
108 public function getFieldSpecifications() {
111 'name' => pht('Artifact Name'),
115 'blueprintPHIDs' => array(
116 'name' => pht('Use Blueprints'),
117 'type' => 'blueprints',
120 'repositoryPHIDs' => array(
121 'name' => pht('Also Clone'),
122 'type' => 'datasource',
123 'datasource.class' => 'DiffusionRepositoryDatasource',
128 private function buildRepositoryMap(HarbormasterBuildTarget
$build_target) {
129 $viewer = PhabricatorUser
::getOmnipotentUser();
130 $variables = $build_target->getVariables();
132 $repository_phid = idx($variables, 'repository.phid');
133 if (!$repository_phid) {
136 'Unable to determine how to clone the repository for this '.
137 'buildable: it is not associated with a tracked repository.'));
140 $also_phids = $build_target->getFieldValue('repositoryPHIDs');
141 if (!is_array($also_phids)) {
142 $also_phids = array();
145 $all_phids = $also_phids;
146 $all_phids[] = $repository_phid;
148 $repositories = id(new PhabricatorRepositoryQuery())
150 ->withPHIDs($all_phids)
152 $repositories = mpull($repositories, null, 'getPHID');
154 foreach ($all_phids as $phid) {
155 if (empty($repositories[$phid])) {
156 throw new PhabricatorWorkerPermanentFailureException(
158 'Unable to load repository with PHID "%s".',
165 foreach ($also_phids as $also_phid) {
166 $also_repo = $repositories[$also_phid];
167 $map[$also_repo->getCloneName()] = array(
168 'phid' => $also_repo->getPHID(),
169 'branch' => 'master',
173 $repository = $repositories[$repository_phid];
175 $commit = idx($variables, 'buildable.commit');
176 $ref_uri = idx($variables, 'repository.staging.uri');
177 $ref_ref = idx($variables, 'repository.staging.ref');
182 } else if ($ref_uri && $ref_ref) {
192 'Unable to determine how to fetch changes: this buildable does not '.
193 'identify a commit or a staging ref. You may need to configure a '.
194 'repository staging area.'));
197 $directory = $repository->getCloneName();
198 $map[$directory] = array(
199 'phid' => $repository->getPHID(),