GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( e1606a...756f12 )
by Anton
02:23
created

Deployer::getConsole()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/* (c) Anton Medvedev <[email protected]>
3
 *
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace Deployer;
9
10
use Deployer\Collection\Collection;
11
use Deployer\Console\Application;
12
use Deployer\Console\AutocompleteCommand;
13
use Deployer\Console\CommandEvent;
14
use Deployer\Console\DebugCommand;
15
use Deployer\Console\InitCommand;
16
use Deployer\Console\Output\Informer;
17
use Deployer\Console\Output\OutputWatcher;
18
use Deployer\Console\RunCommand;
19
use Deployer\Console\SshCommand;
20
use Deployer\Console\TaskCommand;
21
use Deployer\Console\WorkerCommand;
22
use Deployer\Executor\ParallelExecutor;
23
use Deployer\Executor\SeriesExecutor;
24
use Deployer\Logger\Handler\FileHandler;
25
use Deployer\Logger\Handler\NullHandler;
26
use Deployer\Logger\Logger;
27
use function Deployer\Support\array_merge_alternate;
28
use Deployer\Task;
29
use Deployer\Utility\ProcessOutputPrinter;
30
use Deployer\Utility\ProcessRunner;
31
use Deployer\Utility\Reporter;
32
use Deployer\Utility\Rsync;
33
use Pimple\Container;
34
use Symfony\Component\Console;
35
use Symfony\Component\Console\Input\ArgvInput;
36
use Symfony\Component\Console\Output\ConsoleOutput;
37
use Symfony\Component\Console\Style\SymfonyStyle;
38
39
/**
40
 * Deployer class represents DI container for configuring
41
 *
42
 * @property Application console
43
 * @property Task\TaskCollection|Task\Task[] tasks
44
 * @property Host\HostCollection|Collection|Host\Host[] hosts
45
 * @property Collection config
46
 * @property Rsync rsync
47
 * @property Ssh\Client sshClient
48
 * @property ProcessRunner processRunner
49
 * @property Task\ScriptManager scriptManager
50
 * @property Host\HostSelector hostSelector
51
 * @property SeriesExecutor seriesExecutor
52
 * @property ParallelExecutor parallelExecutor
53
 * @property Informer informer
54
 * @property Logger logger
55
 * @property ProcessOutputPrinter pop
56
 * @property Collection fail
57
 */
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 32
    public function __construct(Application $console)
70
    {
71 32
        parent::__construct();
72
73
        /******************************
74
         *           Console          *
75
         ******************************/
76
77
        $this['console'] = function () use ($console) {
78 17
            $console->catchIO(function ($input, $output) {
79 16
                $this['input'] = $input;
80 16
                $this['output'] =  new OutputWatcher($output);
81 16
                return [$this['input'], $this['output']];
82 17
            });
83 17
            return $console;
84
        };
85
86
        /******************************
87
         *           Config           *
88
         ******************************/
89
90 32
        $this['config'] = function () {
91 32
            return new Collection();
92
        };
93 32
        $this->config['ssh_multiplexing'] = true;
94 32
        $this->config['default_stage'] = null;
95
96
        /******************************
97
         *            Core            *
98
         ******************************/
99
100 10
        $this['pop'] = function ($c) {
101 10
            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 10
        $this['processRunner'] = function ($c) {
110 10
            return new ProcessRunner($c['pop']);
111
        };
112 21
        $this['tasks'] = function () {
113 21
            return new Task\TaskCollection();
114
        };
115 21
        $this['hosts'] = function () {
116 21
            return new Host\HostCollection();
117
        };
118 18
        $this['scriptManager'] = function ($c) {
119 18
            return new Task\ScriptManager($c['tasks']);
120
        };
121 16
        $this['hostSelector'] = function ($c) {
122 16
            $defaultStage = $c['config']['default_stage'];
123 16
            if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) {
124
                $defaultStage = call_user_func($defaultStage);
125
            }
126 16
            return new Host\HostSelector($c['hosts'], $defaultStage);
127
        };
128 12
        $this['fail'] = function () {
129 12
            return new Collection();
130
        };
131 16
        $this['informer'] = function ($c) {
132 16
            return new Informer($c['output']);
133
        };
134 11
        $this['seriesExecutor'] = function ($c) {
135 11
            return new SeriesExecutor($c['input'], $c['output'], $c['informer']);
136
        };
137 5
        $this['parallelExecutor'] = function ($c) {
138 5
            return new ParallelExecutor($c['input'], $c['output'], $c['informer'], $c['console']);
139
        };
140
141
        /******************************
142
         *           Logger           *
143
         ******************************/
144
145 11
        $this['log_handler'] = function () {
146 11
            return !empty($this->config['log_file'])
147
                ? new FileHandler($this->config['log_file'])
148 11
                : new NullHandler();
149
        };
150 11
        $this['logger'] = function () {
151 11
            return new Logger($this['log_handler']);
152
        };
153
154
        /******************************
155
         *        Init command        *
156
         ******************************/
157
158 17
        $this['init_command'] = function () {
159 17
            return new InitCommand();
160
        };
161
162 32
        self::$instance = $this;
163 32
    }
164
165
    /**
166
     * @return Deployer
167
     */
168 34
    public static function get()
169
    {
170 34
        return self::$instance;
171
    }
172
173
    /**
174
     * @param string $name
175
     * @param mixed $value
176
     */
