fix(deployments): trim remote command outputs before processing

Normalize saved command output for reliable status and metadata handling, and bump the Coolify version to 4.3.23.
This commit is contained in:
Andras Bacsai
2026-09-18 15:34:50 +02:00
parent 23f24f8425
commit e2e2d4010b
7 changed files with 43 additions and 14 deletions
+7 -6
View File
@@ -671,7 +671,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
[executeInDocker($this->deployment_uuid, "stat -c '%F' {$realPathInGit}"), 'hidden' => true, 'ignore_errors' => true, 'save' => $saveName]
);
if ($this->saved_outputs->has($saveName)) {
$fileStat = $this->saved_outputs->get($saveName);
$fileStat = $this->trimmedSavedOutput($saveName);
if ($fileStat->value() === 'directory' && ! $fileStorage->is_directory) {
$fileStorage->is_directory = true;
$fileStorage->content = null;
@@ -2171,12 +2171,13 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->application_deployment_queue->addLogEntry("Healthcheck logs: {$health_check_logs} | Return code: {$health_check_return_code}");
}
if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') {
$healthCheckStatus = $this->trimmedSavedOutput('health_check')->replace('"', '')->value();
if ($healthCheckStatus === 'healthy') {
$this->newVersionIsHealthy = true;
$this->application->update(['status' => 'running']);
$this->application_deployment_queue->addLogEntry('New container is healthy.');
break;
} elseif (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') {
} elseif ($healthCheckStatus === 'unhealthy') {
$this->newVersionIsHealthy = false;
$this->application_deployment_queue->addLogEntry('New container is unhealthy.', type: 'error');
$this->query_logs();
@@ -2189,7 +2190,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$sleeptime++;
}
}
if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'starting') {
if ($this->trimmedSavedOutput('health_check')->replace('"', '')->value() === 'starting') {
$this->query_logs();
}
}
@@ -2571,7 +2572,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
]
);
if ($this->saved_outputs->get('commit_message')) {
$commit_message = str($this->saved_outputs->get('commit_message'));
$commit_message = $this->trimmedSavedOutput('commit_message');
$this->application_deployment_queue->commit_message = $commit_message->value();
ApplicationDeploymentQueue::whereCommit($this->commit)->whereApplicationId($this->application->id)->update(
['commit_message' => $commit_message->value()]
@@ -2641,7 +2642,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
[executeInDocker($this->deployment_uuid, "nixpacks detect {$this->workdir}"), 'save' => 'nixpacks_type', 'hidden' => true],
);
if ($this->saved_outputs->get('nixpacks_type')) {
$this->nixpacks_type = $this->saved_outputs->get('nixpacks_type');
$this->nixpacks_type = $this->trimmedSavedOutput('nixpacks_type')->value();
if (str($this->nixpacks_type)->isEmpty()) {
throw new DeploymentException('Nixpacks failed to detect the application type. Please check the documentation of Nixpacks: https://nixpacks.com/docs/providers');
}
+7 -1
View File
@@ -9,6 +9,7 @@ use App\Models\Server;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Stringable;
trait ExecuteRemoteCommand
{
@@ -247,7 +248,12 @@ trait ExecuteRemoteCommand
return;
}
$this->saved_outputs->put($this->save, str($output));
$this->saved_outputs->put($this->save, str($output)->trim());
}
private function trimmedSavedOutput(string $key): Stringable
{
return str($this->saved_outputs->get($key))->trim();
}
/**
+1 -1
View File
@@ -2,7 +2,7 @@
return [
'coolify' => [
'version' => env('COOLIFY_VERSION') ?: '4.3.22',
'version' => env('COOLIFY_VERSION') ?: '4.3.23',
'helper_version' => '1.0.17',
'realtime_version' => '1.0.19',
'railpack_version' => '0.23.0',
+1 -1
View File
@@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.3.22"
"version": "4.3.23"
},
"nightly": {
"version": "4.4-rc.1"
+24 -2
View File
@@ -23,6 +23,11 @@ function remoteCommandOutputCollector(): object
{
$this->saveCommandOutput($output, $append);
}
public function trimmedOutput(string $key = 'dockerfile'): string
{
return $this->trimmedSavedOutput($key)->value();
}
};
}
@@ -37,11 +42,28 @@ it('preserves whitespace across streamed saved output chunks', function () {
->toBe("FROM alpine\nARG FIRST\nARG SECOND\nRUN true\n");
});
it('replaces saved output without trimming it when append is disabled', function () {
it('trims saved output when append is disabled', function () {
$collector = remoteCommandOutputCollector();
$collector->collectOutput('old');
$collector->collectOutput(" new output\n", append: false);
expect((string) $collector->saved_outputs->get('dockerfile'))->toBe(" new output\n");
expect((string) $collector->saved_outputs->get('dockerfile'))->toBe('new output');
});
it('keeps non-appended command output safe for exact status comparisons', function () {
$collector = remoteCommandOutputCollector();
$collector->collectOutput("\"healthy\"\n", append: false);
expect(str($collector->saved_outputs->get('dockerfile'))->replace('"', '')->value())
->toBe('healthy');
});
it('normalizes streamed scalar output without changing the saved value', function () {
$collector = remoteCommandOutputCollector();
$collector->collectOutput("node\n");
expect($collector->trimmedOutput())->toBe('node')
->and((string) $collector->saved_outputs->get('dockerfile'))->toBe("node\n");
});
+2 -2
View File
@@ -25,8 +25,8 @@ it('publishes v4 branch builds under the commit sha with a traceable internal ve
->toContain('ARG COOLIFY_VERSION')
->toContain('ENV COOLIFY_VERSION=${COOLIFY_VERSION}')
->and($constants)
->toContain("'version' => env('COOLIFY_VERSION') ?: '4.3.22'")
->and($versions['coolify']['v4']['version'])->toBe('4.3.22')
->toContain("'version' => env('COOLIFY_VERSION') ?: '4.3.23'")
->and($versions['coolify']['v4']['version'])->toBe('4.3.23')
->and($versions['coolify']['nightly']['version'])->toBe('4.4-rc.1')
->and($nightlyVersions)->toBe($versions);
});
+1 -1
View File
@@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.3.22"
"version": "4.3.23"
},
"nightly": {
"version": "4.4-rc.1"