1 | <?php |
||
58 | class Deployer extends Container |
||
59 | { |
||
60 | /** |
||
61 | * Global instance of deployer. It's can be accessed only after constructor call. |
||
62 | * @var Deployer |
||
63 | */ |
||
64 | private static $instance; |
||
65 | |||
66 | /** |
||
67 | * @param Application $console |
||
68 | */ |
||
69 | 18 | public function __construct(Application $console) |
|
70 | { |
||
71 | 18 | parent::__construct(); |
|
72 | |||
73 | /****************************** |
||
74 | * Console * |
||
75 | ******************************/ |
||
76 | |||
77 | $this['console'] = function () use ($console) { |
||
78 | $console->catchIO(function ($input, $output) { |
||
79 | 3 | $this['input'] = $input; |
|
80 | 3 | $this['output'] = new OutputWatcher($output); |
|
81 | 3 | return [$this['input'], $this['output']]; |
|
82 | 4 | }); |
|
83 | 4 | return $console; |
|
84 | }; |
||
85 | |||
86 | /****************************** |
||
87 | * Config * |
||
88 | ******************************/ |
||
89 | |||
90 | $this['config'] = function () { |
||
91 | 18 | return new Collection(); |
|
92 | }; |
||
93 | 18 | $this->config['ssh_multiplexing'] = true; |
|
94 | 18 | $this->config['default_stage'] = null; |
|
95 | |||
96 | /****************************** |
||
97 | * Core * |
||
98 | ******************************/ |
||
99 | |||
100 | $this['pop'] = function ($c) { |
||
101 | return new ProcessOutputPrinter($c['output'], $c['logger']); |
||
102 | }; |
||
103 | $this['sshClient'] = function ($c) { |
||
104 | return new Ssh\Client($c['output'], $c['pop'], $c['config']['ssh_multiplexing']); |
||
105 | }; |
||
106 | $this['rsync'] = function ($c) { |
||
107 | return new Rsync($c['pop']); |
||
108 | }; |
||
109 | $this['processRunner'] = function ($c) { |
||
110 | return new ProcessRunner($c['pop']); |
||
111 | }; |
||
112 | $this['tasks'] = function () { |
||
113 | 8 | return new Task\TaskCollection(); |
|
114 | }; |
||
115 | $this['hosts'] = function () { |
||
116 | 8 | return new Host\HostCollection(); |
|
117 | }; |
||
118 | $this['scriptManager'] = function ($c) { |
||
119 | 5 | return new Task\ScriptManager($c['tasks']); |
|
120 | }; |
||
121 | $this['hostSelector'] = function ($c) { |
||
122 | 3 | $defaultStage = $c['config']['default_stage']; |
|
123 | 3 | if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) { |
|
124 | $defaultStage = call_user_func($defaultStage); |
||
125 | } |
||
126 | 3 | return new Host\HostSelector($c['hosts'], $defaultStage); |
|
127 | }; |
||
128 | $this['fail'] = function () { |
||
129 | 1 | return new Collection(); |
|
130 | }; |
||
131 | $this['informer'] = function ($c) { |
||
132 | 3 | return new Informer($c['output']); |
|
133 | }; |
||
134 | $this['seriesExecutor'] = function ($c) { |
||
135 | 3 | return new SeriesExecutor($c['input'], $c['output'], $c['informer']); |
|
136 | }; |
||
137 | $this['parallelExecutor'] = function ($c) { |
||
138 | return new ParallelExecutor($c['input'], $c['output'], $c['informer'], $c['console']); |
||
139 | }; |
||
140 | |||
141 | /****************************** |
||
142 | * Logger * |
||
143 | ******************************/ |
||
144 | |||
145 | $this['log_handler'] = function () { |
||
146 | return !empty($this->config['log_file']) |
||
147 | ? new FileHandler($this->config['log_file']) |
||
148 | : new NullHandler(); |
||
149 | }; |
||
150 | $this['logger'] = function () { |
||
151 | return new Logger($this['log_handler']); |
||
152 | }; |
||
153 | |||
154 | /****************************** |
||
155 | * Init command * |
||
156 | ******************************/ |
||
157 | |||
158 | $this['init_command'] = function () { |
||
159 | 4 | return new InitCommand(); |
|
160 | }; |
||
161 | |||
162 | 18 | self::$instance = $this; |
|
163 | 18 | } |
|
164 | |||
165 | /** |
||
166 | * @return Deployer |
||
167 | */ |
||
168 | 19 | public static function get() |
|
172 | |||
173 | /** |
||
174 | * @param string $name |
||
175 | * @param mixed $value |
||
176 | */ |
||
177 | 4 | public static function setDefault($name, $value) |
|
181 | |||
182 | /** |
||
183 | * @param string $name |
||
184 | * @param mixed $default |
||
185 | * @return mixed |
||
186 | */ |
||
187 | 4 | public static function getDefault($name, $default = null) |
|
191 | |||
192 | /** |
||
193 | * @param string $name |
||
194 | * @return boolean |
||
195 | */ |
||
196 | 4 | public static function hasDefault($name) |
|
200 | |||
201 | /** |
||
202 | * @param string $name |
||
203 | * @param array $array |
||
204 | */ |
||
205 | 2 | public static function addDefault($name, $array) |
|
217 | |||
218 | /** |
||
219 | * Init console application |
||
220 | */ |
||
221 | 4 | public function init() |
|
232 | |||
233 | /** |
||
234 | * Transform tasks to console commands. |
||
235 | */ |
||
236 | 4 | public function addConsoleCommands() |
|
248 | |||
249 | /** |
||
250 | * @param string $name |
||
251 | * @return mixed |
||
252 | * @throws \InvalidArgumentException |
||
253 | */ |
||
254 | 22 | public function __get($name) |
|
262 | |||
263 | /** |
||
264 | * @return Application |
||
265 | */ |
||
266 | 4 | public function getConsole() |
|
270 | |||
271 | /** |
||
272 | * @return Console\Input\InputInterface |
||
273 | */ |
||
274 | public function getInput() |
||
278 | |||
279 | /** |
||
280 | * @return Console\Output\OutputInterface |
||
281 | */ |
||
282 | public function getOutput() |
||
286 | |||
287 | /** |
||
288 | * @param string $name |
||
289 | * @return Console\Helper\HelperInterface |
||
290 | */ |
||
291 | public function getHelper($name) |
||
295 | |||
296 | /** |
||
297 | * Run Deployer |
||
298 | * |
||
299 | * @param string $version |
||
300 | * @param string $deployFile |
||
301 | */ |
||
302 | public static function run($version, $deployFile) |
||
303 | { |
||
304 | // Init Deployer |
||
305 | $console = new Application('Deployer', $version); |
||
306 | $input = new ArgvInput(); |
||
307 | $output = new ConsoleOutput(); |
||
308 | $deployer = new self($console); |
||
309 | |||
310 | // Pretty-print uncaught exceptions in symfony-console |
||
311 | set_exception_handler(function ($e) use ($input, $output, $deployer) { |
||
312 | $io = new SymfonyStyle($input, $output); |
||
313 | $io->block($e->getMessage(), get_class($e), 'fg=white;bg=red', ' ', true); |
||
314 | $io->block($e->getTraceAsString()); |
||
315 | |||
316 | $deployer->logger->log('['. get_class($e) .'] '. $e->getMessage()); |
||
317 | $deployer->logger->log($e->getTraceAsString()); |
||
318 | exit(1); |
||
319 | }); |
||
320 | |||
321 | // Require deploy.php file |
||
322 | self::loadRecipe($deployFile); |
||
323 | |||
324 | // Run Deployer |
||
325 | $deployer->init(); |
||
326 | $console->run($input, $output); |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Collect anonymous stats about Deployer usage for improving developer experience. |
||
331 | * If you are not comfortable with this, you will always be able to disable this |
||
332 | * by setting `allow_anonymous_stats` to false in your deploy.php file. |
||
333 | * |
||
334 | * @param CommandEvent $commandEvent |
||
335 | * @codeCoverageIgnore |
||
336 | */ |
||
337 | public function collectAnonymousStats(CommandEvent $commandEvent) |
||
372 | |||
373 | /** |
||
374 | * Load recipe file |
||
375 | * |
||
376 | * @param string $deployFile |
||
377 | * |
||
378 | * @return void |
||
379 | * @codeCoverageIgnore |
||
380 | */ |
||
381 | public static function loadRecipe($deployFile) |
||
399 | } |
||
400 |