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 ( c538d5...8bac07 )
by Anton
02:32
created

Deployer::getCalledScript()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
nc 8
nop 0
dl 0
loc 11
ccs 0
cts 0
cp 0
crap 20
rs 9.9
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\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\RunCommand;
20
use Deployer\Console\SshCommand;
21
use Deployer\Console\MainCommand;
22
use Deployer\Console\TreeCommand;
23
use Deployer\Console\WorkerCommand;
24
use Deployer\Executor\ParallelExecutor;
25
use Deployer\Executor\Messenger;
26
use Deployer\Logger\Handler\FileHandler;
27
use Deployer\Logger\Handler\NullHandler;
28
use Deployer\Logger\Logger;
29
use Deployer\Task;
30
use Deployer\Utility\Reporter;
31
use Deployer\Utility\Rsync;
32
use Pimple\Container;
33
use Symfony\Component\Console;
34
use Symfony\Component\Console\Input\ArgvInput;
35
use Symfony\Component\Console\Input\InputInterface;
36
use Symfony\Component\Console\Output\ConsoleOutput;
37
use Symfony\Component\Console\Output\OutputInterface;
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 Configuration $config
46
 * @property Rsync $rsync
47
 * @property Client $sshClient
48
 * @property ProcessRunner $processRunner
49
 * @property Task\ScriptManager $scriptManager
50
 * @property Host\HostSelector $hostSelector
51
 * @property ParallelExecutor $executor
52
 * @property Messenger $messenger
53
 * @property Messenger $logger
54
 * @property Printer $pop
55
 * @property Collection $fail
56
 */
57
class Deployer extends Container
58
{
59
    /**
60
     * Global instance of deployer. It's can be accessed only after constructor call.
61
     * @var Deployer
62
     */
63
    private static $instance;
64
65
    /**
66
     * @param Application $console
67
     */
68 10
    public function __construct(Application $console, InputInterface $input, OutputInterface $output)
69
    {
70 10
        parent::__construct();
71
72
        /******************************
73
         *           Console          *
74
         ******************************/
75
76
        $this['console'] = function () use ($console) {
77
            return $console;
78
        };
79
80
        $this['input'] = function () use ($input) {
81
            return $input;
82
        };
83
84
        $this['output'] = function () use ($output) {
85 1
            return $output;
86
        };
87
88
        /******************************
89
         *           Config           *
90
         ******************************/
91
92
        $this['config'] = function () {
93 10
            return new Configuration();
94
        };
95 10
        $this->config['ssh_multiplexing'] = true;
96 10
        $this->config['default_stage'] = null;
97
98
        /******************************
99
         *            Core            *
100
         ******************************/
101
102
        $this['pop'] = function ($c) {
103 1
            return new Printer($c['output']);
104
        };
105
        $this['sshClient'] = function ($c) {
106
            return new Client($c['output'], $c['pop'], $c['logger']);
107
        };
108
        $this['rsync'] = function ($c) {
109
            return new Rsync($c['pop'], $c['output']);
110
        };
111
        $this['processRunner'] = function ($c) {
112 1
            return new ProcessRunner($c['pop'], $c['logger']);
113
        };
114
        $this['tasks'] = function () {
115 10
            return new Task\TaskCollection();
116
        };
117
        $this['hosts'] = function () {
118 4
            return new Host\HostCollection();
119
        };
120
        $this['scriptManager'] = function ($c) {
121 2
            return new Task\ScriptManager($c['tasks']);
122
        };
123
        $this['hostSelector'] = function ($c) {
124
            $defaultStage = $c['config']['default_stage'];
125
            if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) {
126
                $defaultStage = call_user_func($defaultStage);
127
            }
128
            return new Host\HostSelector($c['hosts'], $defaultStage);
0 ignored issues
show
Unused Code introduced by
The call to HostSelector::__construct() has too many arguments starting with $defaultStage.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
129
        };
130
        $this['fail'] = function () {
131
            return new Collection();
132
        };
133
        $this['messenger'] = function ($c) {
134
            return new Messenger($c['input'], $c['output']);
135
        };
136
        $this['executor'] = function ($c) {
137
            return new ParallelExecutor(
138
                $c['input'],
139
                $c['output'],
140
                $c['messenger'],
141
                $c['console'],
142
                $c['sshClient'],
143
                $c['config']
144
            );
145
        };
146
147
        /******************************
148
         *           Logger           *
149
         ******************************/
150
151
        $this['log_handler'] = function () {
152 1
            return !empty($this->config['log_file'])
153
                ? new FileHandler($this->config['log_file'])
154 1
                : new NullHandler();
155
        };
156
        $this['logger'] = function () {
157 1
            return new Logger($this['log_handler']);
158
        };
159
160 10
        self::$instance = $this;
161
162
        task('connect', function () {
163
            $this['sshClient']->connect(currentHost());
164 10
        })->desc('Connect to remote server');
165 10
    }
166
167
    /**
168
     * @return Deployer
169
     */
170 25
    public static function get()
171
    {
172 25
        return self::$instance;
173
    }
174
175
    /**
176
     * Init console application
177
     */
178
    public function init()