177 16
    public static function setDefault($name, $value)
178
    {
179 16
        Deployer::get()->config[$name] = $value;
180 16
    }
181
182
    /**
183
     * @param string $name
184
     * @param mixed $default
185
     * @return mixed
186
     */
187 15
    public static function getDefault($name, $default = null)
188
    {
189 15
        return self::hasDefault($name) ? Deployer::get()->config[$name] : $default;
190
    }
191
192
    /**
193
     * @param string $name
194
     * @return boolean
195
     */
196 15
    public static function hasDefault($name)
197
    {
198 15
        return isset(Deployer::get()->config[$name]);
199
    }
200
201
    /**
202
     * @param string $name
203
     * @param array $array
204
     */
205 2
    public static function addDefault($name, $array)
206
    {
207 2
        if (self::hasDefault($name)) {
208 2
            $config = self::getDefault($name);
209 2
            if (!is_array($config)) {
210 1
                throw new \RuntimeException("Configuration parameter `$name` isn't array.");
211
            }
212 1
            self::setDefault($name, array_merge_alternate($config, $array));
213
        } else {
214
            self::setDefault($name, $array);
215
        }
216 1
    }
217
218
    /**
219
     * Init console application
220
     */
221 17
    public function init()
222
    {
223 17
        $this->addConsoleCommands();
224 17
        $this->getConsole()->add(new WorkerCommand($this));
225 17
        $this->getConsole()->add($this['init_command']);
226 17
        $this->getConsole()->add(new SshCommand($this));
227 17
        $this->getConsole()->add(new RunCommand($this));
228 17
        $this->getConsole()->add(new DebugCommand($this));
229 17
        $this->getConsole()->add(new AutocompleteCommand());
230 17
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
231 17
    }
232
233
    /**
234
     * Transform tasks to console commands.
235
     */
236 17
    public function addConsoleCommands()
237
    {
238 17
        $this->getConsole()->addUserArgumentsAndOptions();
239
240 17
        foreach ($this->tasks as $name => $task) {
241 17
            if ($task->isPrivate()) {
242 12
                continue;
243
            }
244
245 17
            $this->getConsole()->add(new TaskCommand($name, $task->getDescription(), $this));
246
        }
247 17
    }
248
249
    /**
250
     * @param string $name
251
     * @return mixed
252
     * @throws \InvalidArgumentException
253
     */
254 37
    public function __get($name)
255
    {
256 37
        if (isset($this[$name])) {
257 37
            return $this[$name];
258
        } else {
259 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
260
        }
261
    }
262
263
    /**
264
     * @return Application
265
     */
266 17
    public function getConsole()
267
    {
268 17
        return $this['console'];
269
    }
270
271
    /**
272
     * @return Console\Input\InputInterface
273
     */
274
    public function getInput()
275
    {
276
        return $this['input'];
277
    }
278
279
    /**
280
     * @return Console\Output\OutputInterface
281
     */
282
    public function getOutput()
283
    {
284
        return $this['output'];
285
    }
286
287
    /**
288
     * @param string $name
289
     * @return Console\Helper\HelperInterface
290
     */
291
    public function getHelper($name)
292
    {
293
        return $this->getConsole()->getHelperSet()->get($name);
294
    }
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)
338
    {
339
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
340
            return;
341
        }
342
343
        $stats = [
344
            'status' => 'success',
345
            'command_name' => $commandEvent->getCommand()->getName(),
346
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
347
            'hosts_count' => $this->hosts->count(),
348
            'deployer_version' => $this->getConsole()->getVersion(),
349
            'deployer_phar' => $this->getConsole()->isPharArchive(),
350
            'php_version' => phpversion(),
351
            'extension_pcntl' => extension_loaded('pcntl'),
352
            'extension_curl' => extension_loaded('curl'),
353
            'os' => defined('PHP_OS_FAMILY') ? PHP_OS_FAMILY : (stristr(PHP_OS, 'DAR') ? 'OSX' : (stristr(PHP_OS, 'WIN') ? 'WIN' : (stristr(PHP_OS, 'LINUX') ? 'LINUX' : PHP_OS))),
354
            'exception' => null,
355
        ];
356
357
        if ($commandEvent->getException() !== null) {
358
            $stats['status'] = 'error';
359
            $stats['exception'] = get_class($commandEvent->getException());
360
        }
361
362
        if ($stats['command_name'] === 'init') {
363
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
364
        }
365
366
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
367
            return;
368
        }
369
370
        Reporter::report($stats);
371
    }
372
373
    /**
374
     * Load recipe file
375
     *
376
     * @param string $deployFile
377
     *
378
     * @return void
379
     * @codeCoverageIgnore
380
     */
381
    public static function loadRecipe($deployFile)
382
    {
383
        if (is_readable($deployFile)) {
384
            // Prevent variable leak into deploy.php file
385
            call_user_func(function () use ($deployFile) {
386
                // reorder autoload stack.
387
                $originStack = spl_autoload_functions();
388
                require $deployFile;
389
                $newStack = spl_autoload_functions();
390
                if ($originStack[0] !== $newStack[0]) {
391
                    foreach (array_reverse($originStack) as $loader) {
392
                        spl_autoload_unregister($loader);
393
                        spl_autoload_register($loader, true, true);
394
                    }
395
                }
396
            });
397
        }
398
    }
399
}
400