/src/Application/BaseApplication.php

https://github.com/TYPO3/Surf · PHP · 223 lines · 133 code · 32 blank · 58 comment · 8 complexity · facf8caa59657f823e75b965e24829ab MD5 · raw file

  1. <?php
  2. namespace TYPO3\Surf\Application;
  3. /*
  4. * This file is part of TYPO3 Surf.
  5. *
  6. * For the full copyright and license information, please view the LICENSE.txt
  7. * file that was distributed with this source code.
  8. */
  9. use TYPO3\Surf\Domain\Model\Application;
  10. use TYPO3\Surf\Domain\Model\Deployment;
  11. use TYPO3\Surf\Domain\Model\Workflow;
  12. use TYPO3\Surf\Task\CleanupReleasesTask;
  13. use TYPO3\Surf\Task\Composer\InstallTask;
  14. use TYPO3\Surf\Task\CreateDirectoriesTask;
  15. use TYPO3\Surf\Task\Generic\CreateDirectoriesTask as GenericCreateDirectoriesTask;
  16. use TYPO3\Surf\Task\Generic\CreateSymlinksTask;
  17. use TYPO3\Surf\Task\GitCheckoutTask;
  18. use TYPO3\Surf\Task\LockDeploymentTask;
  19. use TYPO3\Surf\Task\Package\GitTask;
  20. use TYPO3\Surf\Task\SymlinkReleaseTask;
  21. use TYPO3\Surf\Task\Transfer\RsyncTask;
  22. use TYPO3\Surf\Task\Transfer\ScpTask;
  23. use TYPO3\Surf\Task\UnlockDeploymentTask;
  24. /**
  25. * A base application with Git checkout and basic release directory structure
  26. *
  27. * Most specific applications will extend from BaseApplication.
  28. */
  29. class BaseApplication extends Application
  30. {
  31. /**
  32. * Symlinks, which should be created for each release.
  33. *
  34. * @see \TYPO3\Surf\Task\Generic\CreateSymlinksTask
  35. * @var array
  36. */
  37. protected $symlinks = [];
  38. /**
  39. * Directories which should be created on deployment. E.g. shared folders.
  40. *
  41. * @var array
  42. */
  43. protected $directories = [];
  44. /**
  45. * Basic application specific options
  46. *
  47. * packageMethod: How to prepare the application assets (code and files) locally before transfer
  48. *
  49. * "git" Make a local git checkout and transfer files to the server
  50. * none Default, do not prepare anything locally
  51. *
  52. * transferMethod: How to transfer the application assets to a node
  53. *
  54. * "git" Make a checkout of the application assets remotely on the node
  55. *
  56. * updateMethod: How to prepare and update the application assets on the node after transfer
  57. *
  58. * lockDeployment: Locked deployments can only run once at a time
  59. *
  60. * @var array
  61. */
  62. protected $options = [
  63. 'packageMethod' => 'git',
  64. 'transferMethod' => 'rsync',
  65. 'updateMethod' => null,
  66. 'lockDeployment' => true,
  67. 'webDirectory' => self::DEFAULT_WEB_DIRECTORY,
  68. ];
  69. /**
  70. * Register tasks for the base application
  71. *
  72. * The base application performs the following tasks:
  73. *
  74. * Initialize stage:
  75. * - Create directories for release structure
  76. *
  77. * Update stage:
  78. * - Perform Git checkout (and pass on sha1 / tag or branch option from application to the task)
  79. *
  80. * Switch stage:
  81. * - Symlink the current and previous release
  82. *
  83. * Cleanup stage:
  84. * - Clean up old releases
  85. */
  86. public function registerTasks(Workflow $workflow, Deployment $deployment): void
  87. {
  88. $this->setOption(GenericCreateDirectoriesTask::class . '[directories]', $this->getDirectories());
  89. $this->setOption(CreateSymlinksTask::class . '[symlinks]', $this->getSymlinks());
  90. if ($this->hasOption('packageMethod')) {
  91. $this->registerTasksForPackageMethod($workflow, $this->getOption('packageMethod'));
  92. }
  93. if ($this->hasOption('transferMethod')) {
  94. $this->registerTasksForTransferMethod($workflow, $this->getOption('transferMethod'));
  95. }
  96. $workflow->afterStage('transfer', CreateSymlinksTask::class, $this);
  97. if ($this->hasOption('updateMethod')) {
  98. $this->registerTasksForUpdateMethod($workflow, (string)$this->getOption('updateMethod'));
  99. }
  100. // TODO Define tasks for local shell task and local git checkout
  101. $workflow
  102. ->addTask(CreateDirectoriesTask::class, 'initialize', $this)
  103. ->afterTask(CreateDirectoriesTask::class, GenericCreateDirectoriesTask::class, $this)
  104. ->addTask(SymlinkReleaseTask::class, 'switch', $this)
  105. ->addTask(CleanupReleasesTask::class, 'cleanup', $this);
  106. if ($this->hasOption('lockDeployment') && $this->getOption('lockDeployment') === true) {
  107. $workflow->addTask(LockDeploymentTask::class, 'lock', $this);
  108. $workflow->addTask(UnlockDeploymentTask::class, 'unlock', $this);
  109. }
  110. if ($deployment->getForceRun()) {
  111. $workflow->beforeTask(LockDeploymentTask::class, UnlockDeploymentTask::class, $this);
  112. }
  113. }
  114. public function setSymlinks(array $symlinks): self
  115. {
  116. $this->symlinks = $symlinks;
  117. return $this;
  118. }
  119. public function getSymlinks(): array
  120. {
  121. return $this->symlinks;
  122. }
  123. public function addSymlink(string $linkPath, string $sourcePath): self
  124. {
  125. $this->symlinks[$linkPath] = $sourcePath;
  126. return $this;
  127. }
  128. public function addSymlinks(array $symlinks): self
  129. {
  130. foreach ($symlinks as $linkPath => $sourcePath) {
  131. $this->addSymlink($linkPath, $sourcePath);
  132. }
  133. return $this;
  134. }
  135. public function setDirectories(array $directories): self
  136. {
  137. $this->directories = $directories;
  138. return $this;
  139. }
  140. public function getDirectories(): array
  141. {
  142. return $this->directories;
  143. }
  144. public function addDirectory(string $path): self
  145. {
  146. $this->directories[] = $path;
  147. return $this;
  148. }
  149. public function addDirectories(array $directories): self
  150. {
  151. foreach ($directories as $path) {
  152. $this->addDirectory($path);
  153. }
  154. return $this;
  155. }
  156. protected function registerTasksForPackageMethod(Workflow $workflow, ?string $packageMethod): void
  157. {
  158. switch ($packageMethod) {
  159. case 'git':
  160. $workflow->addTask(GitTask::class, 'package', $this);
  161. $workflow->defineTask(
  162. $localInstallTask = 'TYPO3\\Surf\\DefinedTask\\Composer\\LocalInstallTask',
  163. InstallTask::class,
  164. [
  165. 'nodeName' => 'localhost',
  166. 'useApplicationWorkspace' => true,
  167. 'additionalArguments' => ['--ignore-platform-reqs'],
  168. ]
  169. );
  170. $workflow->afterTask(GitTask::class, $localInstallTask, $this);
  171. break;
  172. }
  173. }
  174. protected function registerTasksForTransferMethod(Workflow $workflow, string $transferMethod): void
  175. {
  176. switch ($transferMethod) {
  177. case 'git':
  178. $workflow->addTask(GitCheckoutTask::class, 'transfer', $this);
  179. break;
  180. case 'rsync':
  181. $workflow->addTask(RsyncTask::class, 'transfer', $this);
  182. break;
  183. case 'scp':
  184. $workflow->addTask(ScpTask::class, 'transfer', $this);
  185. break;
  186. }
  187. }
  188. protected function registerTasksForUpdateMethod(Workflow $workflow, string $updateMethod): void
  189. {
  190. }
  191. }