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
Push — master ( 6c9176...e80da1 )
by Anton
03:08
created

src/Executor/ParallelExecutor.php (1 issue)

Severity

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 declare(strict_types=1);
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\Executor;
9
10
use Deployer\Component\Ssh\Client;
11
use Deployer\Configuration\Configuration;
12
use Deployer\Exception\Exception;
13
use Deployer\Exception\GracefulShutdownException;
14
use Deployer\Host\Host;
15
use Deployer\Host\Localhost;
16
use Deployer\Selector\Selector;
17
use Deployer\Task\Context;
18
use Deployer\Task\Task;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Output\OutputInterface;
21
use Symfony\Component\Process\Process;
22
23 1
const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
24
25
function spinner($message = '')
26
{
27 1
    $frame = FRAMES[(int)(microtime(true) * 10) % count(FRAMES)];
28 1
    return "  $frame $message\r";
29
}
30
31
class ParallelExecutor
32
{
33
    private $input;
34
    private $output;
35
    private $messenger;
36
    private $client;
37
    private $config;
38
39 8
    public function __construct(
40
        InputInterface $input,
41
        OutputInterface $output,
42
        Messenger $messenger,
43
        Client $client,
44
        Configuration $config
45
    )
46
    {
47 8
        $this->input = $input;
48 8
        $this->output = $output;
49 8
        $this->messenger = $messenger;
50 8
        $this->client = $client;
51 8
        $this->config = $config;
52 8
    }
53
54
    /**
55
     * @param Host[] $hosts
56
     */
57 8
    private function connect(array $hosts)
58
    {
59 View Code Duplication
        $callback = function (string $output) {
60
            $output = preg_replace('/\n$/', '', $output);
61
            if (strlen($output) !== 0) {
62
                $this->output->writeln($output);
63
            }
64 8
        };
65
66
        // Connect to each host sequentially, to prevent getting locked.
67 8
        foreach ($hosts as $host) {
68 8
            if ($host instanceof Localhost) {
69 8
                continue;
70
            }
71
            $process = $this->getProcess($host, new Task('connect'));
72
            $process->start();
73
74
            while ($process->isRunning()) {
75
                $this->gatherOutput([$process], $callback);
76
                $this->output->write(spinner(str_pad("connect {$host->tag()}", intval(getenv('COLUMNS')) - 1)));
77
                usleep(1000);
78
            }
79
        }
80
81
        // Clear spinner.
82 8
        $this->output->write(str_repeat(' ', intval(getenv('COLUMNS')) - 1) . "\r");
83 8
    }
84
85
    /**
86
     * @param Task[] $tasks
87
     * @param Host[] $hosts
88
     */
89 8
    public function run(array $tasks, array $hosts, $plan = null): int
90
    {
91 8
        $plan || $this->connect($hosts);
92
93 8
        $localhost = new Localhost();
0 ignored issues
show
$localhost is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
94 8
        $globalLimit = (int)$this->input->getOption('limit') ?: count($hosts);
95
96 8
        foreach ($tasks as $task) {
97 8
            $plan || $this->messenger->startTask($task);
98
99 8
            $limit = min($globalLimit, $task->getLimit() ?? $globalLimit);
100 8
            $selector = $task->getSelector() ?? Selector::parse('all');
101
102 8
            if ($limit === 1 || count($hosts) === 1) {
103 7
                foreach ($hosts as $host) {
104 7
                    if (!Selector::apply($selector, $host)) {
105
                        if ($plan) {
106
                            $plan->commit([], $task);
107
                        }
108
                        continue;
109
                    }
110
111 7
                    if ($plan) {
112
                        $plan->commit([$host], $task);
113
                        continue;
114
                    }
115
116
                    try {
117 7
                        $host->getConfig()->load();
118 7
                        Exception::setTaskSourceLocation($task->getSourceLocation());
119
120 7
                        $task->run(new Context($host, $this->input, $this->output));
121
122 7
                        $host->getConfig()->save();
123 1
                    } catch (GracefulShutdownException $exception) {
124
                        $this->messenger->renderException($exception, $host);
125
                        return GracefulShutdownException::EXIT_CODE;
126 1
                    } catch (\Throwable $exception) {
127 1
                        $this->messenger->renderException($exception, $host);
128 1
                        return 1;
129
                    }
130
                }
131
            } else {
132 1
                foreach (array_chunk($hosts, $limit) as $chunk) {
133 1
                    $exitCode = $this->runTask($chunk, $task, $plan);
134 1
                    if ($exitCode !== 0) {
135
                        return $exitCode;
136
                    }
137
                }
138
            }
139
140 8
            $this->messenger->endTask($task);
141
        }
142
143 8
        return 0;
144
    }
145
146 1
    private function runTask(array $hosts, Task $task, Planner $plan = null): int
147
    {
148 1
        $processes = [];
149 1
        $selectedHosts = [];
150 1
        foreach ($hosts as $host) {
151 1
            $selector = $task->getSelector();
152 1
            if ($selector === null || Selector::apply($selector, $host)) {
153 1
                $selectedHosts[] = $host;
154 1
                $plan || $processes[] = $this->getProcess($host, $task);
155
            }
156
        }
157
158 1
        if ($plan) {
159
            $plan->commit($selectedHosts, $task);
160
            return 0;
161
        }
162
163 View Code Duplication
        $callback = function (string $output) {
164 1
            $output = preg_replace('/\n$/', '', $output);
165 1
            if (strlen($output) !== 0) {
166 1
                $this->output->writeln($output);
167
            }
168 1
        };
169
170 1
        $this->startProcesses($processes);
171
172 1
        while ($this->areRunning($processes)) {
173 1
            $this->gatherOutput($processes, $callback);
174 1
            $this->output->write(spinner());
175 1
            usleep(1000);
176
        }
177
178
        // Clear spinner.
179 1
        $this->output->write("    \r");
180
181 1
        $this->gatherOutput($processes, $callback);
182
183 1
        return $this->cumulativeExitCode($processes);
184
    }
185
186 1
    protected function getProcess(Host $host, Task $task): Process
187
    {
188 1
        $dep = PHP_BINARY . ' ' . DEPLOYER_BIN;
189 1
        $configDirectory = $host->get('config_directory');
190 1
        $decorated = $this->output->isDecorated() ? '--decorated' : '';
191 1
        $command = "$dep worker $task {$host->alias()} $configDirectory {$this->input} $decorated";
192
193 1
        if ($this->output->isDebug()) {
194
            $this->output->writeln("[{$host->tag()}] $command");
195
        }
196
197 1
        return Process::fromShellCommandline($command);
198
    }
199
200
    /**
201
     * @param Process[] $processes
202
     */
203 1
    protected function startProcesses(array $processes)
204
    {
205 1
        foreach ($processes as $process) {
206 1
            $process->start();
207
        }
208 1
    }
209
210
    /**
211
     * @param Process[] $processes
212
     */
213 1
    protected function areRunning(array $processes): bool
214
    {
215 1
        foreach ($processes as $process) {
216 1
            if ($process->isRunning()) {
217 1
                return true;
218
            }
219
        }
220
221 1
        return false;
222
    }
223
224
    /**
225
     * @param Process[] $processes
226
     */
227 1
    protected function gatherOutput(array $processes, callable $callback)
228
    {
229 1
        foreach ($processes as $process) {
230 1
            $output = $process->getIncrementalOutput();
231 1
            if (strlen($output) !== 0) {
232 1
                $callback($output);
233
            }
234
235 1
            $errorOutput = $process->getIncrementalErrorOutput();
236 1
            if (strlen($errorOutput) !== 0) {
237
                $callback($errorOutput);
238
            }
239
        }
240 1
    }
241
242
    /**
243
     * Gather the cumulative exit code for the processes.
244
     */
245 1
    protected function cumulativeExitCode(array $processes): int
246
    {
247 1
        foreach ($processes as $process) {
248 1
            if ($process->getExitCode() > 0) {
249
                return $process->getExitCode();
250
            }
251
        }
252
253 1
        return 0;
254
    }
255
}
256