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