fix: preserve shell negation in sudo commands
This commit is contained in:
parent
778a698553
commit
4766a662fe
2 changed files with 53 additions and 2 deletions
|
|
@ -59,13 +59,18 @@ function parseCommandsByLineForSudo(Collection $commands, Server $server): array
|
|||
return $line;
|
||||
}
|
||||
|
||||
// Negation belongs to the shell, before the elevated command.
|
||||
if (preg_match('/^\s*!\s+/', $line)) {
|
||||
return preg_replace('/^(\s*(?:!\s+)+)/', '$1sudo ', $line);
|
||||
}
|
||||
|
||||
// Check all keywords with word boundary matching
|
||||
// Match keyword followed by space, semicolon, or end of line
|
||||
foreach ($bashKeywords as $keyword) {
|
||||
if (preg_match('/^'.preg_quote($keyword, '/').'(\s|;|$)/', $trimmedLine)) {
|
||||
// Special handling for 'if' - insert sudo after 'if '
|
||||
// Keep any shell negation before sudo in the condition.
|
||||
if ($keyword === 'if') {
|
||||
return preg_replace('/^(\s*)if\s+/', '$1if sudo ', $line);
|
||||
return preg_replace('/^(\s*if\s+(?:!\s+)*)/', '$1sudo ', $line);
|
||||
}
|
||||
|
||||
return $line;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Server;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
beforeEach(function () {
|
||||
// Create a mock server with non-root user
|
||||
|
|
@ -184,6 +185,50 @@
|
|||
expect($result[0])->toBe('if sudo command -v docker');
|
||||
});
|
||||
|
||||
test('preserves shell negation before sudo', function (string $command, string $expected) {
|
||||
expect(parseCommandsByLineForSudo(collect([$command]), $this->server))->toBe([$expected]);
|
||||
})->with([
|
||||
'negated condition' => ['if ! docker inspect coolify-proxy; then', 'if ! sudo docker inspect coolify-proxy; then'],
|
||||
'indented condition' => ["\tif ! docker inspect coolify-proxy; then", "\tif ! sudo docker inspect coolify-proxy; then"],
|
||||
'negated pipeline' => [
|
||||
' if ! docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then',
|
||||
' if ! sudo docker ps -a --format "{{.Names}}" | sudo grep -q "^coolify-proxy$"; then',
|
||||
],
|
||||
'standalone negation' => ['! docker inspect coolify-proxy', '! sudo docker inspect coolify-proxy'],
|
||||
'repeated negation' => ['if ! ! docker inspect coolify-proxy; then', 'if ! ! sudo docker inspect coolify-proxy; then'],
|
||||
'literal exclamation argument' => ['echo "! docker"', 'echo "! docker"'],
|
||||
]);
|
||||
|
||||
test('proxy removal loop exits only once the container is absent', function (string $containers, string $expected) {
|
||||
$commands = collect([
|
||||
'for i in {1..15}; do',
|
||||
' if ! docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then',
|
||||
' echo "Container removed successfully."',
|
||||
' break',
|
||||
' fi',
|
||||
' echo "Waiting for container to be removed... ($i/15)"',
|
||||
'done',
|
||||
]);
|
||||
$script = <<<'BASH'
|
||||
sudo() { "$@"; }
|
||||
docker() { printf '%s\n' "$CONTAINERS"; }
|
||||
BASH;
|
||||
$script .= "\n".implode("\n", parseCommandsByLineForSudo($commands, $this->server));
|
||||
$process = new Process(['bash', '-c', $script], env: ['CONTAINERS' => $containers]);
|
||||
$process->run();
|
||||
|
||||
expect($process->isSuccessful())->toBeTrue()
|
||||
->and($process->getErrorOutput())->toBe('')
|
||||
->and($process->getOutput())->toBe($expected);
|
||||
})->with([
|
||||
'removed' => ['', "Container removed successfully.\n"],
|
||||
'other containers remain' => ['another-container', "Container removed successfully.\n"],
|
||||
'still present' => ['coolify-proxy', implode('', array_map(
|
||||
fn (int $attempt): string => "Waiting for container to be removed... ($attempt/15)\n",
|
||||
range(1, 15),
|
||||
))],
|
||||
]);
|
||||
|
||||
test('skips sudo for fi statements', function () {
|
||||
$commands = collect([
|
||||
'fi',
|
||||
|
|
@ -457,6 +502,7 @@
|
|||
|
||||
// Verify other control structures remain correct
|
||||
expect($result[0])->toStartWith('if sudo docker ps');
|
||||
expect($result[6])->toBe(' if ! sudo docker ps -a --format "{{.Names}}" | sudo grep -q "^coolify-proxy$"; then');
|
||||
expect($result[8])->toBe(' fi');
|
||||
expect($result[13])->toBe('fi');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue