diff --git a/app/Livewire/Project/Application/PreviewDomains.php b/app/Livewire/Project/Application/PreviewDomains.php index 5f454d91ba..ee635f16b6 100644 --- a/app/Livewire/Project/Application/PreviewDomains.php +++ b/app/Livewire/Project/Application/PreviewDomains.php @@ -339,17 +339,18 @@ class PreviewDomains extends Component } $row = $this->domainRows[$index]; + $statusKey = $this->statusKey($row['url'], $row['service']); $checkId = new_public_id(); $this->domainRows[$index]['dns_status'] = 'checking'; $this->domainRows[$index]['dns_message'] = 'Checking DNS...'; $this->domainRows[$index]['check_id'] = $checkId; - $this->persistDnsStatuses(); + $this->persistDnsStatuses([$statusKey]); try { $server = $this->preview->application->destination?->server; CheckDomainDnsJob::dispatch( $this->preview, - $this->statusKey($row['url'], $row['service']), + $statusKey, $row['url'], $server, $server ? serverDnsTargetIp($server) ?? $server->ip : null, @@ -494,7 +495,11 @@ class PreviewDomains extends Component return true; } - private function persistDnsStatuses(): void + /** + * @param array $startingCheckKeys Status keys whose check is being started by this call. + * They are allowed to replace a stored completed result. + */ + private function persistDnsStatuses(array $startingCheckKeys = []): void { $statuses = []; foreach ($this->domainRows as $row) { @@ -505,13 +510,13 @@ class PreviewDomains extends Component ]; } - DB::transaction(function () use (&$statuses): void { + DB::transaction(function () use (&$statuses, $startingCheckKeys): void { $preview = ApplicationPreview::query()->lockForUpdate()->findOrFail($this->preview->id); $storedStatuses = $preview->domain_dns_statuses ?? []; foreach ($statuses as $key => $status) { $storedStatus = $storedStatuses[$key] ?? null; - if (! is_array($storedStatus)) { + if (! is_array($storedStatus) || in_array($key, $startingCheckKeys, true)) { continue; } diff --git a/tests/Feature/ApplicationDomainsTest.php b/tests/Feature/ApplicationDomainsTest.php index 183073366b..4bc05e018a 100644 --- a/tests/Feature/ApplicationDomainsTest.php +++ b/tests/Feature/ApplicationDomainsTest.php @@ -3598,3 +3598,59 @@ it('does not overwrite a completed dns result with stale checking state', functi 'check_id' => 'completed-check', ]); }); + +it('replaces a completed dns result when the domain is checked again', function () { + $settings = InstanceSettings::get(); + $settings->is_dns_validation_enabled = true; + $settings->save(); + + $url = 'https://this-domain-should-not-resolve-for-coolify-tests.invalid'; + $checkedAt = now()->subDays(12)->toIso8601String(); + $this->application->update([ + 'fqdn' => $url, + 'domain_dns_statuses' => [ + $url => [ + 'status' => 'ok', + 'message' => 'DNS looks correct.', + 'expected_ip' => '203.0.113.10', + 'checked_at' => $checkedAt, + ], + ], + ]); + + Livewire::test(Domains::class, ['application' => $this->application->fresh()]) + ->call('checkDomainDns', 0) + ->call('pollDnsChecks') + ->assertSet('domainRows.0.dns_status', 'failed'); + + expect($this->application->fresh()->domain_dns_statuses[$url]) + ->status->toBe('failed') + ->checked_at->not->toBe($checkedAt); +}); + +it('restarts a preview dns check when the domain already has a completed result', function () { + Queue::fake(); + + $url = 'https://preview-recheck.example.com'; + $statusKey = hash('sha256', $url.'|'); + $preview = ApplicationPreview::create([ + 'application_id' => $this->application->id, + 'pull_request_id' => 54, + 'pull_request_html_url' => 'https://github.com/coollabsio/coolify/pull/54', + 'fqdn' => $url, + 'domain_dns_statuses' => [ + $statusKey => [ + 'status' => 'failed', + 'message' => 'Required DNS record type A pointing to 203.0.113.10', + ], + ], + ]); + + Livewire::test(PreviewDomains::class, ['preview' => $preview]) + ->call('checkDomainDns', 0) + ->assertSet('domainRows.0.dns_status', 'checking'); + + expect($preview->fresh()->domain_dns_statuses[$statusKey]['status'])->toBe('checking'); + + Queue::assertPushed(CheckDomainDnsJob::class); +});