Skip to content

Commit

Permalink
Better rendering of run errors
Browse files Browse the repository at this point in the history
  • Loading branch information
lyrixx committed Nov 14, 2024
1 parent 2d5a474 commit 4adb208
Show file tree
Hide file tree
Showing 32 changed files with 114 additions and 127 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Not released yet

### Features

* Better rendering of run errors

### Internal

* Rework the releasing
Expand Down
2 changes: 1 addition & 1 deletion examples/run.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function exception(): void
output()->writeln('Re-run with -v, -vv, -vvv for different output.');
}

run('echo foo; echo bar>&2; exit 1', context: context()->withPty(false)->withQuiet());
run('echo $foo; echo ' . str_repeat('x', 1000) . 'bar>&2; exit 1', context: context()->withPty(false)->withQuiet()->withEnvironment(['foo' => 'bar']));
}

#[AsTask(description: 'Run a sub-process and display information about it, with ProcessHelper')]
Expand Down
15 changes: 15 additions & 0 deletions src/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Castor\Container;
use Castor\Exception\ProblemException;
use Castor\Kernel;
use Castor\Runner\ProcessRunner;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
Expand All @@ -14,6 +15,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Process\Exception\ProcessFailedException;

/** @internal */
class Application extends SymfonyApplication
Expand All @@ -28,6 +30,8 @@ public function __construct(
private readonly Kernel $kernel,
#[Autowire(lazy: true)]
private readonly SymfonyStyle $io,
#[Autowire(lazy: true)]
private readonly ProcessRunner $processRunner,
) {
parent::__construct(static::NAME, static::VERSION);
}
Expand Down Expand Up @@ -68,6 +72,17 @@ public function renderThrowable(\Throwable $e, OutputInterface $output): void

return;
}

if ($e instanceof ProcessFailedException) {
$process = $e->getProcess();
$this->io->error('The following process did not finish successfully: (exit code ' . $process->getExitCode() . ')');

$runnable = $this->processRunner->buildRunnableCommand($process);
$this->io->writeln("<fg=yellow>{$runnable}</>");
$this->io->newLine();

return;
}
}

parent::renderThrowable($e, $output);
Expand Down
23 changes: 10 additions & 13 deletions src/Monolog/Processor/ProcessProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@

namespace Castor\Monolog\Processor;

use Castor\Runner\ProcessRunner;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Process\Process;

