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.
Test Failed
Pull Request — master (#1904)
by Anton
02:21
created

Deployer::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 11
ccs 0
cts 10
cp 0
crap 2
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\Ssh\Client;
12
use Deployer\Configuration\Configuration;
13
use Deployer\Console\Application;
14
use Deployer\Console\AutocompleteCommand;
15
use Deployer\Console\CommandEvent;
16
use Deployer\Console\TreeCommand;
17
use Deployer\Console\DiceCommand;
18
use Deployer\Console\InitCommand;
19
use Deployer\Executor\Status;
20
use Deployer\Console\Output\OutputWatcher;
21
use Deployer\Console\RunCommand;
22
use Deployer\Console\SshCommand;
23
use Deployer\Console\TaskCommand;
24
use Deployer\Console\WorkerCommand;
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\Task;
30
use Deployer\Component\ProcessRunner\Printer;
31
use Deployer\Component\ProcessRunner\ProcessRunner;
32
use Deployer\Utility\Reporter;
33
use Deployer\Utility\Rsync;
34
use Pimple\Container;
35
use Symfony\Component\Console;
36
use Symfony\Component\Console\Input\ArgvInput;
37
use Symfony\Component\Console\Output\ConsoleOutput;
38
use Symfony\Component\Console\Style\SymfonyStyle;
39
40
/**
41
 * Deployer class represents DI container for configuring
42
 *
43
 * @property Application $console
44
 * @property Task\TaskCollection|Task\Task[] $tasks
45
 * @property Host\HostCollection|Collection|Host\Host[] $hosts
46
 * @property Configuration $config
47
 * @property Rsync $rsync
48
 * @property Deployer\Component\Ssh\Client $sshClient
49
 * @property ProcessRunner $processRunner
50
 * @property Task\ScriptManager $scriptManager
51
 * @property Host\HostSelector $hostSelector
52
 * @property ParallelExecutor $executor
53
 * @property Status $informer
54
 * @property Status $logger
55
 * @property Printer $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 10
    public function __construct(Application $console)
70
    {
71 10
        parent::__construct();
72
73
        /******************************
74
         *           Console          *
75
         ******************************/
76
77
        $this['console'] = function () use ($console) {
78
            $console->catchIO(function ($input, $output) {
79
                $this['input'] = $input;
80
                $this['output'] = $output;
81
                return [$this['input'], $this['output']];
82
            });
83
            return $console;
84
        };
85
86
        /******************************
87
         *           Config           *
88
         ******************************/
89
90
        $this['config'] = function () {
91 10
            return new Configuration();
92
        };
93 10
        $this->config['ssh_multiplexing'] = true;
94 10
        $this->config['default_stage'] = null;
95
96
        /******************************
97
         *            Core            *
98
         ******************************/
99
100
        $this['pop'] = function ($c) {
101 1
            return new Printer($c['output']);
102
        };
103
        $this['sshClient'] = function ($c) {
104
            return new Client($c['output'], $c['pop'], $c['logger']);
105
        };
106
        $this['rsync'] = function ($c) {
107
            return new Rsync($c['pop']);
108
        };
109
        $this['processRunner'] = function ($c) {
110 1
            return new ProcessRunner($c['pop'], $c['logger']);
111
        };
112
        $this['tasks'] = function () {
113 10
            return new Task\TaskCollection();
114
        };
115
        $this['hosts'] = function () {
116 4
            return new Host\HostCollection();
117
        };
118
        $this['scriptManager'] = function ($c) {
119 2
            return new Task\ScriptManager($c['tasks']);
120
        };
121
        $this['hostSelector'] = function ($c) {
122
            $defaultStage = $c['config']['default_stage'];
123
            if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) {
124
                $defaultStage = call_user_func($defaultStage);
125
            }
126
            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...
127
        };
128
        $this['fail'] = function () {
129
            return new Collection();
130
        };
131
        $this['informer'] = function ($c) {
132
            return new Status($c['output']);
133
        };
134
        $this['executor'] = function ($c) {
135
            return new ParallelExecutor(
136
                $c['input'],
137
                $c['output'],
138
                $c['informer'],
139
                $c['console'],
140
                $c['sshClient'],
141
                $c['config']
142
            );
143
        };
144
145
        /******************************
146
         *           Logger           *
147
         ******************************/
148
149
        $this['log_handler'] = function () {
150 1
            return !empty($this->config['log_file'])
151
                ? new FileHandler($this->config['log_file'])
152 1
                : new NullHandler();
153
        };
154
        $this['logger'] = function () {
155 1
            return new Logger($this['log_handler']);
156
        };
157
158 10
        self::$instance = $this;
159
160
        task('connect', function () {
161
            $this['sshClient']->connect(currentHost());
162 10
        })->desc('Connect to remote server');
163 10
    }
164
165
    /**
166
     * @return Deployer
167
     */
168 25
    public static function get()
169
    {
170 25
        return self::$instance;
171
    }
172
173
    /**
174
     * Init console application
175
     */
176
    public function init()
