This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Class representing a single deplyoment (passed or failed) at a time to a particular environment |
||
5 | * |
||
6 | * @property string $SHA |
||
7 | * @property string $ResqueToken |
||
8 | * @property string $State |
||
9 | * @property int $RefType |
||
10 | * @property string $RefName |
||
11 | * @property SS_Datetime $DeployStarted |
||
12 | * @property SS_Datetime $DeployRequested |
||
13 | * |
||
14 | * @method DNEnvironment Environment() |
||
15 | * @property int EnvironmentID |
||
16 | * @method Member Deployer() |
||
17 | * @property int DeployerID |
||
18 | */ |
||
19 | class DNDeployment extends DataObject implements Finite\StatefulInterface, HasStateMachine { |
||
0 ignored issues
–
show
The property $default_sort is not named in camelCase.
This check marks property names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The property $summary_fields is not named in camelCase.
This check marks property names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
20 | |||
21 | const STATE_NEW = 'New'; |
||
22 | const STATE_SUBMITTED = 'Submitted'; |
||
23 | const STATE_INVALID = 'Invalid'; |
||
24 | const STATE_APPROVED = 'Approved'; |
||
25 | const STATE_REJECTED = 'Rejected'; |
||
26 | const STATE_QUEUED = 'Queued'; |
||
27 | const STATE_DEPLOYING = 'Deploying'; |
||
28 | const STATE_ABORTING = 'Aborting'; |
||
29 | const STATE_COMPLETED = 'Completed'; |
||
30 | const STATE_FAILED = 'Failed'; |
||
31 | // Deleted is used as 'soft-delete' which will in all regards keep the record in the DB |
||
32 | // but not display it in the UI. This is for auditing and also for UI history updates |
||
33 | const STATE_DELETED = 'Deleted'; |
||
34 | |||
35 | const TR_NEW = 'new'; |
||
36 | const TR_SUBMIT = 'submit'; |
||
37 | const TR_INVALIDATE = 'invalidate'; |
||
38 | const TR_APPROVE = 'approve'; |
||
39 | const TR_REJECT = 'reject'; |
||
40 | const TR_QUEUE = 'queue'; |
||
41 | const TR_DEPLOY = 'deploy'; |
||
42 | const TR_ABORT = 'abort'; |
||
43 | const TR_COMPLETE = 'complete'; |
||
44 | const TR_FAIL = 'fail'; |
||
45 | const TR_DELETE = 'delete'; |
||
46 | |||
47 | /** |
||
48 | * @var array |
||
49 | */ |
||
50 | private static $db = array( |
||
51 | "SHA" => "GitSHA", |
||
52 | "ResqueToken" => "Varchar(255)", |
||
53 | // is it a branch, tag etc, see GitDispatcher REF_TYPE_* constants |
||
54 | "RefType" => "Int", |
||
55 | // The ref name that was used to deploy this, e.g. branch name or tag. |
||
56 | // Can't really be inferred from Git history because the commit could appear in lots of |
||
57 | // branches/tags that are irrelevant to the user when it comes to deployment history, and the reference |
||
58 | // may have been deleted. |
||
59 | "RefName" => "Varchar(255)", |
||
60 | "State" => "Enum('New, Submitted, Invalid, Approved, Rejected, Queued, Deploying, Aborting, Completed, Failed, Deleted', 'New')", |
||
0 ignored issues
–
show
|
|||
61 | // JSON serialised DeploymentStrategy. |
||
62 | "Strategy" => "Text", |
||
63 | "Title" => "Varchar(255)", |
||
64 | "Summary" => "Text", |
||
65 | // the date and time the deploy was queued |
||
66 | "DeployStarted" => "SS_Datetime", |
||
67 | // the date and time a deployment was requested to be approved |
||
68 | "DeployRequested" => "SS_Datetime", |
||
69 | "RejectedReason" => "Text" |
||
70 | ); |
||
71 | |||
72 | /** |
||
73 | * @var array |
||
74 | */ |
||
75 | private static $has_one = array( |
||
76 | "Environment" => "DNEnvironment", |
||
77 | "Deployer" => "Member", |
||
78 | "Approver" => "Member", |
||
79 | "BackupDataTransfer" => "DNDataTransfer" // denotes an automated backup done for this deployment |
||
80 | ); |
||
81 | |||
82 | private static $default_sort = '"LastEdited" DESC'; |
||
83 | |||
84 | private static $dependencies = [ |
||
85 | 'stateMachineFactory' => '%$StateMachineFactory' |
||
86 | ]; |
||
87 | |||
88 | private static $summary_fields = array( |
||
89 | 'LastEdited' => 'Last Edited', |
||
90 | 'SHA' => 'SHA', |
||
91 | 'State' => 'State', |
||
92 | 'Deployer.Name' => 'Deployer' |
||
93 | ); |
||
94 | |||
95 | public function setResqueToken($token) { |
||
96 | $this->ResqueToken = $token; |
||
97 | } |
||
98 | |||
99 | public function getFiniteState() { |
||
100 | return $this->State; |
||
101 | } |
||
102 | |||
103 | public function setFiniteState($state) { |
||
104 | $this->State = $state; |
||
105 | $this->write(); |
||
106 | } |
||
107 | |||
108 | public function getStatus() { |
||
109 | return $this->State; |
||
110 | } |
||
111 | |||
112 | public function getMachine() { |
||
113 | return $this->stateMachineFactory->forDNDeployment($this); |
||
0 ignored issues
–
show
The property
stateMachineFactory does not exist on object<DNDeployment> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
114 | } |
||
115 | |||
116 | public function Link() { |
||
117 | if ($this->Environment()->IsNewDeployEnabled()) { |
||
118 | return \Controller::join_links($this->Environment()->Link(\EnvironmentOverview::ACTION_OVERVIEW), 'deployment', $this->ID); |
||
0 ignored issues
–
show
|
|||
119 | } else { |
||
120 | return \Controller::join_links($this->Environment()->Link(), 'deploy', $this->ID); |
||
121 | } |
||
122 | } |
||
123 | |||
124 | public function LogLink() { |
||
125 | return $this->Link() . '/log'; |
||
126 | } |
||
127 | |||
128 | public function canView($member = null) { |
||
129 | return $this->Environment()->canView($member); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Return a path to the log file. |
||
134 | * @return string |
||
135 | */ |
||
136 | protected function logfile() { |
||
137 | return sprintf( |
||
138 | '%s.%s.log', |
||
139 | $this->Environment()->getFullName('.'), |
||
140 | $this->ID |
||
141 | ); |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @return DeploynautLogFile |
||
146 | */ |
||
147 | public function log() { |
||
148 | return Injector::inst()->createWithArgs('DeploynautLogFile', array($this->logfile())); |
||
149 | } |
||
150 | |||
151 | public function LogContent() { |
||
152 | return $this->log()->content(); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * This remains here for backwards compatibility - we don't want to expose Resque status in here. |
||
157 | * Resque job (DeployJob) will change statuses as part of its execution. |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | public function ResqueStatus() { |
||
162 | return $this->State; |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Fetch the git repository |
||
167 | * |
||
168 | * @return \Gitonomy\Git\Repository|null |
||
169 | */ |
||
170 | public function getRepository() { |
||
171 | if(!$this->SHA) { |
||
0 ignored issues
–
show
The expression
$this->SHA of type string|null is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
172 | return null; |
||
173 | } |
||
174 | return $this->Environment()->Project()->getRepository(); |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * Gets the commit from source. The result is cached upstream in Repository. |
||
179 | * |
||
180 | * @return \Gitonomy\Git\Commit|null |
||
181 | */ |
||
182 | View Code Duplication | public function getCommit() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
183 | $repo = $this->getRepository(); |
||
184 | if($repo) { |
||
185 | try { |
||
186 | return $this->Environment()->getCommit($this->SHA); |
||
187 | } catch(Gitonomy\Git\Exception\ReferenceNotFoundException $ex) { |
||
188 | return null; |
||
189 | } |
||
190 | } |
||
191 | |||
192 | return null; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Get the commit URL to the commit associated with this deployment. |
||
197 | * @return null|string |
||
198 | */ |
||
199 | public function getCommitURL() { |
||
200 | $environment = $this->Environment(); |
||
201 | if (!$environment) { |
||
202 | return null; |
||
203 | } |
||
204 | $project = $environment->Project(); |
||
205 | if (!$project) { |
||
206 | return null; |
||
207 | } |
||
208 | $interface = $project->getRepositoryInterface(); |
||
209 | if (!$interface) { |
||
210 | return null; |
||
211 | } |
||
212 | return $interface->CommitURL . '/' . $this->SHA; |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Gets the commit message. |
||
217 | * |
||
218 | * @return string|null |
||
219 | */ |
||
220 | View Code Duplication | public function getCommitMessage() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
221 | $commit = $this->getCommit(); |
||
222 | if($commit) { |
||
223 | try { |
||
224 | return Convert::raw2xml($this->Environment()->getCommitMessage($commit)); |
||
225 | } catch(Gitonomy\Git\Exception\ReferenceNotFoundException $e) { |
||
226 | return null; |
||
227 | } |
||
228 | } |
||
229 | return null; |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Gets the commit message. |
||
234 | * |
||
235 | * @return string|null |
||
236 | */ |
||
237 | View Code Duplication | public function getCommitSubjectMessage() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
238 | $commit = $this->getCommit(); |
||
239 | if($commit) { |
||
240 | try { |
||
241 | return Convert::raw2xml($this->Environment()->getCommitSubjectMessage($commit)); |
||
242 | } catch(Gitonomy\Git\Exception\ReferenceNotFoundException $e) { |
||
243 | return null; |
||
244 | } |
||
245 | } |
||
246 | return null; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Return all tags for the deployed commit. |
||
251 | * |
||
252 | * @return ArrayList |
||
253 | */ |
||
254 | public function getTags() { |
||
255 | $commit = $this->Environment()->getCommit($this->SHA); |
||
256 | if(!$commit) { |
||
257 | return new ArrayList([]); |
||
258 | } |
||
259 | $tags = $this->Environment()->getCommitTags($commit); |
||
260 | $returnTags = []; |
||
261 | if (!empty($tags)) { |
||
262 | foreach($tags as $tag) { |
||
263 | $field = Varchar::create('Tag', '255'); |
||
264 | $field->setValue($tag->getName()); |
||
265 | $returnTags[] = $field; |
||
266 | } |
||
267 | } |
||
268 | return new ArrayList($returnTags); |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Collate the list of additional flags to affix to this deployment. |
||
273 | * Elements of the array will be rendered literally. |
||
274 | * |
||
275 | * @return ArrayList |
||
276 | */ |
||
277 | public function getFullDeployMessages() { |
||
278 | $strategy = $this->getDeploymentStrategy(); |
||
279 | if ($strategy->getActionCode()!=='full') return null; |
||
280 | |||
281 | $changes = $strategy->getChangesModificationNeeded(); |
||
282 | $messages = []; |
||
283 | foreach ($changes as $change => $details) { |
||
284 | if ($change==='Code version') continue; |
||
285 | |||
286 | $messages[] = [ |
||
287 | 'Flag' => sprintf( |
||
288 | '<span class="label label-default full-deploy-info-item">%s</span>', |
||
289 | $change[0] |
||
290 | ), |
||
291 | 'Text' => sprintf('%s changed', $change) |
||
292 | ]; |
||
293 | } |
||
294 | |||
295 | if (empty($messages)) { |
||
296 | $messages[] = [ |
||
297 | 'Flag' => '', |
||
298 | 'Text' => '<i>Environment changes have been made.</i>' |
||
299 | ]; |
||
300 | } |
||
301 | |||
302 | return new ArrayList($messages); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Fetches the latest tag for the deployed commit |
||
307 | * |
||
308 | * @return \Varchar|null |
||
309 | */ |
||
310 | public function getTag() { |
||
311 | $tags = $this->getTags(); |
||
312 | if($tags->count() > 0) { |
||
313 | return $tags->last(); |
||
314 | } |
||
315 | return null; |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * @return DeploymentStrategy |
||
320 | */ |
||
321 | public function getDeploymentStrategy() { |
||
322 | $environment = $this->Environment(); |
||
323 | $strategy = new DeploymentStrategy($environment); |
||
324 | $strategy->fromJSON($this->Strategy); |
||
0 ignored issues
–
show
The property
Strategy does not exist on object<DNDeployment> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
325 | return $strategy; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Return a list of things that are going to be deployed, such |
||
330 | * as the code version, and any infrastructural changes. |
||
331 | * |
||
332 | * @return ArrayList |
||
333 | */ |
||
334 | public function getChanges() { |
||
335 | $list = new ArrayList(); |
||
336 | $strategy = $this->getDeploymentStrategy(); |
||
337 | foreach($strategy->getChanges() as $name => $change) { |
||
338 | $changed = (isset($change['from']) && isset($change['to'])) ? $change['from'] != $change['to'] : null; |
||
339 | $description = isset($change['description']) ? $change['description'] : ''; |
||
340 | $compareUrl = null; |
||
341 | |||
342 | // if there is a compare URL, and a description or a change (something actually changed) |
||
343 | // then show the URL. Otherwise don't show anything, as there is no comparison to be made. |
||
344 | if ($changed || $description) { |
||
345 | $compareUrl = isset($change['compareUrl']) ? $change['compareUrl'] : ''; |
||
346 | } |
||
347 | |||
348 | $list->push(new ArrayData([ |
||
349 | 'Name' => $name, |
||
350 | 'From' => isset($change['from']) ? $change['from'] : null, |
||
351 | 'To' => isset($change['to']) ? $change['to'] : null, |
||
352 | 'Description' => $description, |
||
353 | 'Changed' => $changed, |
||
354 | 'CompareUrl' => $compareUrl |
||
355 | ])); |
||
356 | } |
||
357 | |||
358 | return $list; |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * Start a resque job for this deployment |
||
363 | * |
||
364 | * @return string Resque token |
||
365 | */ |
||
366 | public function enqueueDeployment() { |
||
367 | $environment = $this->Environment(); |
||
368 | $project = $environment->Project(); |
||
369 | $log = $this->log(); |
||
370 | |||
371 | $args = array( |
||
372 | 'environmentName' => $environment->Name, |
||
373 | 'repository' => $project->getLocalCVSPath(), |
||
374 | 'logfile' => $this->logfile(), |
||
375 | 'projectName' => $project->Name, |
||
376 | 'env' => $project->getProcessEnv(), |
||
377 | 'deploymentID' => $this->ID, |
||
378 | 'sigFile' => $this->getSigFile(), |
||
379 | ); |
||
380 | |||
381 | $strategy = $this->getDeploymentStrategy(); |
||
382 | // Inject options. |
||
383 | $args = array_merge($args, $strategy->getOptions()); |
||
384 | // Make sure we use the SHA as it was written into this DNDeployment. |
||
385 | $args['sha'] = $this->SHA; |
||
386 | |||
387 | if(!$this->DeployerID) { |
||
388 | $this->DeployerID = Member::currentUserID(); |
||
389 | } |
||
390 | |||
391 | View Code Duplication | if($this->DeployerID) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
392 | $deployer = $this->Deployer(); |
||
393 | $message = sprintf( |
||
394 | 'Deploy to %s initiated by %s (%s), with IP address %s', |
||
395 | $environment->getFullName(), |
||
396 | $deployer->getName(), |
||
397 | $deployer->Email, |
||
398 | \Controller::curr()->getRequest()->getIP() |
||
399 | ); |
||
400 | $log->write($message); |
||
401 | } |
||
402 | |||
403 | return Resque::enqueue('deploy', 'DeployJob', $args, true); |
||
404 | } |
||
405 | |||
406 | public function getSigFile() { |
||
407 | $dir = DNData::inst()->getSignalDir(); |
||
408 | if (!is_dir($dir)) { |
||
409 | `mkdir $dir`; |
||
410 | } |
||
411 | return sprintf( |
||
412 | '%s/deploynaut-signal-%s-%s', |
||
413 | DNData::inst()->getSignalDir(), |
||
414 | $this->ClassName, |
||
415 | $this->ID |
||
416 | ); |
||
417 | } |
||
418 | |||
419 | /** |
||
420 | * Signal the worker to self-abort. If we had a reliable way of figuring out the right PID, |
||
421 | * we could posix_kill directly, but Resque seems to not provide a way to find out the PID |
||
422 | * from the job nor worker. |
||
423 | */ |
||
424 | public function setSignal($signal) { |
||
425 | $sigFile = $this->getSigFile(); |
||
426 | // 2 is SIGINT - we can't use SIGINT constant in the Apache context, only available in workers. |
||
427 | file_put_contents($sigFile, $signal); |
||
428 | } |
||
429 | } |
||
430 |
This check marks property names that have not been written in camelCase.
In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes
databaseConnectionString
.