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 ( c538d5...8bac07 )
by Anton
02:32
created

src/Component/Ssh/Client.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
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\Component\Ssh;
9
10
use Deployer\Deployer;
11
use Deployer\Exception\RunException;
12
use Deployer\Host\Host;
13
use Deployer\Component\ProcessRunner\Printer;
14
use Deployer\Logger\Logger;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Process\Process;
17
18
class Client
19
{
20
    private $output;
21
    private $pop;
22
    private $logger;
23
24
    public function __construct(OutputInterface $output, Printer $pop, Logger $logger)
25
    {
26
        $this->output = $output;
27
        $this->pop = $pop;
28
        $this->logger = $logger;
29
    }
30
31
    public function run(Host $host, string $command, array $config = [])
32
    {
33
        $hostname = $host->hostname();
0 ignored issues
show
$hostname 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...
34
        $connectionString = $host->getConnectionString();
35
        $defaults = [
36
            'timeout' => $host->get('default_timeout', 300),
37
        ];
38
39
        $config = array_merge($defaults, $config);
40
        $sshArguments = $host->getSshArguments();
41
        if ($host->sshMultiplexing()) {
42
            $sshArguments = $this->initMultiplexing($host);
43
        }
44
45
        $become = '';
46
        if ($host->has('become')) {
47
            $become = sprintf('sudo -H -u %s', $host->get('become'));
48
        }
49
50
        $shellCommand = $host->shell();
51
52
        if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
53
            $ssh = "ssh $sshArguments $connectionString $become \"$shellCommand; printf '[exit_code:%s]' $?;\"";
54
        } else {
55
            $ssh = "ssh $sshArguments $connectionString $become '$shellCommand; printf \"[exit_code:%s]\" $?;'";
56
        }
57
58
        // -vvv for ssh command
59
        if ($this->output->isDebug()) {
60
            $this->pop->writeln(Process::OUT, $host, "$ssh");
61
        }
62
63
        $this->pop->command($host, $command);
64
        $this->logger->log("[{$host->alias()}] run $command");
65
66
        $terminalOutput = $this->pop->callback($host);
67
        $callback = function ($type, $buffer) use ($host, $terminalOutput) {
68
            $this->logger->printBuffer($host, $type, $buffer);
69
            $terminalOutput($type, $buffer);
70
        };
71
72
        $process = $this->createProcess($ssh);
73
        $process
74
            ->setInput(str_replace('%secret%', $config['secret'] ?? '', $command))
75
            ->setTimeout($config['timeout']);
76
77
78
        $process->run($callback);
79
80
        $output = $this->pop->filterOutput($process->getOutput());
81
        $exitCode = $this->parseExitStatus($process);
82
83
        if ($exitCode !== 0) {
84
            throw new RunException(
85
                $host,
86
                $command,
87
                $exitCode,
88
                $output,
89
                $process->getErrorOutput()
90
            );
91
        }
92
93
        return $output;
94
    }
95
96
    private function parseExitStatus(Process $process)
97
    {
98
        $output = $process->getOutput();
99
        preg_match('/\[exit_code:(.*?)\]/', $output, $match);
100
101
        if (!isset($match[1])) {
102
            return -1;
103
        }
104
105
        $exitCode = (int)$match[1];
106
        return $exitCode;
107
    }
108
109
    public function connect(Host $host)
110
    {
111
        if ($host->sshMultiplexing()) {
112
            $this->initMultiplexing($host);
113
        }
114
    }
115
116
    private function initMultiplexing(Host $host)
117
    {
118
        $sshArguments = $host->getSshArguments()->withMultiplexing($host);
119
120
        if (!$this->isMultiplexingInitialized($host, $sshArguments)) {
121
            $connectionString = $host->getConnectionString();
122
            $command = "ssh -N $sshArguments $connectionString";
123
124
            if ($this->output->isDebug()) {
125
                $this->pop->writeln(Process::OUT, $host, '<info>ssh multiplexing initialization</info>');
126
                $this->pop->writeln(Process::OUT, $host, $command);
127
            }
128
129
            $output = $this->exec($command);
130
131
            if ($this->output->isDebug()) {
132
                $this->pop->printBuffer(Process::OUT, $host, $output);
133
            }
134
        }
135
136
        return $sshArguments;
137
    }
138
139
    private function isMultiplexingInitialized(Host $host, Arguments $sshArguments)
140
    {
141
        $command = "ssh -O check $sshArguments echo 2>&1";
142
        if ($this->output->isDebug()) {
143
            $this->pop->printBuffer(Process::OUT, $host, $command);
144
        }
145
146
        $process = $this->createProcess($command);
147
        $process->run();
148
        $output = $process->getOutput();
149
150
        if ($this->output->isDebug()) {
151
            $this->pop->printBuffer(Process::OUT, $host, $output);
152
        }
153
        return (bool)preg_match('/Master running/', $output);
154
    }
155
156
    private function exec($command, &$exitCode = null)
157
    {
158
        $descriptors = [
159
            ['pipe', 'r'],
160
            ['pipe', 'w'],
161
            ['pipe', 'w'],
162
        ];
163
164
        // Don't read from stderr, there is a bug in OpenSSH_7.2p2 (stderr doesn't closed with ControlMaster)
165
166
        $process = proc_open($command, $descriptors, $pipes);
167
        if (is_resource($process)) {
168
            fclose($pipes[0]);
169
            $output = stream_get_contents($pipes[1]);
170
            fclose($pipes[1]);
171
            fclose($pipes[2]);
172
            $exitCode = proc_close($process);
173
        } else {
174
            $output = 'proc_open failure';
175
            $exitCode = 1;
176
        }
177
        return $output;
178
    }
179
180
    private function createProcess($command)
181
    {
182
        if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
183
            return Process::fromShellCommandline($command);
184
        } else {
185
            return new Process($command);
186
        }
187
    }
188
}
189