/** @internal */
class ProcessProcessor implements ProcessorInterface
final class ProcessProcessor implements ProcessorInterface
{
public function __construct(
#[Autowire(lazy: true)]
private readonly ProcessRunner $processRunner,
) {
}

public function __invoke(LogRecord $record): LogRecord
{
foreach ($record->context as $key => $value) {
Expand All @@ -30,21 +38,10 @@ public function __invoke(LogRecord $record): LogRecord
*/
private function formatProcess(Process $process): array
{
$runnable = $process->getCommandLine();

foreach ($process->getEnv() as $key => $value) {
if ('argv' === $key || 'argc' === $key) {
continue;
}
$runnable = \sprintf('%s=%s %s ', $key, escapeshellarg($value), $runnable);
}

$runnable = rtrim($runnable, ' ');

return [
'cwd' => $process->getWorkingDirectory(),
'env' => $process->getEnv(),
'runnable' => $runnable,
'runnable' => $this->processRunner->buildRunnableCommand($process),
];
}
}
23 changes: 17 additions & 6 deletions src/Runner/ProcessRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Symfony\Component\Process\Process;

use function Castor\context;
use function Symfony\Component\String\u;

/** @internal */
class ProcessRunner
Expand Down Expand Up @@ -156,7 +157,7 @@ public function run(

$this->eventDispatcher->dispatch(new Event\ProcessCreatedEvent($process));

$this->logger->notice(\sprintf('Running command: "%s".', $process->getCommandLine()), [
$this->logger->notice(\sprintf('Running command: "%s".', u($process->getCommandLine())->truncate(40, '...')), [
'process' => $process,
]);

Expand Down Expand Up @@ -213,11 +214,7 @@ public function run(
}

if (!$context->allowFailure) {
if ($context->verbosityLevel->isVerbose()) {
throw new ProcessFailedException($process);
}

throw new \RuntimeException("The command \"{$process->getCommandLine()}\" failed.");
throw new ProcessFailedException($process);
}

return $process;
Expand Down Expand Up @@ -291,4 +288,18 @@ public function exitCode(

return $process->getExitCode() ?? 0;
}

public function buildRunnableCommand(Process $process): string
{
$runnable = $process->getCommandLine();

foreach ($process->getEnv() as $key => $value) {
if ('argv' === $key || 'argc' === $key) {
continue;
}
$runnable = \sprintf('%s=%s %s ', $key, escapeshellarg($value), $runnable);
}

return rtrim($runnable, ' ');
}
}
8 changes: 0 additions & 8 deletions tests/Generated/FailureFailureTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
bash: line 1: i_do_not_exist: command not found

In failure.php line XXXX:

The command "bash -c i_do_not_exist" failed.


failure:failure

4 changes: 4 additions & 0 deletions tests/Generated/FailureFailureTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[ERROR] The following process did not finish successfully: (exit code 127)

bash -c i_do_not_exist

2 changes: 1 addition & 1 deletion tests/Generated/FailureVerboseArgumentsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public function test(): void
}

$this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput());
$this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput());
$this->assertSame('', $process->getErrorOutput());
}
}
7 changes: 0 additions & 7 deletions tests/Generated/FailureVerboseArgumentsTest.php.err.txt

This file was deleted.

7 changes: 6 additions & 1 deletion tests/Generated/FailureVerboseArgumentsTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
bash: line 1: i_do_not_exist: command not found

Do you want to retry the command with verbose arguments? (yes/no) [no]:
>
>

[ERROR] The following process did not finish successfully: (exit code 127)

bash -c i_do_not_exist

2 changes: 1 addition & 1 deletion tests/Generated/FailureVerboseArgumentsTrueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public function test(): void
}

$this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput());
$this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput());
$this->assertSame('', $process->getErrorOutput());
}
}
19 changes: 0 additions & 19 deletions tests/Generated/FailureVerboseArgumentsTrueTest.php.err.txt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ bash: line 1: i_do_not_exist: command not found
Do you want to retry the command with verbose arguments? (yes/no) [no]:
>
-x: line 1: i_do_not_exist: command not found
[ERROR] The following process did not finish successfully: (exit code 127)

bash -c i_do_not_exist -x -e

8 changes: 0 additions & 8 deletions tests/Generated/ParallelExceptionTest.php.err.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ In parallel.php line XXXX:
parallel:exception


In parallel.php line XXXX:

The command "exit 1" failed.


parallel:exception


In parallel.php line XXXX:

One or more exceptions were thrown in parallel.
Expand Down
4 changes: 4 additions & 0 deletions tests/Generated/ParallelExceptionTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
[ERROR] The following process did not finish successfully: (exit code 1)

exit 1

I am executed
2 changes: 1 addition & 1 deletion tests/Generated/RunExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public function test(): void
}

$this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput());
$this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput());
$this->assertSame('', $process->getErrorOutput());
}
}
7 changes: 0 additions & 7 deletions tests/Generated/RunExceptionTest.php.err.txt

This file was deleted.

5 changes: 5 additions & 0 deletions tests/Generated/RunExceptionTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
Re-run with -v, -vv, -vvv for different output.

[ERROR] The following process did not finish successfully: (exit code 1)

foo='bar' echo $foo; echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbar>&2; exit 1

8 changes: 5 additions & 3 deletions tests/Generated/RunExceptionVerboseTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
In ProcessRunner.php line XXXX:

