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/Executor/ParallelExecutor.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 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\Collection\PersistentCollection;
11
use Deployer\Configuration\Configuration;
12
use Deployer\Console\Application;
13
use Deployer\Deployer;
14
use Deployer\Exception\Exception;
15
use Deployer\Exception\GracefulShutdownException;
16
use Deployer\Host\Host;
17
use Deployer\Host\Localhost;
18
use Deployer\Host\Storage;
19
use Deployer\Component\Ssh\Client;
20
use Deployer\Task\Context;
21
use Deployer\Task\Task;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Output\OutputInterface;
24
use Symfony\Component\Process\Process;
25
26
const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
27
28
function spinner($message = '')
29
{
30
    $frame = FRAMES[(int)(microtime(true) * 10) % count(FRAMES)];
31
    return "  $frame $message\r";
32
}
33
34
class ParallelExecutor
35
{
36
    private $input;
37
    private $output;
38
    private $messenger;
39
    private $console;
40
    private $client;
41
    private $config;
42
43
    public function __construct(
44
        InputInterface $input,
45
        OutputInterface $output,
46
        Messenger $messenger,
47
        Application $console,
48
        Client $client,
49
        Configuration $config
50
    )
51
    {
52
        $this->input = $input;
53
        $this->output = $output;
54
        $this->messenger = $messenger;
55
        $this->console = $console;
56
        $this->client = $client;
57
        $this->config = $config;
58
    }
59
60
    /**
61
     * @param Host[] $hosts
62
     */
63
    private function connect(array $hosts)
64
    {
65 View Code Duplication
        $callback = function (string $output) {
66
            $output = preg_replace('/\n$/', '', $output);
67
            if (strlen($output) !== 0) {
68
                $this->output->writeln($output);
69
            }
70
        };
71
72
        // Connect to each host sequentially, to prevent getting locked.
73
        foreach ($hosts as $host) {
74
            if ($host instanceof Localhost) {
75
                continue;
76
            }
77
            $process = $this->getProcess($host, new Task('connect'));
78
            $process->start();
79
80
            while ($process->isRunning()) {
81
                $this->gatherOutput([$process], $callback);
82
                $this->output->write(spinner(str_pad("connect {$host->tag()}", intval(getenv('COLUMNS')) - 1)));
83
                usleep(1000);
84
            }
85
        }
86
87
        // Clear spinner.
88
        $this->output->write(str_repeat(' ', intval(getenv('COLUMNS')) - 1) . "\r");
89
    }
90
91
    /**
92
     * @param Task[] $tasks
93
     * @param Host[] $hosts
94
     */
95
    public function run(array $tasks, array $hosts): int
96
    {
97
        $this->persistHosts($hosts);
98
        $this->connect($hosts);
99
100
        $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...
101
        $limit = (int)$this->input->getOption('limit') ?: count($hosts);
102
103
        foreach ($tasks as $task) {
104
            $this->messenger->startTask($task);
105
106
            if ($limit === 1 || count($hosts) === 1) {
107
                foreach ($hosts as $host) {
108
                    $host->getConfig()->getCollection()->load();
109
                    $task->run(new Context($host, $this->input, $this->output));
110
                    $host->getConfig()->getCollection()->flush();
111
                }
112
            } else {
113
                foreach (array_chunk($hosts, $limit) as $chunk) {
114
                    $exitCode = $this->runTask($chunk, $task);
115
                    if ($exitCode !== 0) {
116
                        return $exitCode;
117
                    }
118
                }
119
            }
120
121
            $this->messenger->endTask($task);
122
        }
123
124
        return 0;
125
    }
126
127
    private function runTask(array $hosts, Task $task): int
128
    {
129
        $processes = [];
130
        foreach ($hosts as $host) {
131
            if ($task->shouldBePerformed($host)) {
132
                $processes[] = $this->getProcess($host, $task);
133
                if ($task->isOnce()) {
134
                    $task->setHasRun();
135
                }
136
            }
137
        }
138
139 View Code Duplication
        $callback = function (string $output) {
140
            $output = preg_replace('/\n$/', '', $output);
141
            if (strlen($output) !== 0) {
142
                $this->output->writeln($output);
143
            }
144
        };
145
146
        $this->startProcesses($processes);
147
148
        while ($this->areRunning($processes)) {
149
            $this->gatherOutput($processes, $callback);
150
            $this->output->write(spinner());
151
            usleep(1000);
152
        }
153
154
        // Clear spinner.
155
        $this->output->write("    \r");
156
157
        $this->gatherOutput($processes, $callback);
158
159
        return $this->gatherExitCodes($processes);
160
    }
161
162
    protected function getProcess(Host $host, Task $task): Process
163
    {
164
        $dep = PHP_BINARY . ' ' . DEPLOYER_BIN;
165
        $configFile = $host->get('worker-config');
166
        $decorated = $this->output->isDecorated() ? '--decorated' : '';
167
        $command = "$dep worker $task {$host->alias()} $configFile {$this->input} $decorated";
168
169
        if ($this->output->isDebug()) {
170
            $this->output->writeln("[{$host->tag()}] $command");
171
        }
172
173
        return Process::fromShellCommandline($command);
174
    }
175
176
    /**
177
     * Start all of the processes.
178
     *
179
     * @param Process[] $processes
180
     * @return void
181
     */
182
    protected function startProcesses(array $processes)
183
    {
184
        foreach ($processes as $process) {
185
            $process->start();
186
        }
187
    }
188
189
    /**
190
     * Determine if any of the processes are running.
191
     *
192
     * @param Process[] $processes
193
     * @return bool
194
     */
195
    protected function areRunning(array $processes): bool
196
    {
197
        foreach ($processes as $process) {
198
            if ($process->isRunning()) {
199
                return true;
200
            }
201
        }
202
203
        return false;
204
    }
205
206
    /**
207
     * Gather the output from all of the processes.
208
     *
209
     * @param Process[] $processes
210
     * @param callable $callback
211
     * @return void
212
     */
213
    protected function gatherOutput(array $processes, callable $callback)
214
    {
215
        foreach ($processes as $process) {
216
            $output = $process->getIncrementalOutput();
217
            if (strlen($output) !== 0) {
218
                $callback($output);
219
            }
220
221
            $errorOutput = $process->getIncrementalErrorOutput();
222
            if (strlen($errorOutput) !== 0) {
223
                $callback($errorOutput);
224
            }
225
        }
226
    }
227
228
    /**
229
     * Gather the cumulative exit code for the processes.
230
     */
231
    protected function gatherExitCodes(array $processes): int
232
    {
233
        foreach ($processes as $process) {
234
            if ($process->getExitCode() > 0) {
235
                return $process->getExitCode();
236
            }
237
        }
238
239
        return 0;
240
    }
241
242
    /**
243
     * @param Host[] $hosts
244
     */
245
    private function persistHosts(array $hosts)
246
    {
247
        foreach ($hosts as $host) {
248
            Context::push(new Context($host, $this->input, $this->output));
249
250
            $values = $host->getConfig()->persist();
251
            $workerConfig = sys_get_temp_dir() . '/' . uniqid('deployer-') . '-' . $host->alias() . '.dep';
252
            $values['worker-config'] = $workerConfig;
253
254
            $persistentCollection = new PersistentCollection($workerConfig, $values);
255
            $persistentCollection->flush();
256
            $host->getConfig()->setCollection($persistentCollection);
257
258
            Context::pop();
259
        }
260
    }
261
}
262