Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php
12256 views
1
<?php
2
3
final class HarbormasterLeaseWorkingCopyBuildStepImplementation
4
extends HarbormasterBuildStepImplementation {
5
6
public function getName() {
7
return pht('Lease Working Copy');
8
}
9
10
public function getGenericDescription() {
11
return pht('Build a working copy in Drydock.');
12
}
13
14
public function getBuildStepGroupKey() {
15
return HarbormasterDrydockBuildStepGroup::GROUPKEY;
16
}
17
18
public function execute(
19
HarbormasterBuild $build,
20
HarbormasterBuildTarget $build_target) {
21
$viewer = PhabricatorUser::getOmnipotentUser();
22
23
$settings = $this->getSettings();
24
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');
28
29
if ($lease_phid) {
30
$lease = id(new DrydockLeaseQuery())
31
->setViewer($viewer)
32
->withPHIDs(array($lease_phid))
33
->executeOne();
34
if (!$lease) {
35
throw new PhabricatorWorkerPermanentFailureException(
36
pht(
37
'Lease "%s" could not be loaded.',
38
$lease_phid));
39
}
40
} else {
41
$working_copy_type = id(new DrydockWorkingCopyBlueprintImplementation())
42
->getType();
43
44
$allowed_phids = $build_target->getFieldValue('blueprintPHIDs');
45
if (!is_array($allowed_phids)) {
46
$allowed_phids = array();
47
}
48
$authorizing_phid = $build_target->getBuildStep()->getPHID();
49
50
$lease = DrydockLease::initializeNewLease()
51
->setResourceType($working_copy_type)
52
->setOwnerPHID($build_target->getPHID())
53
->setAuthorizingPHID($authorizing_phid)
54
->setAllowedBlueprintPHIDs($allowed_phids);
55
56
$map = $this->buildRepositoryMap($build_target);
57
58
$lease->setAttribute('repositories.map', $map);
59
60
$task_id = $this->getCurrentWorkerTaskID();
61
if ($task_id) {
62
$lease->setAwakenTaskIDs(array($task_id));
63
}
64
65
// TODO: Maybe add a method to mark artifacts like this as pending?
66
67
// Create the artifact now so that the lease is always disposed of, even
68
// if this target is aborted.
69
$build_target->createArtifact(
70
$viewer,
71
$settings['name'],
72
HarbormasterWorkingCopyArtifact::ARTIFACTCONST,
73
array(
74
'drydockLeasePHID' => $lease->getPHID(),
75
));
76
77
$lease->queueForActivation();
78
79
$build_target
80
->setDetail('exec.leasePHID', $lease->getPHID())
81
->save();
82
}
83
84
if ($lease->isActivating()) {
85
// TODO: Smart backoff?
86
throw new PhabricatorWorkerYieldException(15);
87
}
88
89
if (!$lease->isActive()) {
90
// TODO: We could just forget about this lease and retry?
91
throw new PhabricatorWorkerPermanentFailureException(
92
pht(
93
'Lease "%s" never activated.',
94
$lease->getPHID()));
95
}
96
}
97
98
public function getArtifactOutputs() {
99
return array(
100
array(
101
'name' => pht('Working Copy'),
102
'key' => $this->getSetting('name'),
103
'type' => HarbormasterWorkingCopyArtifact::ARTIFACTCONST,
104
),
105
);
106
}
107
108
public function getFieldSpecifications() {
109
return array(
110
'name' => array(
111
'name' => pht('Artifact Name'),
112
'type' => 'text',
113
'required' => true,
114
),
115
'blueprintPHIDs' => array(
116
'name' => pht('Use Blueprints'),
117
'type' => 'blueprints',
118
'required' => true,
119
),
120
'repositoryPHIDs' => array(
121
'name' => pht('Also Clone'),
122
'type' => 'datasource',
123
'datasource.class' => 'DiffusionRepositoryDatasource',
124
),
125
);
126
}
127
128
private function buildRepositoryMap(HarbormasterBuildTarget $build_target) {
129
$viewer = PhabricatorUser::getOmnipotentUser();
130
$variables = $build_target->getVariables();
131
132
$repository_phid = idx($variables, 'repository.phid');
133
if (!$repository_phid) {
134
throw new Exception(
135
pht(
136
'Unable to determine how to clone the repository for this '.
137
'buildable: it is not associated with a tracked repository.'));
138
}
139
140
$also_phids = $build_target->getFieldValue('repositoryPHIDs');
141
if (!is_array($also_phids)) {
142
$also_phids = array();
143
}
144
145
$all_phids = $also_phids;
146
$all_phids[] = $repository_phid;
147
148
$repositories = id(new PhabricatorRepositoryQuery())
149
->setViewer($viewer)
150
->withPHIDs($all_phids)
151
->execute();
152
$repositories = mpull($repositories, null, 'getPHID');
153
154
foreach ($all_phids as $phid) {
155
if (empty($repositories[$phid])) {
156
throw new PhabricatorWorkerPermanentFailureException(
157
pht(
158
'Unable to load repository with PHID "%s".',
159
$phid));
160
}
161
}
162
163
$map = array();
164
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',
170
);
171
}
172
173
$repository = $repositories[$repository_phid];
174
175
$commit = idx($variables, 'buildable.commit');
176
$ref_uri = idx($variables, 'repository.staging.uri');
177
$ref_ref = idx($variables, 'repository.staging.ref');
178
if ($commit) {
179
$spec = array(
180
'commit' => $commit,
181
);
182
} else if ($ref_uri && $ref_ref) {
183
$spec = array(
184
'ref' => array(
185
'uri' => $ref_uri,
186
'ref' => $ref_ref,
187
),
188
);
189
} else {
190
throw new Exception(
191
pht(
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.'));
195
}
196
197
$directory = $repository->getCloneName();
198
$map[$directory] = array(
199
'phid' => $repository->getPHID(),
200
'default' => true,
201
) + $spec;
202
203
return $map;
204
}
205
206
}
207
208