[Symfony\Component\Process\Exception\ProcessFailedException]
The command "echo foo; echo bar>&2; exit 1" failed.
The command "echo $foo; echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbar>&2; exit 1" failed.

Exit Code: 1(General error)

Working directory: ...

Output:
================
foo
bar


Error Output:
================
bar
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxbar


Exception trace:
Expand Down
2 changes: 1 addition & 1 deletion tests/Generated/RunExceptionVerboseTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
hh:mm:ss NOTICE [castor] Running command: "echo foo; echo bar>&2; exit 1". ["process" => ["cwd" => "...","env" => [],"runnable" => "echo foo; echo bar>&2; exit 1"]]
hh:mm:ss NOTICE [castor] Running command: "echo $foo; echo xxxxxxxxxxxxxxxxxxxxx...". ["process" => ["cwd" => "...","env" => ["foo" => "bar"],"runnable" => "foo='bar' echo $foo; echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbar>&2; exit 1"]]
hh:mm:ss NOTICE [castor] Command finished with an error (exit code=1).
8 changes: 0 additions & 8 deletions tests/Generated/SshDownloadTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
ssh: Could not resolve hostname server-1.example.com: Name or service not known

In ssh.php line XXXX:

The command "scp -r [email protected]:/tmp/test.html /var/www/index.html" failed.


ssh:download

4 changes: 4 additions & 0 deletions tests/Generated/SshDownloadTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[ERROR] The following process did not finish successfully: (exit code 1)

scp -r [email protected]:/tmp/test.html /var/www/index.html

10 changes: 0 additions & 10 deletions tests/Generated/SshLsTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
ssh: Could not resolve hostname server-1.example.com: Name or service not known

In ssh.php line XXXX:

The command "ssh -p 2222 [email protected] 'bash -se' << \EOF-SPATIE-SSH
cd /var/www && ls -alh
EOF-SPATIE-SSH" failed.


ssh:ls

6 changes: 6 additions & 0 deletions tests/Generated/SshLsTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[ERROR] The following process did not finish successfully: (exit code 255)

ssh -p 2222 [email protected] 'bash -se' << \EOF-SPATIE-SSH
cd /var/www && ls -alh
EOF-SPATIE-SSH

2 changes: 1 addition & 1 deletion tests/Generated/SshRealTimeOutputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public function test(): void
}

$this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput());
$this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput());
$this->assertSame('', $process->getErrorOutput());
}
}
9 changes: 0 additions & 9 deletions tests/Generated/SshRealTimeOutputTest.php.err.txt

This file was deleted.

6 changes: 6 additions & 0 deletions tests/Generated/SshRealTimeOutputTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
REAL TIME OUTPUT> ssh: Could not resolve hostname server-1.example.com: Name or service not known

[ERROR] The following process did not finish successfully: (exit code 255)

ssh [email protected] 'bash -se' << \EOF-SPATIE-SSH
ls -alh
EOF-SPATIE-SSH

8 changes: 0 additions & 8 deletions tests/Generated/SshUploadTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
ssh: Could not resolve hostname server-1.example.com: Name or service not known

In ssh.php line XXXX:

The command "scp -r .../examples/ssh.php [email protected]:/var/www/index.html" failed.


ssh:upload

4 changes: 4 additions & 0 deletions tests/Generated/SshUploadTest.php.output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[ERROR] The following process did not finish successfully: (exit code 1)

scp -r .../examples/ssh.php [email protected]:/var/www/index.html

10 changes: 0 additions & 10 deletions tests/Generated/SshWhoamiTest.php.err.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
ssh: Could not resolve hostname server-1.example.com: Name or service not known

In ssh.php line XXXX:

The command "ssh -p 2222 server-1.example.com 'bash -se' << \EOF-SPATIE-SSH
cd /var/www && whoami
EOF-SPATIE-SSH" failed.


ssh:whoami

Loading

0 comments on commit 4adb208

Please sign in to comment.