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 ( b3cd52...71bd8a )
by Anton
02:19
created

Deployer   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 31

Test Coverage

Coverage 24.73%

Importance

Changes 0
Metric Value
dl 0
loc 284
ccs 23
cts 93
cp 0.2473
rs 10
c 0
b 0
f 0
wmc 29
lcom 1
cbo 31

11 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 4 1
B __construct() 0 95 2
A init() 0 11 1
A addTaskCommands() 0 10 3
A __get() 0 8 2
A getConsole() 0 4 1
A getHelper() 0 4 1
A run() 0 21 2
A load() 0 20 4
A printException() 0 15 1
C collectAnonymousStats() 0 35 11
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\Component\ProcessRunner\Printer;
12
use Deployer\Component\ProcessRunner\ProcessRunner;
13
use Deployer\Component\Ssh\Client;
14
use Deployer\Configuration\Configuration;
15
use Deployer\Console\Application;
16
use Deployer\Console\CommandEvent;
17
use Deployer\Console\DiceCommand;
18
use Deployer\Console\InitCommand;
19
use Deployer\Console\MainCommand;
20
use Deployer\Console\RunCommand;
21
use Deployer\Console\SshCommand;
22
use Deployer\Console\TreeCommand;
23
use Deployer\Console\WorkerCommand;
24
use Deployer\Executor\Messenger;
25
use Deployer\Executor\ParallelExecutor;
26
use Deployer\Logger\Handler\FileHandler;
27
use Deployer\Logger\Handler\NullHandler;
28
use Deployer\Logger\Logger;
29
use Deployer\Selector\Selector;
30
use Deployer\Task;
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\Input\InputDefinition;
37
use Symfony\Component\Console\Input\InputInterface;
38
use Symfony\Component\Console\Output\ConsoleOutput;
39
use Symfony\Component\Console\Output\OutputInterface;
40
use Throwable;
41
42
/**
43
 * Deployer class represents DI container for configuring
44
 *
45
 * @property Application $console
46
 * @property Task\TaskCollection|Task\Task[] $tasks
47
 * @property Host\HostCollection|Collection|Host\Host[] $hosts
48
 * @property Configuration $config
49
 * @property Rsync $rsync
50
 * @property Client $sshClient
51
 * @property ProcessRunner $processRunner
52
 * @property Task\ScriptManager $scriptManager
53
 * @property Selector $selector
54
 * @property ParallelExecutor $executor
55
 * @property Messenger $messenger
56
 * @property Messenger $logger
57
 * @property Printer $pop
58
 * @property Collection $fail
59
 * @property InputDefinition $inputDefinition
60
 */
