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.

Issues (130)

src/Deployer.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/* (c) Anton Medvedev <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Deployer;
12
13
use Deployer\Collection\Collection;
14
use Deployer\Command\BlackjackCommand;
15
use Deployer\Command\ConfigCommand;
16
use Deployer\Command\InitCommand;
17
use Deployer\Command\MainCommand;
18
use Deployer\Command\RunCommand;
19
use Deployer\Command\SshCommand;
20
use Deployer\Command\TreeCommand;
21
use Deployer\Command\WorkerCommand;
22
use Deployer\Component\PharUpdate\Console\Command as PharUpdateCommand;
23
use Deployer\Component\PharUpdate\Console\Helper as PharUpdateHelper;
24
use Deployer\Component\Pimple\Container;
25
use Deployer\ProcessRunner\Printer;
26
use Deployer\ProcessRunner\ProcessRunner;
27
use Deployer\Ssh\SshClient;
28
use Deployer\Configuration;
29
use Deployer\Executor\Master;
30
use Deployer\Executor\Messenger;
31
use Deployer\Host\Host;
32
use Deployer\Host\HostCollection;
33
use Deployer\Host\Localhost;
34
use Deployer\Importer\Importer;
35
use Deployer\Logger\Handler\FileHandler;
36
use Deployer\Logger\Handler\NullHandler;
37
use Deployer\Logger\Logger;
38
use Deployer\Selector\Selector;
39
use Deployer\Task\ScriptManager;
40
use Deployer\Task\TaskCollection;
41
use Deployer\Utility\Httpie;
42
use Deployer\Utility\Rsync;
43
use Symfony\Component\Console;
44
use Symfony\Component\Console\Application;
45
use Symfony\Component\Console\Input\ArgvInput;
46
use Symfony\Component\Console\Input\InputDefinition;
47
use Symfony\Component\Console\Input\InputInterface;
48
use Symfony\Component\Console\Input\InputOption;
49
use Symfony\Component\Console\Output\ConsoleOutput;
50
use Symfony\Component\Console\Output\OutputInterface;
51
use Throwable;
52
53
/**
54
 * @property Application $console
55
 * @property InputInterface $input
56
 * @property OutputInterface $output
57
 * @property Task\TaskCollection|Task\Task[] $tasks
58
 * @property HostCollection|Host[] $hosts
59
 * @property Configuration $config
60
 * @property Rsync $rsync
61
 * @property SshClient $sshClient
62
 * @property ProcessRunner $processRunner
63
 * @property Task\ScriptManager $scriptManager
64
 * @property Selector $selector
65
 * @property Master $master
66
 * @property Messenger $messenger
67
 * @property Messenger $logger
68
 * @property Printer $pop
69
 * @property Collection $fail
70
 * @property InputDefinition $inputDefinition
71
 * @property Importer $importer
72
 */
