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 ( f46b7f...632562 )
by Anton
02:07
created

src/Deployer.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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