179
    {
180
        $this->addConsoleCommands();
181
        $this->getConsole()->add(new WorkerCommand($this));
182
        $this->getConsole()->add(new DiceCommand());
183
        $this->getConsole()->add(new InitCommand());
184
        $this->getConsole()->add(new SshCommand($this));
185
        $this->getConsole()->add(new RunCommand($this));
186
        $this->getConsole()->add(new TreeCommand($this));
187
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
188
    }
189
190
    /**
191
     * Transform tasks to console commands.
192
     */
193
    public function addConsoleCommands()
194
    {
195
        $this->getConsole()->addUserArgumentsAndOptions();
196
197
        foreach ($this->tasks->all() as $name => $task) {
198
            if ($task->isHidden()) {
199
                continue;
200
            }
201
202
            $this->getConsole()->add(new MainCommand($name, $task->getDescription(), $this));
203
        }
204
    }
205
206
    /**
207
     * @param string $name
208
     * @return mixed
209
     * @throws \InvalidArgumentException
210
     */
211 23
    public function __get($name)
212
    {
213 23
        if (isset($this[$name])) {
214 23
            return $this[$name];
215
        } else {
216 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
217
        }
218
    }
219
220
    /**
221
     * @return Application
222
     */
223
    public function getConsole()
224
    {
225
        return $this['console'];
226
    }
227
228
    /**
229
     * @return Console\Input\InputInterface
230
     */
231
    public function getInput()
232
    {
233
        return $this['input'];
234
    }
235
236
    /**
237
     * @return Console\Output\OutputInterface
238
     */
239
    public function getOutput()
240
    {
241
        return $this['output'];
242
    }
243
244
    /**
245
     * @param string $name
246
     * @return Console\Helper\HelperInterface
247
     */
248
    public function getHelper($name)
249
    {
250
        return $this->getConsole()->getHelperSet()->get($name);
251
    }
252
253
    /**
254
     * Run Deployer
255
     *
256
     * @param string $version
257
     * @param string $deployFile
258
     */
259
    public static function run($version, $deployFile)
260
    {
261
        // Init Deployer
262
        $console = new Application('Deployer', $version);
263
        $input = new ArgvInput();
264
        $output = new ConsoleOutput();
265
        $deployer = new self($console, $input, $output);
266
267
        try {
268
            // Require deploy.php file
269
            self::load($deployFile);
270
        } catch (\Throwable $exception) {
271
            $class = get_class($exception);
272
            $file = basename($exception->getFile());
273
            $output->writeln([
274
                "<fg=white;bg=red> {$class} </> <comment>in {$file} on line {$exception->getLine()}:</>",
275
                "",
276
                implode("\n", array_map(function ($line) {
277
                    return "  " . $line;
278
                }, explode("\n", $exception->getMessage()))),
279
                "",
280
            ]);
281
            $output->writeln($exception->getTraceAsString());
282
            return;
283
        }
284
285
        // Run Deployer
286
        $deployer->init();
287
        $console->run($input, $output);
288
    }
289
290
    /**
291
     * Collect anonymous stats about Deployer usage for improving developer experience.
292
     * If you are not comfortable with this, you will always be able to disable this
293
     * by setting `allow_anonymous_stats` to false in your deploy.php file.
294
     *
295
     * @param CommandEvent $commandEvent
296
     * @codeCoverageIgnore
297
     */
298
    public function collectAnonymousStats(CommandEvent $commandEvent)
299
    {
300
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
301
            return;
302
        }
303
304
        $stats = [
305
            'status' => 'success',
306
            'command_name' => $commandEvent->getCommand()->getName(),
307
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
308
            'hosts_count' => $this->hosts->count(),
309
            'deployer_version' => $this->getConsole()->getVersion(),
310
            'deployer_phar' => $this->getConsole()->isPharArchive(),
311
            'php_version' => phpversion(),
312
            'extension_pcntl' => extension_loaded('pcntl'),
313
            'extension_curl' => extension_loaded('curl'),
314
            '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))),
315
            'exception' => null,
316
        ];
317
318
        if ($commandEvent->getException() !== null) {
319
            $stats['status'] = 'error';
320
            $stats['exception'] = get_class($commandEvent->getException());
321
        }
322
323
        if ($stats['command_name'] === 'init') {
324
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
325
        }
326
327
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
328
            return;
329
        }
330
331
        Reporter::report($stats);
332
    }
333
334
    /**
335
     * Load recipe file.
336
     *
337
     * @param string $deployFile
338
     */
339
    public static function load(string $deployFile)
340
    {
341
        if (is_readable($deployFile)) {
342
            // Prevent variable leak into deploy.php file
343
            call_user_func(function () use ($deployFile) {
344
                // Reorder autoload stack
345
                $originStack = spl_autoload_functions();
346
347
                require $deployFile;
348
349
                $newStack = spl_autoload_functions();
350
                if ($originStack[0] !== $newStack[0]) {
351
                    foreach (array_reverse($originStack) as $loader) {
352
                        spl_autoload_unregister($loader);
353
                        spl_autoload_register($loader, true, true);
354
                    }
355
                }
356
            });
357
        }
358
    }
359
}
360