73
class Deployer extends Container
74
{
75
    private static Deployer $instance;
76
77
    public function __construct(Application $console)
78
    {
79
        parent::__construct();
80
81 20
        /******************************
82
         *           Console          *
83 20
         ******************************/
84
85
        $console->getDefinition()->addOption(
86
            new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'Recipe file path'),
87
        );
88
89 20
        $this['console'] = function () use ($console) {
90 20
            return $console;
91
        };
92
        $this['input'] = function () {
93
            throw new \RuntimeException('Uninitialized "input" in Deployer container.');
94 12
        };
95
        $this['output'] = function () {
96
            throw new \RuntimeException('Uninitialized "output" in Deployer container.');
97
        };
98
        $this['inputDefinition'] = function () {
99
            return new InputDefinition();
100
        };
101
        $this['questionHelper'] = function () {
102
            return $this->getHelper('question');
103 12
        };
104
105
        /******************************
106 12
         *           Config           *
107
         ******************************/
108
109
        $this['config'] = function () {
110
            return new Configuration();
111
        };
112
        // -l  act as if it had been invoked as a login shell (i.e. source ~/.profile file)
113
        // -s  commands are read from the standard input (no arguments should remain after this option)
114 20
        $this->config['shell'] = function () {
115
            if (currentHost() instanceof Localhost) {
116 20
                return 'bash -s'; // Non-login shell for localhost.
117 20
            }
118 20
            return 'bash -ls';
119 20
        };
120 20
        $this->config['forward_agent'] = true;
121 20
        $this->config['ssh_multiplexing'] = true;
122 20
123
        /******************************
124
         *            Core            *
125
         ******************************/
126
127
        $this['pop'] = function ($c) {
128
            return new Printer($c['output']);
129 14
        };
130
        $this['sshClient'] = function ($c) {
131
            return new SshClient($c['output'], $c['pop'], $c['logger']);
132 12
        };
133
        $this['rsync'] = function ($c) {
134
            return new Rsync($c['pop'], $c['output']);
135
        };
136
        $this['processRunner'] = function ($c) {
137
            return new ProcessRunner($c['pop'], $c['logger']);
138 10
        };
139
        $this['tasks'] = function () {
140
            return new TaskCollection();
141 15
        };
142
        $this['hosts'] = function () {
143
            return new HostCollection();
144 14
        };
145
        $this['scriptManager'] = function ($c) {
146
            return new ScriptManager($c['tasks']);
147 14
        };
148
        $this['selector'] = function ($c) {
149
            return new Selector($c['hosts']);
150 10
        };
151
        $this['fail'] = function () {
152
            return new Collection();
153 8
        };
154
        $this['messenger'] = function ($c) {
155
            return new Messenger($c['input'], $c['output'], $c['logger']);
156 12
        };
157
        $this['master'] = function ($c) {
158
            return new Master(
159 12
                $c['hosts'],
160 12
                $c['input'],
161 12
                $c['output'],
162 12
                $c['messenger'],
163
            );
164
        };
165
        $this['importer'] = function () {
166 12
            return new Importer();
167 12
        };
168 12
169 12
        /******************************
170 12
         *           Logger           *
171 12
         ******************************/
172 12
173
        $this['log_handler'] = function () {
174
            return !empty($this['log'])
175
                ? new FileHandler($this['log'])
176
                : new NullHandler();
177
        };
178
        $this['logger'] = function () {
179
            return new Logger($this['log_handler']);
180
        };
181 14
182
        self::$instance = $this;
183 14
    }
184
185
    public static function get(): self
186 14
    {
187
        return self::$instance;
188
    }
189 20
190 20
    public function init(): void
191
    {
192
        $this->addTaskCommands();
193
        $this->getConsole()->add(new BlackjackCommand());
194
        $this->getConsole()->add(new ConfigCommand($this));
195 29
        $this->getConsole()->add(new WorkerCommand($this));
196
        $this->getConsole()->add(new InitCommand());
197 29
        $this->getConsole()->add(new TreeCommand($this));
198
        $this->getConsole()->add(new SshCommand($this));
199
        $this->getConsole()->add(new RunCommand($this));
200
        if (self::isPharArchive()) {
201
            $selfUpdate = new PharUpdateCommand('self-update');
202
            $selfUpdate->setDescription('Updates deployer.phar to the latest version');
203 12
            $selfUpdate->setManifestUri('https://deployer.org/manifest.json');
204
            $selfUpdate->setRunningFile(DEPLOYER_BIN);
205 12
            $this->getConsole()->add($selfUpdate);
206 12
            $this->getConsole()->getHelperSet()->set(new PharUpdateHelper());
207 12
        }
208 12
    }
209 12
210 12
    /**
211 12
     * Transform tasks to console commands.
212 12
     */
213 12
    public function addTaskCommands(): void
214
    {
215
        foreach ($this->tasks as $name => $task) {
216
            $command = new MainCommand($name, $task->getDescription(), $this);
217
            $command->setHidden($task->isHidden());
218
219
            $this->getConsole()->add($command);
220 12
        }
221
    }
222
223
    public function __get(string $name): mixed
224
    {
225 12
        if (isset($this[$name])) {
226
            return $this[$name];
227 12
        } else {
228 12
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
229 12
        }
230
    }