61
class Deployer extends Container
62
{
63
    /**
64
     * Global instance of deployer. It's can be accessed only after constructor call.
65
     * @var Deployer
66
     */
67
    private static $instance;
68
69
    /**
70
     * @param Application $console
71
     */
72 10
    public function __construct(Application $console, InputInterface $input, OutputInterface $output)
73
    {
74 10
        parent::__construct();
75
76
        /******************************
77
         *           Console          *
78
         ******************************/
79
80
        $this['console'] = function () use ($console) {
81
            return $console;
82
        };
83
        $this['input'] = function () use ($input) {
84
            return $input;
85
        };
86
        $this['output'] = function () use ($output) {
87 1
            return $output;
88
        };
89
        $this['inputDefinition'] = function () {
90
            return new InputDefinition();
91
        };
92
93
        /******************************
94
         *           Config           *
95
         ******************************/
96
97
        $this['config'] = function () {
98 10
            return new Configuration();
99
        };
100 10
        $this->config['ssh_multiplexing'] = true;
101 10
        $this->config['default_stage'] = null;
102
103
        /******************************
104
         *            Core            *
105
         ******************************/
106
107
        $this['pop'] = function ($c) {
108 1
            return new Printer($c['output']);
109
        };
110
        $this['sshClient'] = function ($c) {
111
            return new Client($c['output'], $c['pop'], $c['logger']);
112
        };
113
        $this['rsync'] = function ($c) {
114
            return new Rsync($c['pop'], $c['output']);
115
        };
116
        $this['processRunner'] = function ($c) {
117 1
            return new ProcessRunner($c['pop'], $c['logger']);
118
        };
119
        $this['tasks'] = function () {
120 10
            return new Task\TaskCollection();
121
        };
122
        $this['hosts'] = function () {
123 4
            return new Host\HostCollection();
124
        };
125
        $this['scriptManager'] = function ($c) {
126 2
            return new Task\ScriptManager($c['tasks']);
127
        };
128
        $this['selector'] = function ($c) {
129
            return new Selector($c['hosts']);
130
        };
131
        $this['fail'] = function () {
132
            return new Collection();
133
        };
134
        $this['messenger'] = function ($c) {
135
            return new Messenger($c['input'], $c['output']);
136
        };
137
        $this['executor'] = function ($c) {
138
            return new ParallelExecutor(
139
                $c['input'],
140
                $c['output'],
141
                $c['messenger'],
142
                $c['console'],
143
                $c['sshClient'],
144
                $c['config']
145
            );
146
        };
147
148
        /******************************
149
         *           Logger           *
150
         ******************************/
151
152
        $this['log_handler'] = function () {
153 1
            return !empty($this->config['log_file'])
154
                ? new FileHandler($this->config['log_file'])
155 1
                : new NullHandler();
156
        };
157
        $this['logger'] = function () {
158 1
            return new Logger($this['log_handler']);
159
        };
160
161 10
        self::$instance = $this;
162
163
        task('connect', function () {
164
            $this['sshClient']->connect(currentHost());
165 10
        })->desc('Connect to remote server');
166 10
    }
167
168
    /**
169
     * @return Deployer
170
     */
171 19
    public static function get()
172
    {
173 19
        return self::$instance;
174
    }
175
176
    /**
177
     * Init console application
178
     */
179
    public function init()
180
    {
181
        $this->addTaskCommands();
182
        $this->getConsole()->add(new WorkerCommand($this));
183
        $this->getConsole()->add(new DiceCommand());
184
        $this->getConsole()->add(new InitCommand());
185
        $this->getConsole()->add(new TreeCommand($this));
186
        $this->getConsole()->add(new SshCommand($this));
187
        $this->getConsole()->add(new RunCommand($this));
188
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
189
    }
190
191
    /**
192
     * Transform tasks to console commands.
193
     */
194
    public function addTaskCommands()
195
    {
196
        foreach ($this->tasks as $name => $task) {
197
            if ($task->isHidden()) {
198
                continue;
199
            }
200
201
            $this->getConsole()->add(new MainCommand($name, $task->getDescription(), $this));
202
        }
203
    }
204
205
    /**
206
     * @param string $name
207
     * @return mixed
208
     * @throws \InvalidArgumentException
209
     */
210 17
    public function __get($name)
211
    {
212 17
        if (isset($this[$name])) {
213 17
            return $this[$name];
214
        } else {
215 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
216
        }
217
    }
218
219
    /**
220
     * @return Application
221
     */
222
    public function getConsole()
223
    {
224
        return $this['console'];
225
    }
226
227
    /**
228
     * @param string $name
229
     * @return Console\Helper\HelperInterface
230
     */
231
    public function getHelper($name)
232
    {
233
        return $this->getConsole()->getHelperSet()->get($name);
234
    }
235
236
    /**
237
     * Run Deployer
238
     *
239
     * @param string $version
240
     * @param string $deployFile
241
     */
242
    public static function run($version, $deployFile)
243
    {
244
        // Init Deployer
245
        $console = new Application('Deployer', $version);
246
        $input = new ArgvInput();
247
        $output = new ConsoleOutput();
248
        $deployer = new self($console, $input, $output);
249
250
        try {
251
252
            // Require deploy.php file
253
            self::load($deployFile);
254
255
            // Run Deployer
256
            $deployer->init();
257
            $console->run($input, $output);
258
259
        } catch (Throwable $exception) {
260
            self::printException($output, $exception);
261
        }
262
    }
263
264
    public static function load(string $deployFile)
265
    {
266
        if (is_readable($deployFile)) {
267
            // Prevent variable leak into deploy.php file
268
            call_user_func(function () use ($deployFile) {
269
                // Reorder autoload stack
270
                $originStack = spl_autoload_functions();
271
272
                require $deployFile;
273
274
                $newStack = spl_autoload_functions();
275
                if ($originStack[0] !== $newStack[0]) {
276
                    foreach (array_reverse($originStack) as $loader) {
277
                        spl_autoload_unregister($loader);
278
                        spl_autoload_register($loader, true, true);
279
                    }
280
                }
281
            });
282
        }
283
    }
284
285
    private static function printException(OutputInterface $output, Throwable $exception)
286
    {
287
        $class = get_class($exception);
288
        $file = basename($exception->getFile());
289
        $output->writeln([
290
            "<fg=white;bg=red> {$class} </> <comment>in {$file} on line {$exception->getLine()}:</>",
291
            "",
292
            implode("\n", array_map(function ($line) {
293
                return "  " . $line;
294
            }, explode("\n", $exception->getMessage()))),
295
            "",
296
        ]);
297
        $output->writeln($exception->getTraceAsString());
298
        return;
299
    }
300
301
    /**
302
     * Collect anonymous stats about Deployer usage for improving developer experience.
303
     * If you are not comfortable with this, you will always be able to disable this
304
     * by setting `allow_anonymous_stats` to false in your deploy.php file.
305
     *
306
     * @param CommandEvent $commandEvent
307
     * @codeCoverageIgnore
308
     */
309
    public function collectAnonymousStats(CommandEvent $commandEvent)
310
    {
311
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
312
            return;
313
        }
314
315
        $stats = [
316
            'status' => 'success',
317
            'command_name' => $commandEvent->getCommand()->getName(),
318
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
319
            'hosts_count' => $this->hosts->count(),
320
            'deployer_version' => $this->getConsole()->getVersion(),
321
            'deployer_phar' => $this->getConsole()->isPharArchive(),
322
            'php_version' => phpversion(),
323
            'extension_pcntl' => extension_loaded('pcntl'),
324
            'extension_curl' => extension_loaded('curl'),
325
            '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))),
326
            'exception' => null,
327
        ];
328
329
        if ($commandEvent->getException() !== null) {
330
            $stats['status'] = 'error';
331
            $stats['exception'] = get_class($commandEvent->getException());
332
        }
333
334
        if ($stats['command_name'] === 'init') {
335
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
336
        }
337
338
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
339
            return;
340
        }
341
342
        Reporter::report($stats);
343
    }
344
}
345