userator /
deploid
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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 | } |