231 12
232
    public function __set(string $name, mixed $value): void
233 12
    {
234
        $this[$name] = $value;
235
    }
236
237
    public function getConsole(): Application
238
    {
239
        return $this['console'];
240 27
    }
241
242 27
    public function getHelper(string $name): Console\Helper\HelperInterface
243 27
    {
244
        return $this->getConsole()->getHelperSet()->get($name);
245
    }
246
247
    public static function run(string $version, ?string $deployFile): void
248
    {
249
        if (str_contains($version, 'master')) {
250
            // Get version from composer.lock
251
            $lockFile = __DIR__ . '/../../../../composer.lock';
252
            if (file_exists($lockFile)) {
253 12
                $content = file_get_contents($lockFile);
254
                $json = json_decode($content);
255 12
                foreach ($json->packages as $package) {
256 12
                    if ($package->name === 'deployer/deployer') {
257
                        $version = $package->version;
258
                    }
259
                }
260
            }
261 12
        }
262
263 12
        // Version must be without "v" prefix.
264
        //    Incorrect: v7.0.0
265
        //    Correct: 7.0.0
266
        // But deployphp/deployer uses tags with "v", and it gets passed to
267
        // the composer.json file. Let's manually remove it from the version.
268
        if (preg_match("/^v/", $version)) {
269
            $version = substr($version, 1);
270 12
        }
271
272 12
        if (!defined('DEPLOYER_VERSION')) {
273
            define('DEPLOYER_VERSION', $version);
274
        }
275
276
        $input = new ArgvInput();
277
        $output = new ConsoleOutput();
278
279
        try {
280
            $console = new Application('Deployer', $version);
281
            $deployer = new self($console);
282
283
            // Import recipe file
284
            if (is_readable($deployFile ?? '')) {
285
                $deployer->importer->import($deployFile);
286
            }
287
288
            $deployer->init();
289
            $console->run($input, $output);
290
291
        } catch (Throwable $exception) {
292
            if (str_contains("$input", "-vvv")) {
293
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
294
            }
295
            self::printException($output, $exception);
296
297
            exit(1);
298
        }
299
    }
300
301
    public static function printException(OutputInterface $output, Throwable $exception): void
302
    {
303 12
        $class = get_class($exception);
304
        $file = basename($exception->getFile());
305 12
        $output->writeln([
306
            "<fg=white;bg=red> {$class} </> <comment>in {$file} on line {$exception->getLine()}:</>",
307
            "",
308
            implode("\n", array_map(function ($line) {
309 12
                return "  " . $line;
310
            }, explode("\n", $exception->getMessage()))),
311 12
            "",
312
        ]);
313 12
        if ($output->isDebug()) {
314 12
            $output->writeln($exception->getTraceAsString());
315
        }
316
317
        if ($exception->getPrevious()) {
318
            self::printException($output, $exception->getPrevious());
319
        }
320 12
    }
321
322 12
    public static function isWorker(): bool
323
    {
324
        return defined('MASTER_ENDPOINT');
325
    }
326
327
    /**
328
     * @return array|bool|string
329
     */
330
    public static function masterCall(Host $host, string $func, mixed ...$arguments): mixed
331
    {
332
        // As request to master will stop master permanently, wait a little bit
333
        // in order for ticker gather worker outputs and print it to user.
334
        usleep(100_000); // Sleep 100ms.
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_STRING, expecting ',' or ')' on line 334 at column 18
Loading history...
335
336
        return Httpie::get(MASTER_ENDPOINT . '/proxy')
337
            ->setopt(CURLOPT_CONNECTTIMEOUT, 0) // no timeout
338
            ->setopt(CURLOPT_TIMEOUT, 0) // no timeout
339
            ->jsonBody([
340
                'host' => $host->getAlias(),
341 1
                'func' => $func,
342 1
                'arguments' => $arguments,
343
            ])
344
            ->getJson();
345
    }
346
347
    public static function isPharArchive(): bool
348
    {
349
        return str_starts_with(__FILE__, 'phar:');
350
    }
351
}
352