From 8af0606a32be4b1d22689e9247257729abe800e8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:37:56 +0100 Subject: [PATCH 1/7] docs(readme): add martiinii to small sponsors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de6b80ab95..fb1470585f 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,7 @@ Thank you so much! InterviewPal Decidable Host Havoc +martiinii ...and many more at [GitHub Sponsors](https://github.com/sponsors/coollabsio) From 690331e446f13c1e3865e84069bae72d214e002d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:56:34 +0100 Subject: [PATCH 2/7] docs(readme): remove Context.dev from huge sponsors --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index fb1470585f..82da094800 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,6 @@ Thank you so much! ### Huge Sponsors -* [Context.dev](https://www.context.dev/) - Web scraping API for AI agents * [Ginernet](https://ginernet.com/) - Hosting powerful servers in Spain * [SerpAPI](https://serpapi.com) - Google Search API — Scrape Google and other search engines from our fast, easy, and complete API. * [MVPS](https://www.mvps.net) - Cheap VPS servers at the highest possible quality From 8178fa16b2b4f3a9fc208c8a556f93f4db9a9fd4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:34 +0100 Subject: [PATCH 3/7] fix(ui): use red style for unused key deletion --- resources/views/livewire/security/private-key/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/security/private-key/index.blade.php b/resources/views/livewire/security/private-key/index.blade.php index 70b87a5845..d3c78f42b3 100644 --- a/resources/views/livewire/security/private-key/index.blade.php +++ b/resources/views/livewire/security/private-key/index.blade.php @@ -14,7 +14,7 @@ :confirmWithText="false" :confirmWithPassword="false"> From 759fbe5b3c66c152015cfd7da21276386db08125 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:50:14 +0100 Subject: [PATCH 4/7] feat(deployments): show spinners for in-progress status --- .../views/components/status-badge.blade.php | 22 +++++++++++++++++++ .../dashboard/active-deployments.blade.php | 8 +++---- .../livewire/deployments-indicator.blade.php | 2 +- .../application/deployment/index.blade.php | 6 +++++ .../application/deployment/show.blade.php | 4 ++++ 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/resources/views/components/status-badge.blade.php b/resources/views/components/status-badge.blade.php index a8f49e8bf5..72b58d9666 100644 --- a/resources/views/components/status-badge.blade.php +++ b/resources/views/components/status-badge.blade.php @@ -5,6 +5,7 @@ 'as' => 'span', 'dynamic' => false, 'pulse' => false, // ping the dot for a state that is still in progress + 'spinning' => false, // show the loading spinner instead of the dot, e.g. for a running deployment ]) @php @@ -23,12 +24,19 @@ @if ($dynamic) {{ $slot }} @else + @if ($spinning) + + @else @if ($pulse) @endif + @endif {{ collect([$label, $status])->filter()->join(' ') }} @endif @@ -37,12 +45,19 @@ @if ($dynamic) {{ $slot }} @else + @if ($spinning) + + @else @if ($pulse) @endif + @endif {{ collect([$label, $status])->filter()->join(' ') }} @endif @@ -51,12 +66,19 @@ @if ($dynamic) {{ $slot }} @else + @if ($spinning) + + @else @if ($pulse) @endif + @endif {{ collect([$label, $status])->filter()->join(' ') }} @endif diff --git a/resources/views/livewire/dashboard/active-deployments.blade.php b/resources/views/livewire/dashboard/active-deployments.blade.php index dc3ab8ed93..451a7a7837 100644 --- a/resources/views/livewire/dashboard/active-deployments.blade.php +++ b/resources/views/livewire/dashboard/active-deployments.blade.php @@ -81,14 +81,14 @@ {{ $deployment->server_name ?: '-' }}

- +

{{ $environmentPath ?: '-' }} · @@ -141,14 +141,14 @@ {{ $deployment->server_name ?: '-' }}

- +

{{ $environmentPath ?: '-' }} · diff --git a/resources/views/livewire/deployments-indicator.blade.php b/resources/views/livewire/deployments-indicator.blade.php index 7d745f7066..c325949389 100644 --- a/resources/views/livewire/deployments-indicator.blade.php +++ b/resources/views/livewire/deployments-indicator.blade.php @@ -48,7 +48,7 @@

{{ $deployment->application_name }}

-
diff --git a/resources/views/livewire/project/application/deployment/index.blade.php b/resources/views/livewire/project/application/deployment/index.blade.php index c5fe02f54b..c3afa9176f 100644 --- a/resources/views/livewire/project/application/deployment/index.blade.php +++ b/resources/views/livewire/project/application/deployment/index.blade.php @@ -276,6 +276,7 @@ @unless ($embedded) @@ -333,6 +334,10 @@ {{ \Carbon\Carbon::parse(data_get($deployment, 'created_at'))->diffForHumans(syntax: \Carbon\CarbonInterface::DIFF_ABSOLUTE, short: true) }} + @if ($deploymentStatus === 'in_progress') + + @else $statusType === 'success', @@ -340,6 +345,7 @@ 'bg-red-500' => $statusType === 'error', 'bg-neutral-400 dark:bg-neutral-500' => $statusType === 'neutral', ])> + @endif @endif
+ @if ($deploymentStatus === 'in_progress') + + @else $deploymentStatusType === 'success', @@ -343,6 +346,7 @@ 'bg-red-500' => $deploymentStatusType === 'error', 'bg-neutral-400 dark:bg-neutral-500' => $deploymentStatusType === 'neutral', ])> + @endif {{ $deploymentStatusLabel }} From 868c0f06bfd3272d28f27960b5ed7e0c1717f213 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:46:52 +0100 Subject: [PATCH 5/7] fix(api): require deploy ability for registry check and logout Align the registry check and logout endpoints with the registry login endpoint. Co-Authored-By: Claude Opus 5.5 --- app/Http/Controllers/Api/ServerDockerRegistriesController.php | 4 ++-- openapi.json | 4 ++-- openapi.yaml | 4 ++-- routes/api.php | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Api/ServerDockerRegistriesController.php b/app/Http/Controllers/Api/ServerDockerRegistriesController.php index 2923335dcd..5d76a1301a 100644 --- a/app/Http/Controllers/Api/ServerDockerRegistriesController.php +++ b/app/Http/Controllers/Api/ServerDockerRegistriesController.php @@ -231,7 +231,7 @@ class ServerDockerRegistriesController extends Controller #[OA\Post( summary: 'Check a registry login on a server', - description: 'Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server.', + description: 'Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server. Needs a token with the write and deploy permissions.', path: '/servers/{uuid}/registries/{registry}/check', operationId: 'check-server-registry-login', security: [['bearerAuth' => []]], @@ -268,7 +268,7 @@ class ServerDockerRegistriesController extends Controller #[OA\Delete( summary: 'Log out from a registry on a server', - description: 'Run docker logout on the server for a registry.', + description: 'Run docker logout on the server for a registry. Needs a token with the write and deploy permissions.', path: '/servers/{uuid}/registries/{registry}', operationId: 'logout-server-registry', security: [['bearerAuth' => []]], diff --git a/openapi.json b/openapi.json index 611d8f87af..53f3325211 100644 --- a/openapi.json +++ b/openapi.json @@ -17000,7 +17000,7 @@ "Servers" ], "summary": "Check a registry login on a server", - "description": "Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server.", + "description": "Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server. Needs a token with the write and deploy permissions.", "operationId": "check-server-registry-login", "parameters": [ { @@ -17065,7 +17065,7 @@ "Servers" ], "summary": "Log out from a registry on a server", - "description": "Run docker logout on the server for a registry.", + "description": "Run docker logout on the server for a registry. Needs a token with the write and deploy permissions.", "operationId": "logout-server-registry", "parameters": [ { diff --git a/openapi.yaml b/openapi.yaml index acaae528e9..743cf4b7ee 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -10824,7 +10824,7 @@ paths: tags: - Servers summary: 'Check a registry login on a server' - description: 'Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server.' + description: 'Check that the saved login of the server for a registry still works. Runs docker login with the saved credentials on the server. Needs a token with the write and deploy permissions.' operationId: check-server-registry-login parameters: - @@ -10866,7 +10866,7 @@ paths: tags: - Servers summary: 'Log out from a registry on a server' - description: 'Run docker logout on the server for a registry.' + description: 'Run docker logout on the server for a registry. Needs a token with the write and deploy permissions.' operationId: logout-server-registry parameters: - diff --git a/routes/api.php b/routes/api.php index f2efce3b00..8d445c84e5 100644 --- a/routes/api.php +++ b/routes/api.php @@ -194,8 +194,8 @@ Route::group([ Route::get('/servers/{uuid}/registries', [ServerDockerRegistriesController::class, 'index'])->middleware(['api.ability:read:sensitive']); Route::post('/servers/{uuid}/registries', [ServerDockerRegistriesController::class, 'login'])->middleware(['api.ability:write', 'api.ability:deploy']); - Route::post('/servers/{uuid}/registries/{registry}/check', [ServerDockerRegistriesController::class, 'check'])->middleware(['api.ability:write']); - Route::delete('/servers/{uuid}/registries/{registry}', [ServerDockerRegistriesController::class, 'logout'])->middleware(['api.ability:write']); + Route::post('/servers/{uuid}/registries/{registry}/check', [ServerDockerRegistriesController::class, 'check'])->middleware(['api.ability:write', 'api.ability:deploy']); + Route::delete('/servers/{uuid}/registries/{registry}', [ServerDockerRegistriesController::class, 'logout'])->middleware(['api.ability:write', 'api.ability:deploy']); Route::get('/servers/{uuid}/proxy', [ServerProxyController::class, 'show'])->middleware(['api.ability:read']); Route::patch('/servers/{uuid}/proxy', [ServerProxyController::class, 'update'])->middleware(['api.ability:write']); From 23eebbf2adc7e9e3503af2b9fb603ce5dbc1db21 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:49:13 +0100 Subject: [PATCH 6/7] fix(servers): refresh provider status with server details action --- app/Livewire/Server/Show.php | 29 +++++++++++++- .../views/livewire/server/show.blade.php | 38 +++++-------------- tests/Feature/HostingerServerCreationTest.php | 16 ++++++-- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index 45b617fab1..bf5d519018 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -850,8 +850,11 @@ class Show extends Component { try { $this->authorize('update', $this->server); + $providerRefreshed = $this->refreshProviderStatus(); if (! $this->server->isFunctional()) { - $this->dispatch('error', 'Validate the server connection before fetching details.'); + $providerRefreshed + ? $this->dispatch('info', 'Provider status refreshed. Validate the server connection to fetch server details.') + : $this->dispatch('error', 'Validate the server connection before fetching details.'); return; } @@ -868,6 +871,30 @@ class Show extends Component } } + /** + * Refresh the state of the linked cloud provider server, if there is one. + */ + private function refreshProviderStatus(): bool + { + if (! $this->server->cloudProviderToken || $this->server->isTransferredAway()) { + return false; + } + + $check = match (true) { + filled($this->server->hetzner_server_id) => $this->checkHetznerServerStatus(...), + filled($this->server->digitalocean_droplet_id) => $this->checkDigitalOceanDropletStatus(...), + filled($this->server->vultr_instance_id) => $this->checkVultrInstanceStatus(...), + filled($this->server->hostinger_virtual_machine_id) => $this->checkHostingerVirtualMachineStatus(...), + default => null, + }; + if (! $check) { + return false; + } + $check(); + + return true; + } + public function submit() { try { diff --git a/resources/views/livewire/server/show.blade.php b/resources/views/livewire/server/show.blade.php index bbd3c5935b..96387be41d 100644 --- a/resources/views/livewire/server/show.blade.php +++ b/resources/views/livewire/server/show.blade.php @@ -28,6 +28,7 @@ 'Hostinger' => $hostingerVirtualMachineStatus, default => null, }; + $canRefreshProvider = $provider && $server->cloudProviderToken && ! $server->isTransferredAway(); $providerStatusType = match (true) { in_array($providerStatus, ['running', 'active']) => 'success', in_array($providerStatus, ['starting', 'initializing', 'pending', 'new', 'initial', 'creating', 'unsuspending', 'recreating', 'restoring']) => 'warning', @@ -265,35 +266,14 @@ - - @if ($provider) + @if ($provider) + - @if ($provider === 'Hetzner') - - - - @elseif ($provider === 'DigitalOcean') - - - - @elseif ($provider === 'Vultr') - - - - @elseif ($provider === 'Hostinger') - - - - @endif + + @endif + + @if ($provider) @if ($server->cloudProviderToken && ! $server->isTransferredAway()) @if ($provider === 'Hetzner' && !$server->isFunctional() && $hetznerServerStatus === 'off') + :disabled="! $server->isFunctional() && ! $canRefreshProvider" + :tooltip="$server->isFunctional() || $canRefreshProvider ? null : 'Validate the connection first.'"> {{ $server->server_metadata ? 'Refresh details' : 'Fetch server details' }} diff --git a/tests/Feature/HostingerServerCreationTest.php b/tests/Feature/HostingerServerCreationTest.php index ac39d73271..378b03e8be 100644 --- a/tests/Feature/HostingerServerCreationTest.php +++ b/tests/Feature/HostingerServerCreationTest.php @@ -407,7 +407,7 @@ it('starts a stopped Hostinger VPS from the server page', function () { expect($server->fresh()->hostinger_virtual_machine_status)->toBe('starting'); }); -it('labels the Hostinger status refresh button on the server page', function () { +it('refreshes the Hostinger status from the server details action before the server is validated', function () { $server = Server::factory()->create([ 'team_id' => $this->team->id, 'private_key_id' => $this->privateKey->id, @@ -416,10 +416,20 @@ it('labels the Hostinger status refresh button on the server page', function () 'hostinger_virtual_machine_status' => 'running', ]); + Http::fake([ + 'https://developers.hostinger.com/api/vps/v1/virtual-machines/17923' => Http::response([ + 'id' => 17923, + 'state' => 'stopped', + 'ipv4' => [['address' => $server->ip]], + ]), + ]); + Livewire::test(Show::class, ['server_uuid' => $server->uuid]) ->assertSee('Hostinger · Running') - ->assertSee('Refresh provider status') - ->assertSeeHtml('wire:click.prevent="checkHostingerVirtualMachineStatus(true)"'); + ->call('refreshServerMetadata') + ->assertSet('hostingerVirtualMachineStatus', 'stopped') + ->assertDispatched('info', 'Provider status refreshed. Validate the server connection to fetch server details.') + ->assertSee('Hostinger · Stopped'); }); it('does not validate a stopped Hostinger VPS over SSH', function () { From faf0b6fac4f74d1eee873fe78c2bed98ee7e4dd3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 1 Nov 2026 21:03:26 +0100 Subject: [PATCH 7/7] fix(runners): preserve unsaved settings during Sysbox checks Move Sysbox checks and installation into a lazy Livewire component so its requests do not reset the runner form's unsaved state. Update tests to cover the separate component. --- app/Livewire/Server/GithubRunners.php | 25 -------- app/Livewire/Server/SysboxStatus.php | 62 +++++++++++++++++++ .../livewire/server/github-runners.blade.php | 28 +-------- .../sysbox-status-placeholder.blade.php | 5 ++ .../livewire/server/sysbox-status.blade.php | 22 +++++++ tests/Feature/GithubRunnerSettingsTest.php | 33 +++++----- 6 files changed, 108 insertions(+), 67 deletions(-) create mode 100644 app/Livewire/Server/SysboxStatus.php create mode 100644 resources/views/livewire/server/sysbox-status-placeholder.blade.php create mode 100644 resources/views/livewire/server/sysbox-status.blade.php diff --git a/app/Livewire/Server/GithubRunners.php b/app/Livewire/Server/GithubRunners.php index 598a8485fc..1da4a95f48 100644 --- a/app/Livewire/Server/GithubRunners.php +++ b/app/Livewire/Server/GithubRunners.php @@ -55,11 +55,6 @@ class GithubRunners extends Component public bool $allowPullRequests = false; - /** Null until checked over SSH. */ - public ?bool $isSysboxInstalled = null; - - protected $listeners = ['sysboxInstalled' => 'checkSysbox']; - public function mount(string $server_uuid) { try { @@ -178,7 +173,6 @@ class GithubRunners extends Component $githubApp = $this->selectedApp; $this->authorize('update', $githubApp); if ($this->dockerMode === GithubRunnerDockerMode::Sysbox->value && ! InstallSysbox::isInstalled($this->server)) { - $this->isSysboxInstalled = false; throw ValidationException::withMessages(['dockerMode' => 'Sysbox is not installed on this server. Install it, then save again.']); } @@ -258,25 +252,6 @@ class GithubRunners extends Component } } - public function checkSysbox(): void - { - $this->authorize('view', $this->server); - $this->isSysboxInstalled = InstallSysbox::isInstalled($this->server); - } - - public function installSysbox() - { - $this->authorize('update', $this->server); - - try { - $activity = InstallSysbox::run($this->server); - $this->dispatch('sysbox-install-started'); - $this->dispatch('activityMonitor', $activity->id, 'sysboxInstalled'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - /** * Creates the runner group when the App can run workflow jobs. An App that is not ready is saved anyway: * the page lists what it misses, and the runner group is created when the first job is provisioned. diff --git a/app/Livewire/Server/SysboxStatus.php b/app/Livewire/Server/SysboxStatus.php new file mode 100644 index 0000000000..06cb0549b3 --- /dev/null +++ b/app/Livewire/Server/SysboxStatus.php @@ -0,0 +1,62 @@ + 'checkSysbox']; + + public function mount(Server $server): void + { + $this->authorize('view', $server); + $this->server = $server; + $this->checkSysbox(); + } + + public function checkSysbox(): void + { + $this->authorize('view', $this->server); + $this->isInstalled = InstallSysbox::isInstalled($this->server); + } + + public function installSysbox() + { + $this->authorize('update', $this->server); + + try { + $activity = InstallSysbox::run($this->server); + $this->dispatch('sysbox-install-started'); + $this->dispatch('activityMonitor', $activity->id, 'sysboxInstalled'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function placeholder(): View + { + return view('livewire.server.sysbox-status-placeholder'); + } + + public function render(): View + { + return view('livewire.server.sysbox-status'); + } +} diff --git a/resources/views/livewire/server/github-runners.blade.php b/resources/views/livewire/server/github-runners.blade.php index 9623b0453f..bcda87358c 100644 --- a/resources/views/livewire/server/github-runners.blade.php +++ b/resources/views/livewire/server/github-runners.blade.php @@ -171,32 +171,8 @@ :placeholder="config('constants.github_runner.image')" helper="Empty uses the latest official runner image, which Coolify pulls for every runner. Set a tag, for example ghcr.io/actions/actions-runner:2.337.0, to pin a version, or use a custom image based on the official one to add tools. GitHub stops sending jobs to runners that are more than 30 days old." /> -
- @if ($isSysboxInstalled === true) - - Jobs get a private Docker daemon in an unprivileged container. - - @elseif ($isSysboxInstalled === false) - - Isolated Docker needs the Sysbox runtime. Coolify installs Sysbox - {{ config('constants.github_runner.sysbox.version') }} from the official package - (Debian and Ubuntu, kernel 5.12 or newer). Docker reloads its configuration, and - running containers are not restarted. - @can('update', $server) -
- - Install Sysbox - -
- @endcan -
- @else - - Coolify checks if Sysbox is installed on this server. - - @endif +
+
diff --git a/resources/views/livewire/server/sysbox-status-placeholder.blade.php b/resources/views/livewire/server/sysbox-status-placeholder.blade.php new file mode 100644 index 0000000000..d6a3e2a34e --- /dev/null +++ b/resources/views/livewire/server/sysbox-status-placeholder.blade.php @@ -0,0 +1,5 @@ +
+ + Coolify checks if Sysbox is installed on this server. + +
diff --git a/resources/views/livewire/server/sysbox-status.blade.php b/resources/views/livewire/server/sysbox-status.blade.php new file mode 100644 index 0000000000..b6bd94a7aa --- /dev/null +++ b/resources/views/livewire/server/sysbox-status.blade.php @@ -0,0 +1,22 @@ +
+ @if ($isInstalled) + + Jobs get a private Docker daemon in an unprivileged container. + + @else + + Isolated Docker needs the Sysbox runtime. Coolify installs Sysbox + {{ config('constants.github_runner.sysbox.version') }} from the official package + (Debian and Ubuntu, kernel 5.12 or newer). Docker reloads its configuration, and + running containers are not restarted. + @can('update', $server) +
+ + Install Sysbox + +
+ @endcan +
+ @endif +
diff --git a/tests/Feature/GithubRunnerSettingsTest.php b/tests/Feature/GithubRunnerSettingsTest.php index 16fe8067df..6bfc8e142d 100644 --- a/tests/Feature/GithubRunnerSettingsTest.php +++ b/tests/Feature/GithubRunnerSettingsTest.php @@ -8,6 +8,7 @@ use App\Jobs\ProvisionGithubRunnerJob; use App\Livewire\Server\GithubRunnerExecutions; use App\Livewire\Server\GithubRunners; use App\Livewire\Server\Show; +use App\Livewire\Server\SysboxStatus; use App\Livewire\Source\Github\Change; use App\Livewire\Source\Github\Create; use App\Models\GithubApp; @@ -446,8 +447,7 @@ describe('isolated Docker with Sysbox', function () { ->set('githubAppId', $this->githubApp->id) ->set('dockerMode', 'sysbox') ->call('submit') - ->assertHasErrors('dockerMode') - ->assertSet('isSysboxInstalled', false); + ->assertHasErrors('dockerMode'); expect(GithubRunnerConfig::count())->toBe(0); }); @@ -469,29 +469,29 @@ describe('isolated Docker with Sysbox', function () { it('checks that Sysbox can mount its FUSE file system', function () { Process::fake(['*' => Process::result(output: '')]); - Livewire::actingAs($this->owner) - ->test(GithubRunners::class, ['server_uuid' => $this->server->uuid]) - ->call('checkSysbox'); + Livewire::withoutLazyLoading() + ->actingAs($this->owner) + ->test(SysboxStatus::class, ['server' => $this->server]); Process::assertRan(fn ($process) => str_contains(remoteProcessScript($process), 'test -x /usr/bin/fusermount3')); }); it('shows the install button when Sysbox is missing', function () { Process::fake(['*' => Process::result(output: '')]); - GithubRunnerConfig::create(['server_id' => $this->server->id, 'github_app_id' => $this->githubApp->id, 'labels' => ['coolify']]); - Livewire::actingAs($this->owner) - ->test(GithubRunners::class, ['server_uuid' => $this->server->uuid]) - ->call('checkSysbox') - ->assertSet('isSysboxInstalled', false) + Livewire::withoutLazyLoading() + ->actingAs($this->owner) + ->test(SysboxStatus::class, ['server' => $this->server]) + ->assertSet('isInstalled', false) ->assertSee('Install Sysbox'); }); it('stops before the installation on servers without apt', function () { Process::fake(['*' => Process::result(output: '')]); - Livewire::actingAs($this->owner) - ->test(GithubRunners::class, ['server_uuid' => $this->server->uuid]) + Livewire::withoutLazyLoading() + ->actingAs($this->owner) + ->test(SysboxStatus::class, ['server' => $this->server]) ->call('installSysbox') ->assertNotDispatched('activityMonitor'); @@ -499,14 +499,15 @@ describe('isolated Docker with Sysbox', function () { }); it('does not let members install Sysbox', function () { - Process::fake(); + Process::fake(['*' => Process::result(output: '')]); - Livewire::actingAs($this->member) - ->test(GithubRunners::class, ['server_uuid' => $this->server->uuid]) + Livewire::withoutLazyLoading() + ->actingAs($this->member) + ->test(SysboxStatus::class, ['server' => $this->server]) ->call('installSysbox') ->assertForbidden(); - Process::assertNothingRan(); + Process::assertDidntRun(fn ($process) => str_contains(remoteProcessScript($process), 'apt-get')); }); });