fix(new-resource): pass server ids in the resource wizard (#12327)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-26 10:14:45 +01:00
committed by GitHub
co-authored by Claude Opus 5.5
parent eeca882b82
commit 88e67cbf42
3 changed files with 157 additions and 11 deletions
+23 -10
View File
@@ -28,9 +28,9 @@ class Select extends Component
public bool $onlyBuildServerAvailable = false;
public ?Collection $standaloneDockers;
public ?Collection $standaloneDockers = null;
public ?Collection $swarmDockers;
public ?Collection $swarmDockers = null;
public array $parameters;
@@ -79,11 +79,14 @@ class Select extends Component
$queryDestination = request()->query('destination');
if ($queryType === 'postgresql' && $queryServerId !== null && $queryDestination) {
$this->type = $queryType;
$this->server_id = $queryServerId;
$this->destination_uuid = $queryDestination;
$this->server = Server::ownedByCurrentTeam()->find($queryServerId);
$this->current_step = 'select-postgresql-type';
$server = Server::isUsable()->whereKey($queryServerId)->first();
if ($server && $this->findDestination($server, $queryDestination)) {
$this->type = $queryType;
$this->server_id = $server->id;
$this->destination_uuid = $queryDestination;
$this->server = $server;
$this->current_step = 'select-postgresql-type';
}
}
} catch (\Exception $e) {
return handleError($e, $this);
@@ -433,20 +436,23 @@ class Select extends Component
if (count($this->servers) === 1 && $this->buildServers?->isEmpty()) {
$server = $this->servers->first();
if ($server instanceof Server) {
$this->setServer($server);
$this->setServer($server->id);
}
}
if (! is_null($this->server)) {
$foundServer = $this->servers->where('id', $this->server->id)->first();
if ($foundServer) {
return $this->setServer($foundServer);
return $this->setServer($foundServer->id);
}
}
$this->current_step = 'servers';
}
public function setServer(Server $server)
public function setServer(int $serverId)
{
$server = $this->servers?->firstWhere('id', $serverId);
abort_unless($server instanceof Server, 404);
$this->server_id = $server->id;
$this->server = $server;
$this->standaloneDockers = $server->standaloneDockers;
@@ -465,11 +471,18 @@ class Select extends Component
public function setDestination(string $destination_uuid)
{
abort_unless($this->server && $this->findDestination($this->server, $destination_uuid), 404);
$this->destination_uuid = $destination_uuid;
return $this->whatToDoNext();
}
private function findDestination(Server $server, string $destinationUuid): ?object
{
return $server->standaloneDockers->concat($server->swarmDockers)->firstWhere('uuid', $destinationUuid);
}
public function setPostgresqlType(string $type)
{
$this->postgresql_type = $type;
@@ -648,7 +648,7 @@
@endif
<div class="divide-y divide-neutral-200 dark:divide-white/[0.07]">
@forelse($servers as $server)
<button type="button" wire:click="setServer({{ $server }})"
<button type="button" wire:click="setServer({{ $server->id }})"
class="group flex min-h-14 w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-neutral-50 dark:hover:bg-white/[0.025]">
<span
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.035] dark:text-fg-dim">
@@ -0,0 +1,133 @@
<?php
use App\Livewire\Project\New\Select;
use App\Models\Environment;
use App\Models\InstanceSettings;
use App\Models\Project;
use App\Models\Server;
use App\Models\StandaloneDocker;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Routing\Events\RouteMatched;
use Illuminate\Support\Facades\Event;
use Livewire\Livewire;
use Symfony\Component\HttpKernel\Exception\HttpException;
uses(RefreshDatabase::class);
function createUsableSelectServer(Team $team): Server
{
$server = Server::factory()->create(['team_id' => $team->id]);
$server->settings()->update([
'is_reachable' => true,
'is_usable' => true,
'is_build_server' => false,
'is_swarm_worker' => false,
'force_disabled' => false,
]);
return $server->refresh();
}
beforeEach(function () {
Server::flushIdentityMap();
InstanceSettings::forceCreate(['id' => 0]);
$this->team = Team::factory()->create();
$this->user = User::factory()->create();
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
$this->actingAs($this->user);
session(['currentTeam' => $this->team]);
$this->server = createUsableSelectServer($this->team);
$this->defaultDestination = StandaloneDocker::query()->where('server_id', $this->server->id)->firstOrFail();
$this->secondDestination = StandaloneDocker::factory()->create([
'server_id' => $this->server->id,
'network' => 'second-network',
]);
$this->otherTeam = Team::factory()->create();
$this->otherServer = createUsableSelectServer($this->otherTeam);
$this->otherDestination = StandaloneDocker::query()->where('server_id', $this->otherServer->id)->firstOrFail();
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
$parameters = [
'project_uuid' => $this->project->uuid,
'environment_uuid' => $this->environment->uuid,
];
Event::listen(RouteMatched::class, function (RouteMatched $event) use ($parameters): void {
foreach ($parameters as $name => $value) {
$event->route->setParameter($name, $value);
}
});
});
afterEach(function () {
Server::flushIdentityMap();
});
test('selecting a server that is not in the server list returns not found and loads nothing', function () {
$component = Livewire::test(Select::class)->call('loadServers');
$select = $component->instance();
expect(fn () => $select->setServer($this->otherServer->id))
->toThrow(fn (HttpException $exception) => expect($exception->getStatusCode())->toBe(404))
->and($select->server)->toBeNull()
->and($select->standaloneDockers)->toBeNull()
->and($select->swarmDockers)->toBeNull()
->and($select->current_step)->toBe('type');
$component->call('setServer', $this->otherServer->id)->assertNotFound();
});
test('selecting a listed server shows its destinations', function () {
$component = Livewire::test(Select::class)
->call('loadServers')
->call('setServer', $this->server->id)
->assertOk()
->assertSet('server_id', (string) $this->server->id)
->assertSet('current_step', 'destinations');
expect($component->get('server')->id)->toBe($this->server->id)
->and($component->get('standaloneDockers')->pluck('uuid')->all())
->toEqualCanonicalizing([$this->defaultDestination->uuid, $this->secondDestination->uuid]);
});
test('selecting a destination of the selected server continues to the create page', function () {
Livewire::test(Select::class)
->call('loadServers')
->set('type', 'dockerfile')
->call('setServer', $this->server->id)
->call('setDestination', $this->secondDestination->uuid)
->assertRedirect(route('project.resource.create', [
'project_uuid' => $this->project->uuid,
'environment_uuid' => $this->environment->uuid,
'type' => 'dockerfile',
'destination' => $this->secondDestination->uuid,
'server_id' => $this->server->id,
]));
});
test('selecting a destination that is not on the selected server returns not found', function () {
Livewire::test(Select::class)
->call('loadServers')
->set('type', 'dockerfile')
->call('setServer', $this->server->id)
->call('setDestination', $this->otherDestination->uuid)
->assertNotFound()
->assertNoRedirect();
});
test('the postgresql shortcut ignores a server that is not in the server list', function () {
Livewire::withQueryParams([
'type' => 'postgresql',
'server_id' => $this->otherServer->id,
'destination' => $this->otherDestination->uuid,
])
->test(Select::class)
->assertSet('server', null)
->assertSet('current_step', 'type');
});