From 894eb144ddbebde03f500bfe9c96823bc1753ad1 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 13 Jun 2026 11:48:48 +0300 Subject: [PATCH] Report live reload build failures --- src/Console/ServeCommand.php | 24 +++++++++++++++---- src/Web/DevServer/assets/live-reload.js | 11 +++++++++ src/Web/LiveReload/SiteBuildResult.php | 18 ++++++++++++++ src/Web/LiveReload/SiteBuildRunner.php | 4 ++-- .../Web/LiveReload/SiteBuildRunnerTest.php | 11 +++++---- 5 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 src/Web/LiveReload/SiteBuildResult.php diff --git a/src/Console/ServeCommand.php b/src/Console/ServeCommand.php index 3936861..f1451e2 100644 --- a/src/Console/ServeCommand.php +++ b/src/Console/ServeCommand.php @@ -7,6 +7,7 @@ use YiiPress\Environment; use YiiPress\RuntimePaths; use YiiPress\Web\DevServer\DevHtmlInjector; +use YiiPress\Web\LiveReload\SiteBuildResult; use YiiPress\Web\LiveReload\SiteBuildRunner; use FilesystemIterator; use HttpSoft\Message\ServerRequest; @@ -412,8 +413,21 @@ function (): void { return; } - $this->buildLiveReloadSite(); - $this->broadcastLiveReloadEvent('reload', 'changed', true); + $result = $this->buildLiveReloadSite(); + if ($result === null) { + return; + } + + if ($result->succeeded()) { + $this->broadcastLiveReloadEvent('reload', 'changed', true); + return; + } + + $this->broadcastLiveReloadEvent( + 'build-error', + json_encode(['output' => $result->output], JSON_THROW_ON_ERROR), + true, + ); }); } @@ -461,15 +475,15 @@ private function closeLiveReloadWatcher(): void $this->liveReloadClients = []; } - private function buildLiveReloadSite(): void + private function buildLiveReloadSite(): ?SiteBuildResult { $now = microtime(true); if ($now - $this->lastLiveReloadBuildTime < 1.0) { - return; + return null; } $this->lastLiveReloadBuildTime = $now; - $this->createLiveReloadBuildRunner()->build(); + return $this->createLiveReloadBuildRunner()->build(); } private function finishLiveReloadResponse(ConnectionInterface $connection, string $event, string $data): void diff --git a/src/Web/DevServer/assets/live-reload.js b/src/Web/DevServer/assets/live-reload.js index 76e1ebe..6128b98 100644 --- a/src/Web/DevServer/assets/live-reload.js +++ b/src/Web/DevServer/assets/live-reload.js @@ -19,6 +19,17 @@ } es = new EventSource("/_live-reload"); es.addEventListener("reload", function() { es.close(); location.reload(); }); + es.addEventListener("build-error", function(event) { + es.close(); + try { + var payload = JSON.parse(event.data); + if (payload.output) { + console.error(payload.output); + } + } catch (error) { + console.error(event.data); + } + }); es.addEventListener("ping", function() {}); es.onerror = function() { es.close(); diff --git a/src/Web/LiveReload/SiteBuildResult.php b/src/Web/LiveReload/SiteBuildResult.php new file mode 100644 index 0000000..6e28875 --- /dev/null +++ b/src/Web/LiveReload/SiteBuildResult.php @@ -0,0 +1,18 @@ +exitCode === 0; + } +} diff --git a/src/Web/LiveReload/SiteBuildRunner.php b/src/Web/LiveReload/SiteBuildRunner.php index a4ac76a..b78092d 100644 --- a/src/Web/LiveReload/SiteBuildRunner.php +++ b/src/Web/LiveReload/SiteBuildRunner.php @@ -12,7 +12,7 @@ public function __construct( private string $outputDir, ) {} - public function build(): bool + public function build(): SiteBuildResult { $command = escapeshellarg($this->yiiBinary) . ' build' @@ -22,6 +22,6 @@ public function build(): bool exec($command, $output, $exitCode); - return $exitCode === 0; + return new SiteBuildResult($exitCode, implode("\n", $output)); } } diff --git a/tests/Unit/Web/LiveReload/SiteBuildRunnerTest.php b/tests/Unit/Web/LiveReload/SiteBuildRunnerTest.php index 2eb7cd0..16b4e5c 100644 --- a/tests/Unit/Web/LiveReload/SiteBuildRunnerTest.php +++ b/tests/Unit/Web/LiveReload/SiteBuildRunnerTest.php @@ -52,7 +52,7 @@ public function testBuildUsesIncrementalCommandLine(): void $runner = new SiteBuildRunner($script, $this->tempDir . '/content', $this->tempDir . '/output'); - self::assertTrue($runner->build()); + self::assertTrue($runner->build()->succeeded()); $commandLine = file_get_contents($recordFile); assertSame( @@ -64,15 +64,18 @@ public function testBuildUsesIncrementalCommandLine(): void assertStringNotContainsString('--no-cache', $commandLine); } - public function testBuildReturnsFalseWhenCommandFails(): void + public function testBuildReturnsFailureResultWhenCommandFails(): void { $script = $this->tempDir . '/fail-yii'; - file_put_contents($script, "#!/bin/sh\nexit 1\n"); + file_put_contents($script, "#!/bin/sh\nprintf 'failed build\n'\nexit 1\n"); chmod($script, 0o755); $runner = new SiteBuildRunner($script, $this->tempDir . '/content', $this->tempDir . '/output'); + $result = $runner->build(); - assertFalse($runner->build()); + assertFalse($result->succeeded()); + assertSame(1, $result->exitCode); + assertStringContainsString('failed build', $result->output); } private function removeDir(string $path): void