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')); }); });