177
    {
178
        $this->addConsoleCommands();
179
        $this->getConsole()->add(new WorkerCommand($this));
180
        $this->getConsole()->add(new DiceCommand());
181
        $this->getConsole()->add(new InitCommand());
182
        $this->getConsole()->add(new SshCommand($this));
183
        $this->getConsole()->add(new RunCommand($this));
184
        $this->getConsole()->add(new TreeCommand($this));
185
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
186
    }
187
188
    /**
189
     * Transform tasks to console commands.
190
     */
191
    public function addConsoleCommands()
192
    {
193
        $this->getConsole()->addUserArgumentsAndOptions();
194
195
        foreach ($this->tasks as $name => $task) {
196
            if ($task->isPrivate()) {
197
                continue;
198
            }
199
200
            $this->getConsole()->add(new TaskCommand($name, $task->getDescription(), $this));
201
        }
202
    }
203
204
    /**
205
     * @param string $name
206
     * @return mixed
207
     * @throws \InvalidArgumentException
208
     */
209 23
    public function __get($name)
210
    {
211 23
        if (isset($this[$name])) {
212 23
            return $this[$name];
213
        } else {
214 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
215
        }
216
    }
217
218
    /**
219
     * @return Application
220
     */
221
    public function getConsole()
222
    {
223
        return $this['console'];
224
    }
225
226
    /**
227
     * @return Console\Input\InputInterface
228
     */
229
    public function getInput()
230
    {
231
        return $this['input'];
232
    }
233
234
    /**
235
     * @return Console\Output\OutputInterface
236
     */
237
    public function getOutput()
238
    {
239
        return $this['output'];
240
    }
241
242
    /**
243
     * @param string $name
244
     * @return Console\Helper\HelperInterface
245
     */
246
    public function getHelper($name)
247
    {
248
        return $this->getConsole()->getHelperSet()->get($name);
249
    }
250
251
    /**
252
     * Run Deployer
253
     *
254
     * @param string $version
255
     * @param string $deployFile
256
     */
257
    public static function run($version, $deployFile)
258
    {
259
        // Init Deployer
260
        $console = new Application('Deployer', $version);
261
        $input = new ArgvInput();
262
        $output = new ConsoleOutput();
263
        $deployer = new self($console);
264
265
        // Require deploy.php file
266
        self::loadRecipe($deployFile);
267
268
        // Run Deployer
269
        $deployer->init();
270
        $console->run($input, $output);
271
    }
272
273
    /**
274
     * Collect anonymous stats about Deployer usage for improving developer experience.
275
     * If you are not comfortable with this, you will always be able to disable this
276
     * by setting `allow_anonymous_stats` to false in your deploy.php file.
277
     *
278
     * @param CommandEvent $commandEvent
279
     * @codeCoverageIgnore
280
     */
281
    public function collectAnonymousStats(CommandEvent $commandEvent)
282
    {
283
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
284
            return;
285
        }
286
287
        $stats = [
288
            'status' => 'success',
289
            'command_name' => $commandEvent->getCommand()->getName(),
290
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
291
            'hosts_count' => $this->hosts->count(),
292
            'deployer_version' => $this->getConsole()->getVersion(),
293
            'deployer_phar' => $this->getConsole()->isPharArchive(),
294
            'php_version' => phpversion(),
295
            'extension_pcntl' => extension_loaded('pcntl'),
296
            'extension_curl' => extension_loaded('curl'),
297
            '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))),
298
            'exception' => null,
299
        ];
300
301
        if ($commandEvent->getException() !== null) {
302
            $stats['status'] = 'error';
303
            $stats['exception'] = get_class($commandEvent->getException());
304
        }
305
306
        if ($stats['command_name'] === 'init') {
307
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
308
        }
309
310
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
311
            return;
312
        }
313
314
        Reporter::report($stats);
315
    }
316
317
    /**
318
     * Load recipe file
319
     *
320
     * @param string $deployFile
321
     *
322
     * @return void
323
     * @codeCoverageIgnore
324
     */
325
    public static function loadRecipe($deployFile)
326
    {
327
        if (is_readable($deployFile)) {
328
            // Prevent variable leak into deploy.php file
329
            call_user_func(function () use ($deployFile) {
330
                // reorder autoload stack.
331
                $originStack = spl_autoload_functions();
332
                require $deployFile;
333
                $newStack = spl_autoload_functions();
334
                if ($originStack[0] !== $newStack[0]) {
335
                    foreach (array_reverse($originStack) as $loader) {
336
                        spl_autoload_unregister($loader);
337
                        spl_autoload_register($loader, true, true);
338
                    }
339
                }
340
            });
341
        }
342
    }
343
344
    /**
345
     * @return string
346
     * @codeCoverageIgnore
347
     */
348
    public static function getCalledScript(): string
349
    {
350
        $executable = !empty($_SERVER['_']) ? $_SERVER['_'] : $_SERVER['PHP_SELF'];
351
        $shortcut = false !== strpos(getenv('PATH'), dirname($executable)) ? basename($executable) : $executable;
352
353
        if ($executable !== $_SERVER['PHP_SELF']) {
354
            return sprintf('%s %s', $shortcut, $_SERVER['PHP_SELF']);
355
        }
356
357
        return $shortcut;
358
    }
359
}
360