mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
A queued deployment whose commit no longer validates (for example one queued before an upgrade) made the job dispatch throw. The row stayed in_progress, blocked every later deployment of the application, and stopped the queue loop. Such a row is now marked failed with a log entry and a failure notification, and the next queued deployment starts. An exception after the new container passed its health check (for example in additional destinations, the next-deployment loop, or notifications) made failed() remove the new container, which could be the only one running. failed() now keeps a healthy new container, and errors in the steps after a status change are logged without flipping a finished deployment to failed.
76 lines
3.5 KiB
PHP
76 lines
3.5 KiB
PHP
<?php
|
|
|
|
use App\Jobs\ApplicationDeploymentJob;
|
|
use App\Models\Application;
|
|
use App\Models\ApplicationDeploymentQueue;
|
|
use App\Models\ApplicationSetting;
|
|
|
|
/**
|
|
* @return array<int, array<int|string, mixed>>
|
|
*/
|
|
function runFailedDeploymentCleanup(bool $consistentContainerName, ?string $customInternalName, int $pullRequestId, bool $newVersionIsHealthy = false): array
|
|
{
|
|
$settings = new ApplicationSetting;
|
|
$settings->setRawAttributes([
|
|
'is_consistent_container_name_enabled' => $consistentContainerName,
|
|
'custom_internal_name' => $customInternalName,
|
|
]);
|
|
|
|
$application = new Application;
|
|
$application->setRawAttributes(['build_pack' => 'dockerfile']);
|
|
$application->setRelation('settings', $settings);
|
|
|
|
$queue = Mockery::mock(ApplicationDeploymentQueue::class);
|
|
$queue->shouldReceive('addLogEntry')->andReturnNull();
|
|
|
|
$job = Mockery::mock(ApplicationDeploymentJob::class)->makePartial();
|
|
$job->shouldAllowMockingProtectedMethods();
|
|
$job->shouldReceive('failDeployment')->andReturnNull();
|
|
|
|
$remoteCommands = [];
|
|
$job->shouldReceive('execute_remote_command')->andReturnUsing(function (...$commands) use (&$remoteCommands) {
|
|
array_push($remoteCommands, ...$commands);
|
|
});
|
|
|
|
$reflection = new ReflectionClass(ApplicationDeploymentJob::class);
|
|
$reflection->getProperty('application_deployment_queue')->setValue($job, $queue);
|
|
$reflection->getProperty('application')->setValue($job, $application);
|
|
$reflection->getProperty('pull_request_id')->setValue($job, $pullRequestId);
|
|
$reflection->getProperty('container_name')->setValue($job, 'new-container-20261001T120000');
|
|
$reflection->getProperty('newVersionIsHealthy')->setValue($job, $newVersionIsHealthy);
|
|
|
|
$job->failed(new RuntimeException('Health check failed'));
|
|
|
|
return $remoteCommands;
|
|
}
|
|
|
|
it('removes the new rolling-update container when only a custom internal name is set', function () {
|
|
$remoteCommands = runFailedDeploymentCleanup(consistentContainerName: false, customInternalName: 'my-api', pullRequestId: 0);
|
|
|
|
expect($remoteCommands)->toHaveCount(1)
|
|
->and($remoteCommands[0][0])->toContain('new-container-20261001T120000');
|
|
});
|
|
|
|
it('removes the new rolling-update container when no custom name is set', function () {
|
|
expect(runFailedDeploymentCleanup(consistentContainerName: false, customInternalName: null, pullRequestId: 0))->toHaveCount(1);
|
|
});
|
|
|
|
it('keeps the running container when consistent container names are enabled', function () {
|
|
expect(runFailedDeploymentCleanup(consistentContainerName: true, customInternalName: 'my-api', pullRequestId: 0))->toBeEmpty();
|
|
});
|
|
|
|
it('keeps the running container for pull request deployments', function () {
|
|
expect(runFailedDeploymentCleanup(consistentContainerName: false, customInternalName: 'my-api', pullRequestId: 12))->toBeEmpty();
|
|
});
|
|
|
|
it('keeps the new container when the deployment fails after the new container became healthy', function () {
|
|
expect(runFailedDeploymentCleanup(consistentContainerName: false, customInternalName: null, pullRequestId: 0, newVersionIsHealthy: true))->toBeEmpty();
|
|
});
|
|
|
|
it('removes the new container when the deployment fails before the new container became healthy', function () {
|
|
$remoteCommands = runFailedDeploymentCleanup(consistentContainerName: false, customInternalName: null, pullRequestId: 0, newVersionIsHealthy: false);
|
|
|
|
expect($remoteCommands)->toHaveCount(1)
|
|
->and($remoteCommands[0][0])->toContain('new-container-20261001T120000');
|
|
});
|