1 | <?php |
||||
2 | |||||
3 | namespace Deploid; |
||||
4 | |||||
5 | use Symfony\Component\Console\Application as ConsoleApplication; |
||||
6 | use Psr\Log\LoggerAwareInterface; |
||||
7 | use Psr\Log\LoggerInterface; |
||||
8 | use Symfony\Component\Process\Process; |
||||
9 | |||||
10 | class Application extends ConsoleApplication implements LoggerAwareInterface { |
||||
11 | |||||
12 | /** @var string */ |
||||
13 | private $releaseNameFormat = 'Y-m-d_H-i-s'; |
||||
14 | |||||
15 | /** @var string */ |
||||
16 | private $chmod = 0777; |
||||
17 | |||||
18 | /** @var array */ |
||||
19 | private $structure = [ |
||||
20 | 'dirs' => [ |
||||
21 | 'releases', |
||||
22 | 'releases/first', |
||||
23 | 'shared', |
||||
24 | ], |
||||
25 | 'files' => [ |
||||
26 | 'deploid.log', |
||||
27 | ], |
||||
28 | 'links' => [ |
||||
29 | 'current:releases/first', |
||||
30 | ], |
||||
31 | ]; |
||||
32 | |||||
33 | /** @var LoggerInterface */ |
||||
34 | private $logger; |
||||
35 | |||||
36 | /* mutators */ |
||||
37 | |||||
38 | public function getReleaseNameFormat() { |
||||
39 | return $this->releaseNameFormat; |
||||
40 | } |
||||
41 | |||||
42 | public function setReleaseNameFormat($releaseNameFormat) { |
||||
43 | $this->releaseNameFormat = $releaseNameFormat; |
||||
44 | } |
||||
45 | |||||
46 | public function getChmod() { |
||||
47 | return $this->chmod; |
||||
48 | } |
||||
49 | |||||
50 | public function setChmod($chmod) { |
||||
51 | $this->chmod = $chmod; |
||||
52 | } |
||||
53 | |||||
54 | /** |
||||
55 | * @return LoggerInterface |
||||
56 | */ |
||||
57 | public function getLogger() { |
||||
58 | return $this->logger; |
||||
59 | } |
||||
60 | |||||
61 | /** |
||||
62 | * @param LoggerInterface $logger |
||||
63 | * @return void |
||||
64 | */ |
||||
65 | public function setLogger(LoggerInterface $logger) { |
||||
66 | $this->logger = $logger; |
||||
67 | } |
||||
68 | |||||
69 | public function getStructure() { |
||||
70 | return $this->structure; |
||||
71 | } |
||||
72 | |||||
73 | public function setStructure(array $structure) { |
||||
74 | $this->structure = $structure; |
||||
75 | } |
||||
76 | |||||
77 | 1 | public function makeStructure($path, array $structure) { |
|||
78 | 1 | if (empty($path)) throw new \InvalidArgumentException('empty path'); |
|||
79 | |||||
80 | 1 | if (empty($structure)) true; |
|||
81 | |||||
82 | 1 | foreach ($structure as $section => $items) { |
|||
83 | 1 | if (empty($items)) continue; |
|||
84 | 1 | foreach ($items as $item) { |
|||
85 | 1 | if (empty($item)) continue; |
|||
86 | 1 | if ($section == 'dirs') { |
|||
87 | 1 | $dir = $path . DIRECTORY_SEPARATOR . $item; |
|||
88 | 1 | mkdir($dir, $this->chmod, true); |
|||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
89 | 1 | } else if ($section == 'files') { |
|||
90 | 1 | $file = $path . DIRECTORY_SEPARATOR . $item; |
|||
91 | 1 | if (!is_dir(dirname($file))) mkdir(dirname($file), $this->chmod, true); |
|||
92 | 1 | touch($path . DIRECTORY_SEPARATOR . $item); |
|||
93 | 1 | } else if ($section == 'links') { |
|||
94 | 1 | $link = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[0]); |
|||
95 | 1 | $target = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[1]); |
|||
96 | 1 | if (!is_dir(dirname($link))) mkdir(dirname($link), $this->chmod, true); |
|||
97 | 1 | symlink($target, $link); |
|||
98 | 1 | } |
|||
99 | 1 | } |
|||
100 | 1 | } |
|||
101 | |||||
102 | 1 | return true; |
|||
103 | } |
||||
104 | |||||
105 | public function scanStructure($path) { |
||||
106 | if (empty($path)) throw new \InvalidArgumentException('empty path'); |
||||
107 | |||||
108 | $directory = new \RecursiveDirectoryIterator(realpath($path), \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS); |
||||
109 | $iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST); |
||||
110 | |||||
111 | $items = []; |
||||
112 | foreach ($iterator as $item) { |
||||
113 | $items[] = $item; |
||||
114 | } |
||||
115 | |||||
116 | if (empty($items)) return []; |
||||
117 | |||||
118 | $structure = []; |
||||
119 | foreach ($items as $item) { |
||||
120 | if (is_link($item)) { |
||||
121 | $structure['links'][] = str_ireplace(realpath($path) . DIRECTORY_SEPARATOR, '', $item) . ':' . str_ireplace(realpath($path) . DIRECTORY_SEPARATOR, '', readlink($item)); |
||||
122 | } else if (is_file($item)) { |
||||
123 | $structure['files'][] = str_ireplace(realpath($path) . DIRECTORY_SEPARATOR, '', $item); |
||||
124 | } else if (is_dir($item)) { |
||||
125 | $structure['dirs'][] = str_ireplace(realpath($path) . DIRECTORY_SEPARATOR, '', $item); |
||||
126 | } |
||||
127 | } |
||||
128 | |||||
129 | return $structure; |
||||
130 | } |
||||
131 | |||||
132 | public function sortStructure(array $structure) { |
||||
133 | ksort($structure); |
||||
134 | |||||
135 | $structure = array_map(function ($item) { |
||||
136 | sort($item); |
||||
137 | return $item; |
||||
138 | }, $structure); |
||||
139 | |||||
140 | return $structure; |
||||
141 | } |
||||
142 | |||||
143 | public function diffStructure(array $structureThin, array $structureFat) { |
||||
144 | if (empty($structureThin)) return []; |
||||
145 | if (empty($structureFat)) return []; |
||||
146 | |||||
147 | $structureDiff = []; |
||||
148 | |||||
149 | foreach ($structureFat as $section => $items) { |
||||
150 | if (empty($structureThin[$section])) continue; |
||||
151 | $diff = array_diff($items, $structureThin[$section]); |
||||
152 | if (empty($diff)) continue; |
||||
153 | $structureDiff[$section] = $diff; |
||||
154 | } |
||||
155 | |||||
156 | return $structureDiff; |
||||
157 | } |
||||
158 | |||||
159 | public function toRealpaths($path, array $structure) { |
||||
160 | if (empty($path)) throw new \InvalidArgumentException('empty path'); |
||||
161 | |||||
162 | if (empty($structure)) return []; |
||||
163 | |||||
164 | $realpaths = []; |
||||
165 | |||||
166 | foreach ($structure as $section => $items) { |
||||
167 | if (empty($items)) continue; |
||||
168 | foreach ($items as $item) { |
||||
169 | if (empty($item)) continue; |
||||
170 | if ($section == 'links') { |
||||
171 | $realpaths[] = realpath($path) . DIRECTORY_SEPARATOR . explode(':', $item)[0]; |
||||
172 | } else if ($section == 'files') { |
||||
173 | $realpaths[] = realpath($path) . DIRECTORY_SEPARATOR . $item; |
||||
174 | } else if ($section == 'dirs') { |
||||
175 | $realpaths[] = realpath($path) . DIRECTORY_SEPARATOR . $item; |
||||
176 | } |
||||
177 | } |
||||
178 | } |
||||
179 | |||||
180 | rsort($realpaths); |
||||
181 | |||||
182 | return $realpaths; |
||||
183 | } |
||||
184 | |||||
185 | /* tools */ |
||||
186 | |||||
187 | /** |
||||
188 | * @param string $path |
||||
189 | * @return \Deploid\Payload |
||||
190 | */ |
||||
191 | 2 | public function deploidStructureValidate($path) { |
|||
192 | 2 | $payload = new Payload(); |
|||
193 | |||||
194 | 2 | if (!strlen($path)) { |
|||
195 | $payload->setType(Payload::STRUCTURE_VALIDATE_FAIL); |
||||
196 | $payload->setMessage('empty path'); |
||||
197 | $payload->setCode(255); |
||||
198 | return $payload; |
||||
199 | } |
||||
200 | |||||
201 | 2 | $path = $this->absolutePath($path, getcwd()); |
|||
202 | 2 | $messages = []; |
|||
203 | |||||
204 | 2 | foreach ($this->structure as $section => $items) { |
|||
205 | 2 | if (empty($items)) continue; |
|||
206 | 2 | foreach ($items as $item) { |
|||
207 | 2 | if (empty($item)) continue; |
|||
208 | 2 | if ($section == 'dirs') { |
|||
209 | 2 | $dir = $path . DIRECTORY_SEPARATOR . $item; |
|||
210 | 2 | if (!is_dir($dir)) $messages[] = 'directory "' . $dir . '" not found'; |
|||
211 | 2 | } else if ($section == 'files') { |
|||
212 | 2 | $file = $path . DIRECTORY_SEPARATOR . $item; |
|||
213 | 2 | if (!is_file($file)) $messages[] = 'file "' . $file . '" not found'; |
|||
214 | 2 | } else if ($section == 'links') { |
|||
215 | 2 | $link = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[0]); |
|||
216 | 2 | if (!is_link($link)) $messages[] = 'link "' . realpath($link) . '" not found'; |
|||
217 | 2 | } |
|||
218 | 2 | } |
|||
219 | 2 | } |
|||
220 | |||||
221 | 2 | if (count($messages)) { |
|||
222 | 1 | $payload->setType(Payload::STRUCTURE_VALIDATE_FAIL); |
|||
223 | 1 | $payload->setMessage($messages); |
|||
224 | 1 | $payload->setCode(255); |
|||
225 | 1 | return $payload; |
|||
226 | } |
||||
227 | |||||
228 | 1 | $payload->setType(Payload::STRUCTURE_VALIDATE_SUCCESS); |
|||
229 | 1 | $payload->setMessage('structure is valid'); |
|||
230 | 1 | $payload->setCode(0); |
|||
231 | 1 | return $payload; |
|||
232 | } |
||||
233 | |||||
234 | /** |
||||
235 | * @param string $path |
||||
236 | * @return \Deploid\Payload |
||||
237 | */ |
||||
238 | 1 | public function deploidStructureInit($path) { |
|||
239 | 1 | $payload = new Payload(); |
|||
240 | |||||
241 | 1 | if (!strlen($path)) { |
|||
242 | $payload->setType(Payload::STRUCTURE_INIT_FAIL); |
||||
243 | $payload->setMessage('empty path'); |
||||
244 | $payload->setCode(255); |
||||
245 | return $payload; |
||||
246 | } |
||||
247 | |||||
248 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
249 | 1 | $messages = []; |
|||
250 | |||||
251 | 1 | if (!is_dir($path)) { |
|||
252 | if (mkdir($path, $this->chmod, true)) { |
||||
0 ignored issues
–
show
$this->chmod of type string is incompatible with the type integer expected by parameter $mode of mkdir() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
253 | $messages[] = 'directory "' . realpath($path) . '" created'; |
||||
254 | } else { |
||||
255 | $payload->setType(Payload::STRUCTURE_INIT_FAIL); |
||||
256 | $payload->setMessage('directory "' . $path . '" does not created'); |
||||
257 | $payload->setCode(255); |
||||
258 | return $payload; |
||||
259 | } |
||||
260 | } |
||||
261 | |||||
262 | 1 | foreach ($this->structure as $section => $items) { |
|||
263 | 1 | if (empty($items)) continue; |
|||
264 | 1 | foreach ($items as $item) { |
|||
265 | 1 | if (empty($item)) continue; |
|||
266 | 1 | if ($section == 'dirs') { |
|||
267 | 1 | $dir = $path . DIRECTORY_SEPARATOR . $item; |
|||
268 | 1 | if (mkdir($dir, $this->chmod, true)) { |
|||
269 | 1 | $messages[] = 'directory "' . $dir . '" created'; |
|||
270 | 1 | } else { |
|||
271 | $payload->setType(Payload::STRUCTURE_INIT_FAIL); |
||||
272 | $payload->setMessage('directory "' . $dir . '" does not created'); |
||||
273 | $payload->setCode(255); |
||||
274 | return $payload; |
||||
275 | } |
||||
276 | 1 | } else if ($section == 'files') { |
|||
277 | 1 | $file = $path . DIRECTORY_SEPARATOR . $item; |
|||
278 | 1 | if (touch($file)) { |
|||
279 | 1 | $messages[] = 'file "' . $file . '" created'; |
|||
280 | 1 | } else { |
|||
281 | $payload->setType(Payload::STRUCTURE_INIT_FAIL); |
||||
282 | $payload->setMessage('file"' . $file . '" does not created'); |
||||
283 | $payload->setCode(255); |
||||
284 | return $payload; |
||||
285 | } |
||||
286 | 1 | } else if ($section == 'links') { |
|||
287 | 1 | $target = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[1]); |
|||
288 | 1 | $link = $path . DIRECTORY_SEPARATOR . (explode(':', $item)[0]); |
|||
289 | 1 | if (symlink($target, $link)) { |
|||
290 | 1 | $messages[] = 'link "' . $link . '" created'; |
|||
291 | 1 | } else { |
|||
292 | $payload->setType(Payload::STRUCTURE_INIT_FAIL); |
||||
293 | $payload->setMessage('link ' . $link . '" does not created'); |
||||
294 | $payload->setCode(255); |
||||
295 | return $payload; |
||||
296 | } |
||||
297 | 1 | } |
|||
298 | 1 | } |
|||
299 | 1 | } |
|||
300 | |||||
301 | 1 | $payload->setType(Payload::STRUCTURE_INIT_SUCCESS); |
|||
302 | 1 | $payload->setMessage($messages); |
|||
303 | 1 | $payload->setCode(0); |
|||
304 | 1 | return $payload; |
|||
305 | } |
||||
306 | |||||
307 | /** |
||||
308 | * @param string $path |
||||
309 | * @return \Deploid\Payload |
||||
310 | */ |
||||
311 | 1 | public function deploidStructureClean($path) { |
|||
312 | 1 | $payload = new Payload(); |
|||
313 | |||||
314 | 1 | if (!strlen($path)) { |
|||
315 | $payload->setType(Payload::STRUCTURE_CLEAN_FAIL); |
||||
316 | $payload->setMessage('empty path'); |
||||
317 | $payload->setCode(255); |
||||
318 | return $payload; |
||||
319 | } |
||||
320 | |||||
321 | 1 | $realpathsClean = $this->toRealpaths($path, $this->structure); |
|||
322 | 1 | $realpathsDirty = $this->toRealpaths($path, $this->scanStructure($path)); |
|||
323 | 1 | $realpathsDiff = array_diff($realpathsDirty, $realpathsClean); |
|||
324 | |||||
325 | 1 | foreach ($realpathsDiff as $item) { |
|||
326 | 1 | if (empty($item)) continue; |
|||
327 | 1 | if (is_link($item)) unlink($item); |
|||
328 | 1 | if (is_file($item)) unlink($item); |
|||
329 | 1 | if (is_dir($item)) rmdir($item); |
|||
330 | 1 | } |
|||
331 | |||||
332 | 1 | $payload->setType(Payload::STRUCTURE_CLEAN_SUCCESS); |
|||
333 | 1 | $payload->setMessage(array_merge(['cleaned items:'], $realpathsDiff)); |
|||
334 | 1 | $payload->setCode(0); |
|||
335 | 1 | return $payload; |
|||
336 | } |
||||
337 | |||||
338 | /** |
||||
339 | * @param string $release |
||||
340 | * @param string $path |
||||
341 | * @return \Deploid\Payload |
||||
342 | */ |
||||
343 | 2 | public function deploidReleaseExist($release, $path) { |
|||
344 | 2 | $payload = new Payload(); |
|||
345 | |||||
346 | 2 | if (!strlen($release)) { |
|||
347 | $payload->setType(Payload::RELEASE_EXIST_FAIL); |
||||
348 | $payload->setMessage('empty release name'); |
||||
349 | $payload->setCode(255); |
||||
350 | return $payload; |
||||
351 | } |
||||
352 | |||||
353 | 2 | if (!strlen($path)) { |
|||
354 | $payload->setType(Payload::RELEASE_EXIST_FAIL); |
||||
355 | $payload->setMessage('empty path'); |
||||
356 | $payload->setCode(255); |
||||
357 | return $payload; |
||||
358 | } |
||||
359 | |||||
360 | 2 | $path = $this->absolutePath($path, getcwd()); |
|||
361 | |||||
362 | 2 | $releaseDir = $path . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release; |
|||
363 | 2 | if (!is_dir($releaseDir)) { |
|||
364 | 1 | $payload->setType(Payload::RELEASE_EXIST_FAIL); |
|||
365 | 1 | $payload->setMessage('release "' . $release . '" does not exist'); |
|||
366 | 1 | $payload->setCode(255); |
|||
367 | 1 | return $payload; |
|||
368 | } |
||||
369 | |||||
370 | 1 | $payload->setType(Payload::RELEASE_EXIST_SUCCESS); |
|||
371 | 1 | $payload->setMessage('release "' . $release . '" exist'); |
|||
372 | 1 | $payload->setCode(0); |
|||
373 | 1 | return $payload; |
|||
374 | } |
||||
375 | |||||
376 | /** |
||||
377 | * @param string $release |
||||
378 | * @param string $path |
||||
379 | * @return \Deploid\Payload |
||||
380 | */ |
||||
381 | 1 | public function deploidReleaseCreate($release, $path) { |
|||
382 | 1 | $payload = new Payload(); |
|||
383 | |||||
384 | 1 | if (!strlen($release)) { |
|||
385 | $payload->setType(Payload::RELEASE_CREATE_FAIL); |
||||
386 | $payload->setMessage('empty release name'); |
||||
387 | $payload->setCode(255); |
||||
388 | return $payload; |
||||
389 | } |
||||
390 | |||||
391 | 1 | if (!strlen($path)) { |
|||
392 | $payload->setType(Payload::RELEASE_CREATE_FAIL); |
||||
393 | $payload->setMessage('empty path'); |
||||
394 | $payload->setCode(255); |
||||
395 | return $payload; |
||||
396 | } |
||||
397 | |||||
398 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
399 | |||||
400 | 1 | $releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release; |
|||
401 | |||||
402 | 1 | if (!mkdir($releaseDir, $this->chmod, true)) { |
|||
0 ignored issues
–
show
$this->chmod of type string is incompatible with the type integer expected by parameter $mode of mkdir() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
403 | $payload->setType(Payload::RELEASE_CREATE_FAIL); |
||||
404 | $payload->setMessage('release "' . $release . '" does not created'); |
||||
405 | $payload->setCode(255); |
||||
406 | return $payload; |
||||
407 | } |
||||
408 | |||||
409 | 1 | $payload->setType(Payload::RELEASE_CREATE_SUCCESS); |
|||
410 | 1 | $payload->setMessage('release "' . $release . '" created'); |
|||
411 | 1 | $payload->setCode(0); |
|||
412 | 1 | return $payload; |
|||
413 | } |
||||
414 | |||||
415 | /** |
||||
416 | * @param string $release |
||||
417 | * @param string $path |
||||
418 | * @return \Deploid\Payload |
||||
419 | */ |
||||
420 | 1 | public function deploidReleaseRemove($release, $path) { |
|||
421 | 1 | $payload = new Payload(); |
|||
422 | |||||
423 | 1 | if (!strlen($release)) { |
|||
424 | $payload->setType(Payload::RELEASE_REMOVE_FAIL); |
||||
425 | $payload->setMessage('empty release name'); |
||||
426 | $payload->setCode(255); |
||||
427 | return $payload; |
||||
428 | } |
||||
429 | |||||
430 | 1 | if (!strlen($path)) { |
|||
431 | $payload->setType(Payload::RELEASE_REMOVE_FAIL); |
||||
432 | $payload->setMessage('empty path'); |
||||
433 | $payload->setCode(255); |
||||
434 | return $payload; |
||||
435 | } |
||||
436 | |||||
437 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
438 | |||||
439 | 1 | $proccess = new Process('rm -r ' . realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release); |
|||
440 | 1 | $proccess->run(); |
|||
441 | |||||
442 | 1 | if (!$proccess->isSuccessful()) { |
|||
443 | $payload->setType(Payload::RELEASE_REMOVE_FAIL); |
||||
444 | $payload->setMessage($proccess->getErrorOutput()); |
||||
445 | $payload->setCode($proccess->getExitCode()); |
||||
446 | return $payload; |
||||
447 | } |
||||
448 | |||||
449 | 1 | $payload->setType(Payload::RELEASE_REMOVE_SUCCESS); |
|||
450 | 1 | $payload->setMessage('release "' . ($release == '*' ? 'all' : $release) . '" removed'); |
|||
451 | 1 | $payload->setCode(0); |
|||
452 | 1 | return $payload; |
|||
453 | } |
||||
454 | |||||
455 | /** |
||||
456 | * @param string $path |
||||
457 | * @return \Deploid\Payload |
||||
458 | */ |
||||
459 | 1 | public function deploidReleaseList($path) { |
|||
460 | 1 | $payload = new Payload(); |
|||
461 | |||||
462 | 1 | if (!strlen($path)) { |
|||
463 | $payload->setType(Payload::RELEASE_LIST_FAIL); |
||||
464 | $payload->setMessage('path "' . $path . '" invalid'); |
||||
465 | $payload->setCode(255); |
||||
466 | return $payload; |
||||
467 | } |
||||
468 | |||||
469 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
470 | |||||
471 | 1 | $dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR); |
|||
472 | |||||
473 | 1 | if (empty($dirs)) { |
|||
474 | $payload->setType(Payload::RELEASE_LIST_FAIL); |
||||
475 | $payload->setMessage('release not found'); |
||||
476 | $payload->setCode(0); |
||||
477 | return $payload; |
||||
478 | } |
||||
479 | |||||
480 | $dirs = array_map(function ($path) { |
||||
481 | 1 | return basename($path); |
|||
482 | 1 | }, $dirs); |
|||
483 | |||||
484 | 1 | $payload->setType(Payload::RELEASE_LIST_SUCCESS); |
|||
485 | 1 | $payload->setMessage($dirs); |
|||
486 | 1 | $payload->setCode(0); |
|||
487 | 1 | return $payload; |
|||
488 | } |
||||
489 | |||||
490 | /** |
||||
491 | * @param string $path |
||||
492 | * @return \Deploid\Payload |
||||
493 | */ |
||||
494 | 1 | public function deploidReleaseLatest($path) { |
|||
495 | 1 | $payload = new Payload(); |
|||
496 | |||||
497 | 1 | if (!strlen($path)) { |
|||
498 | $payload->setType(Payload::RELEASE_LATEST_FAIL); |
||||
499 | $payload->setMessage('empty path'); |
||||
500 | $payload->setCode(255); |
||||
501 | return $payload; |
||||
502 | } |
||||
503 | |||||
504 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
505 | |||||
506 | 1 | $dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR); |
|||
507 | |||||
508 | 1 | if (empty($dirs)) { |
|||
509 | $payload->setType(Payload::RELEASE_LATEST_FAIL); |
||||
510 | $payload->setMessage('release not found'); |
||||
511 | $payload->setCode(255); |
||||
512 | return $payload; |
||||
513 | } |
||||
514 | |||||
515 | 1 | $dirs = array_map(function ($path) { |
|||
516 | 1 | return basename($path); |
|||
517 | 1 | }, $dirs); |
|||
518 | |||||
519 | 1 | if (!rsort($dirs)) { |
|||
520 | $payload->setType(Payload::RELEASE_LATEST_FAIL); |
||||
521 | $payload->setMessage('fail sorted'); |
||||
522 | $payload->setCode(255); |
||||
523 | return $payload; |
||||
524 | } |
||||
525 | |||||
526 | 1 | $payload->setType(Payload::RELEASE_LATEST_SUCCESS); |
|||
527 | 1 | $payload->setMessage(current($dirs)); |
|||
528 | 1 | $payload->setCode(0); |
|||
529 | 1 | return $payload; |
|||
530 | } |
||||
531 | |||||
532 | /** |
||||
533 | * @param string $path |
||||
534 | * @return \Deploid\Payload |
||||
535 | */ |
||||
536 | 1 | public function deploidReleaseCurrent($path) { |
|||
537 | 1 | $payload = new Payload(); |
|||
538 | |||||
539 | 1 | if (!strlen($path)) { |
|||
540 | $payload->setType(Payload::RELEASE_CURRENT_FAIL); |
||||
541 | $payload->setMessage('empty path'); |
||||
542 | $payload->setCode(255); |
||||
543 | return $payload; |
||||
544 | } |
||||
545 | |||||
546 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
547 | |||||
548 | 1 | $link = realpath($path) . DIRECTORY_SEPARATOR . 'current'; |
|||
549 | |||||
550 | 1 | if (!file_exists($link)) { |
|||
551 | $payload->setType(Payload::RELEASE_CURRENT_FAIL); |
||||
552 | $payload->setMessage('current release does not exist'); |
||||
553 | $payload->setCode(255); |
||||
554 | return $payload; |
||||
555 | } |
||||
556 | |||||
557 | 1 | if (!is_link($link)) { |
|||
558 | $payload->setType(Payload::RELEASE_CURRENT_FAIL); |
||||
559 | $payload->setMessage('link to current release does not exist'); |
||||
560 | $payload->setCode(255); |
||||
561 | return $payload; |
||||
562 | } |
||||
563 | |||||
564 | 1 | $linkpath = readlink($link); |
|||
565 | |||||
566 | 1 | if (!$linkpath) { |
|||
567 | $payload->setType(Payload::RELEASE_CURRENT_FAIL); |
||||
568 | $payload->setMessage('fail read link to current release'); |
||||
569 | $payload->setCode(255); |
||||
570 | return $payload; |
||||
571 | } |
||||
572 | |||||
573 | 1 | $payload->setType(Payload::RELEASE_CURRENT_SUCCESS); |
|||
574 | 1 | $payload->setMessage(basename($linkpath)); |
|||
575 | 1 | $payload->setCode(0); |
|||
576 | 1 | return $payload; |
|||
577 | } |
||||
578 | |||||
579 | /** |
||||
580 | * @param string $release |
||||
581 | * @param string $path |
||||
582 | * @return \Deploid\Payload |
||||
583 | */ |
||||
584 | 1 | public function deploidReleaseSetup($release, $path) { |
|||
585 | 1 | $payload = new Payload(); |
|||
586 | |||||
587 | 1 | if (!strlen($path)) { |
|||
588 | $payload->setType(Payload::RELEASE_SETUP_FAIL); |
||||
589 | $payload->setMessage('path "' . $path . '" invalid'); |
||||
590 | $payload->setCode(255); |
||||
591 | return $payload; |
||||
592 | } |
||||
593 | |||||
594 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
595 | |||||
596 | 1 | $releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release; |
|||
597 | 1 | $currentDir = realpath($path) . DIRECTORY_SEPARATOR . 'current'; |
|||
598 | |||||
599 | 1 | $proccess = new Process('ln -sfn ' . $releaseDir . ' ' . $currentDir); |
|||
600 | 1 | $proccess->run(); |
|||
601 | |||||
602 | 1 | if (!$proccess->isSuccessful()) { |
|||
603 | $payload->setType(Payload::RELEASE_SETUP_FAIL); |
||||
604 | $payload->setMessage($proccess->getErrorOutput()); |
||||
605 | $payload->setCode($proccess->getExitCode()); |
||||
606 | return $payload; |
||||
607 | } |
||||
608 | |||||
609 | 1 | $payload->setType(Payload::RELEASE_SETUP_SUCCESS); |
|||
610 | 1 | $payload->setMessage('release "' . $release . '" setup'); |
|||
611 | 1 | $payload->setCode(0); |
|||
612 | 1 | return $payload; |
|||
613 | } |
||||
614 | |||||
615 | /** |
||||
616 | * @param int $quantity |
||||
617 | * @param string $path |
||||
618 | * @return \Deploid\Payload |
||||
619 | */ |
||||
620 | 1 | public function deploidReleaseRotate($quantity, $path) { |
|||
621 | 1 | $payload = new Payload(); |
|||
622 | |||||
623 | 1 | if (!$quantity || $quantity < 1) { |
|||
624 | $payload->setType(Payload::RELEASE_ROTATE_FAIL); |
||||
625 | $payload->setMessage('empty or invalid quantity'); |
||||
626 | $payload->setCode(255); |
||||
627 | return $payload; |
||||
628 | } |
||||
629 | |||||
630 | 1 | if (!strlen($path)) { |
|||
631 | $payload->setType(Payload::RELEASE_ROTATE_FAIL); |
||||
632 | $payload->setMessage('empty path'); |
||||
633 | $payload->setCode(255); |
||||
634 | return $payload; |
||||
635 | } |
||||
636 | |||||
637 | 1 | $path = $this->absolutePath($path, getcwd()); |
|||
638 | |||||
639 | 1 | $releases = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR); |
|||
640 | |||||
641 | 1 | if (count($releases) <= $quantity) { |
|||
642 | $payload->setType(Payload::RELEASE_ROTATE_SUCCESS); |
||||
643 | $payload->setMessage('not found releases to rotate'); |
||||
644 | $payload->setCode(0); |
||||
645 | } |
||||
646 | |||||
647 | 1 | foreach (array_reverse($releases) as $idx => $release) { |
|||
648 | 1 | if ($idx <= ($quantity - 1)) continue; |
|||
649 | 1 | $proccess = new Process('rm -r ' . $release); |
|||
650 | 1 | $proccess->run(); |
|||
651 | 1 | } |
|||
652 | |||||
653 | 1 | $payload->setType(Payload::RELEASE_ROTATE_SUCCESS); |
|||
654 | 1 | $payload->setMessage('releases are rotated'); |
|||
655 | 1 | $payload->setCode(0); |
|||
656 | 1 | return $payload; |
|||
657 | } |
||||
658 | |||||
659 | 2 | public function absolutePath($path, $cwd) { |
|||
660 | 2 | if (empty($path)) throw new \InvalidArgumentException('empty path'); |
|||
661 | 2 | if (empty($cwd)) throw new \InvalidArgumentException('empty cwd'); |
|||
662 | |||||
663 | 2 | if ($path[0] == '/') return $path; |
|||
664 | |||||
665 | 1 | return $cwd . DIRECTORY_SEPARATOR . $path; |
|||
666 | } |
||||
667 | |||||
668 | } |