fix(dns): skip auto DNS jobs when server IP is invalid

ConfigureDnsRecordJob requires a string content value. Guard
configureDnsAfterDomainAdd with the same blank and FILTER_VALIDATE_IP
checks used by createManagedDnsRecord so a missing or hostname-only
server address cannot TypeError after the domain is saved.
This commit is contained in:
Andras Bacsai
2026-09-09 13:07:55 +02:00
parent 25e61deefd
commit 27bb601e66
2 changed files with 52 additions and 0 deletions
@@ -83,6 +83,9 @@ trait InteractsWithDnsProviders
if ($this->dnsProviderProposals === []) {
return false;
}
if (blank($this->serverIp) || filter_var($this->serverIp, FILTER_VALIDATE_IP) === false) {
return false;
}
$this->markDnsPending($hostnames);
$proposalsByHostname = collect($this->dnsProviderProposals)->groupBy('hostname');
+49
View File
@@ -1,13 +1,16 @@
<?php
use App\Jobs\CheckDomainDnsJob;
use App\Jobs\ConfigureDnsRecordJob;
use App\Livewire\Project\Application\Domains;
use App\Livewire\Project\Application\PreviewDomains;
use App\Livewire\Project\Application\Previews;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\DnsProviderZone;
use App\Models\Environment;
use App\Models\InstanceSettings;
use App\Models\IntegrationToken;
use App\Models\Project;
use App\Models\Server;
use App\Models\StandaloneDocker;
@@ -821,6 +824,52 @@ it('adds a domain to the application', function () {
->toBe(['https://app.example.com', 'https://www.app.example.com']);
});
it('dispatches configure dns jobs when a matching automatic zone and valid server ip exist', function () {
Queue::fake();
$token = IntegrationToken::factory()->for($this->team)->create([
'provider' => 'cloudflare',
'capabilities' => ['dns'],
]);
DnsProviderZone::factory()->for($token)->create(['name' => 'example.com']);
Livewire::test(Domains::class, ['application' => $this->application->fresh()])
->set('newDomain', 'https://app.example.com')
->call('addDomain')
->assertHasNoErrors()
->assertDispatched('success', 'Domain added.');
Queue::assertPushed(ConfigureDnsRecordJob::class, 2);
Queue::assertPushed(ConfigureDnsRecordJob::class, fn (ConfigureDnsRecordJob $job): bool => $job->hostname === 'app.example.com'
&& $job->content === '203.0.113.10'
&& $job->teamId === $this->team->id);
Queue::assertPushed(ConfigureDnsRecordJob::class, fn (ConfigureDnsRecordJob $job): bool => $job->hostname === 'www.app.example.com'
&& $job->content === '203.0.113.10');
});
it('does not dispatch configure dns jobs when the server ip is missing or invalid', function () {
Queue::fake();
$this->server->update(['ip' => 'not-an-ip']);
$token = IntegrationToken::factory()->for($this->team)->create([
'provider' => 'cloudflare',
'capabilities' => ['dns'],
]);
DnsProviderZone::factory()->for($token)->create(['name' => 'example.com']);
Livewire::test(Domains::class, ['application' => $this->application->fresh()])
->set('newDomain', 'https://app.example.com')
->call('addDomain')
->assertHasNoErrors()
->assertNotDispatched('error');
expect(explode(',', (string) $this->application->fresh()->fqdn))
->toContain('https://app.example.com');
Queue::assertNotPushed(ConfigureDnsRecordJob::class);
});
it('composes the complete port on the server without duplicating an existing www domain', function () {
$this->application->update(['fqdn' => 'https://www.example.com:3000']);