diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index b518abff7d..e7731e7ae0 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -116,9 +116,15 @@ function queue_application_deployment(Application $application, string $deployme } if ($admission['started']) { - ApplicationDeploymentJob::dispatch( - application_deployment_queue_id: $deployment->id, - ); + try { + ApplicationDeploymentJob::dispatch( + application_deployment_queue_id: $deployment->id, + ); + } catch (Throwable $exception) { + fail_undispatchable_deployment($deployment, $exception); + + throw $exception; + } } return [ diff --git a/tests/Feature/ImmediateDeploymentDispatchFailureTest.php b/tests/Feature/ImmediateDeploymentDispatchFailureTest.php new file mode 100644 index 0000000000..61817a87cf --- /dev/null +++ b/tests/Feature/ImmediateDeploymentDispatchFailureTest.php @@ -0,0 +1,53 @@ + InstanceSettings::firstOrCreate(['id' => 0])); + + $team = Team::factory()->create(); + $server = Server::factory()->create(['team_id' => $team->id]); + $destination = StandaloneDocker::where('server_id', $server->id)->firstOrFail(); + $project = Project::factory()->create(['team_id' => $team->id]); + $environment = $project->environments()->first() + ?? Environment::factory()->create(['project_id' => $project->id]); + $this->application = Application::factory()->create([ + 'environment_id' => $environment->id, + 'destination_id' => $destination->id, + 'destination_type' => $destination->getMorphClass(), + 'docker_registry_image_name' => 'bad name;x', + ]); + + Queue::fake(); + Notification::fake(); +}); + +test('a deployment whose job cannot be dispatched fails and does not block the next deployment', function () { + expect(fn () => queue_application_deployment($this->application, 'prr-undispatchable')) + ->toThrow(DeploymentException::class, 'Docker registry image name contains invalid characters.'); + + $failedDeployment = ApplicationDeploymentQueue::where('deployment_uuid', 'prr-undispatchable')->firstOrFail(); + expect($failedDeployment->status)->toBe('failed') + ->and($failedDeployment->logs)->toContain('Deployment could not be started'); + + $this->application->update(['docker_registry_image_name' => 'ghcr.io/coollabs/app']); + queue_application_deployment($this->application->fresh(), 'prr-next-deployment'); + + expect(ApplicationDeploymentQueue::where('deployment_uuid', 'prr-next-deployment')->value('status'))->toBe('in_progress'); + Queue::assertPushed(ApplicationDeploymentJob::class, 1); +});