From e160b5139a97e58160702d7f9ba77aec17bdd05c Mon Sep 17 00:00:00 2001 From: Cinzya Date: Wed, 22 Oct 2025 20:55:24 +0200 Subject: [PATCH 01/18] refactor: replace allowed IPs validation logic with regex --- app/Livewire/Settings/Advanced.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Settings/Advanced.php b/app/Livewire/Settings/Advanced.php index 832123d5a..adca1baa3 100644 --- a/app/Livewire/Settings/Advanced.php +++ b/app/Livewire/Settings/Advanced.php @@ -89,7 +89,7 @@ public function submit() $allowsFromAnywhere = false; if (empty($this->allowed_ips)) { $allowsFromAnywhere = true; - } elseif ($this->allowed_ips === '0.0.0.0' || str_contains($this->allowed_ips, '0.0.0.0')) { + } elseif ($this->allowed_ips === '0.0.0.0' || in_array('0.0.0.0', array_map('trim', explode(',', $this->allowed_ips)))) { $allowsFromAnywhere = true; } From b6782427803d9bc70472884b7ecd3356f8a0dab7 Mon Sep 17 00:00:00 2001 From: Cinzya Date: Wed, 22 Oct 2025 21:02:23 +0200 Subject: [PATCH 02/18] refactor: remove redundant --- app/Livewire/Settings/Advanced.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/Livewire/Settings/Advanced.php b/app/Livewire/Settings/Advanced.php index adca1baa3..1edfc9638 100644 --- a/app/Livewire/Settings/Advanced.php +++ b/app/Livewire/Settings/Advanced.php @@ -89,13 +89,8 @@ public function submit() $allowsFromAnywhere = false; if (empty($this->allowed_ips)) { $allowsFromAnywhere = true; - } elseif ($this->allowed_ips === '0.0.0.0' || in_array('0.0.0.0', array_map('trim', explode(',', $this->allowed_ips)))) { + } elseif (in_array('0.0.0.0', array_map('trim', explode(',', $this->allowed_ips)))) { $allowsFromAnywhere = true; - } - - // Check if it's 0.0.0.0 (allow all) or empty - if ($this->allowed_ips === '0.0.0.0' || empty($this->allowed_ips)) { - // Keep as is - empty means no restriction, 0.0.0.0 means allow all } else { // Validate and clean up the entries $invalidEntries = []; From 06ee7d01324b3bf942acb3bcfff7bb5a6d501a9d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:49:09 +0200 Subject: [PATCH 03/18] fix: GitHub source creation and configuration issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed multiple issues with GitHub App source creation and management: 1. **Fixed null property assignment error on component mount** - Changed property types to nullable in Change component (appId, installationId, clientId, etc.) - Updated validation rules to allow nullable values - Allows mounting component with newly created GitHub Apps that don't have these fields set yet 2. **Fixed Livewire morphing error on manual creation** - Modified createGithubAppManually() to redirect after saving - Prevents "Cannot read properties of null" error when view structure changes - Fields now properly populated after manual creation without requiring page refresh 3. **Fixed is_system_wide not being saved on creation** - Removed backwards logic that only saved is_system_wide on cloud instances - Added is_system_wide to GithubApp model casts for proper boolean handling - System-wide checkbox now works correctly on self-hosted instances 4. **Fixed misleading preview deployment checkbox** - Removed instantSave attribute from permission checkboxes in unconfigured state - These are configuration options for GitHub App creation, not database fields - Prevents "GitHub App updated" success message when nothing was actually saved 5. **Added validation for Refetch Permissions button** - Validates App ID and Private Key are set before attempting to fetch - Shows clear error messages: "Cannot fetch permissions. Please set the following required fields first: App ID, Private Key" - Prevents crash when private key is null or invalid 6. **Better error handling for unsupported private key formats** - Detects OpenSSH format keys vs RSA PEM format - Shows helpful message: "Please use an RSA private key in PEM format (BEGIN RSA PRIVATE KEY). OpenSSH format keys are not supported." - GitHub Apps require RSA PEM format, not OpenSSH format 7. **Made GitHub App view mobile responsive** - Updated all flex layouts to stack vertically on mobile (flex-col sm:flex-row) - Form fields, buttons, and sections now properly responsive - No more cut-off fields on small screens Added comprehensive test coverage: - GithubSourceChangeTest.php with 7 tests - GithubSourceCreateTest.php with 6 tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/Livewire/Source/Github/Change.php | 96 ++++---- app/Livewire/Source/Github/Create.php | 4 +- app/Models/GithubApp.php | 1 + .../livewire/source/github/change.blade.php | 30 +-- tests/Feature/GithubSourceChangeTest.php | 208 ++++++++++++++++++ tests/Feature/GithubSourceCreateTest.php | 108 +++++++++ 6 files changed, 383 insertions(+), 64 deletions(-) create mode 100644 tests/Feature/GithubSourceChangeTest.php create mode 100644 tests/Feature/GithubSourceCreateTest.php diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index 351407dac..b03d0fa67 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -47,19 +47,19 @@ class Change extends Component public int $customPort; - public int $appId; + public ?int $appId = null; - public int $installationId; + public ?int $installationId = null; - public string $clientId; + public ?string $clientId = null; - public string $clientSecret; + public ?string $clientSecret = null; - public string $webhookSecret; + public ?string $webhookSecret = null; public bool $isSystemWide; - public int $privateKeyId; + public ?int $privateKeyId = null; public ?string $contents = null; @@ -78,16 +78,16 @@ class Change extends Component 'htmlUrl' => 'required|string', 'customUser' => 'required|string', 'customPort' => 'required|int', - 'appId' => 'required|int', - 'installationId' => 'required|int', - 'clientId' => 'required|string', - 'clientSecret' => 'required|string', - 'webhookSecret' => 'required|string', + 'appId' => 'nullable|int', + 'installationId' => 'nullable|int', + 'clientId' => 'nullable|string', + 'clientSecret' => 'nullable|string', + 'webhookSecret' => 'nullable|string', 'isSystemWide' => 'required|bool', 'contents' => 'nullable|string', 'metadata' => 'nullable|string', 'pullRequests' => 'nullable|string', - 'privateKeyId' => 'required|int', + 'privateKeyId' => 'nullable|int', ]; public function boot() @@ -148,47 +148,48 @@ public function checkPermissions() try { $this->authorize('view', $this->github_app); + // Validate required fields before attempting to fetch permissions + $missingFields = []; + + if (! $this->github_app->app_id) { + $missingFields[] = 'App ID'; + } + + if (! $this->github_app->private_key_id) { + $missingFields[] = 'Private Key'; + } + + if (! empty($missingFields)) { + $fieldsList = implode(', ', $missingFields); + $this->dispatch('error', "Cannot fetch permissions. Please set the following required fields first: {$fieldsList}"); + + return; + } + + // Verify the private key exists and is accessible + if (! $this->github_app->privateKey) { + $this->dispatch('error', 'Private Key not found. Please select a valid private key.'); + + return; + } + GithubAppPermissionJob::dispatchSync($this->github_app); $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->dispatch('success', 'Github App permissions updated.'); } catch (\Throwable $e) { + // Provide better error message for unsupported key formats + $errorMessage = $e->getMessage(); + if (str_contains($errorMessage, 'DECODER routines::unsupported') || + str_contains($errorMessage, 'parse your key')) { + $this->dispatch('error', 'The selected private key format is not supported for GitHub Apps.

Please use an RSA private key in PEM format (BEGIN RSA PRIVATE KEY).

OpenSSH format keys (BEGIN OPENSSH PRIVATE KEY) are not supported.'); + + return; + } + return handleError($e, $this); } } - // public function check() - // { - - // Need administration:read:write permission - // https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-self-hosted-runners-for-a-repository - - // $github_access_token = generateGithubInstallationToken($this->github_app); - // $repositories = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100"); - // $runners_by_repository = collect([]); - // $repositories = $repositories->json()['repositories']; - // foreach ($repositories as $repository) { - // $runners_downloads = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/downloads"); - // $runners = Http::withToken($github_access_token)->get("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners"); - // $token = Http::withHeaders([ - // 'Authorization' => "Bearer $github_access_token", - // 'Accept' => 'application/vnd.github+json' - // ])->withBody(null)->post("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/registration-token"); - // $token = $token->json(); - // $remove_token = Http::withHeaders([ - // 'Authorization' => "Bearer $github_access_token", - // 'Accept' => 'application/vnd.github+json' - // ])->withBody(null)->post("{$this->github_app->api_url}/repos/{$repository['full_name']}/actions/runners/remove-token"); - // $remove_token = $remove_token->json(); - // $runners_by_repository->put($repository['full_name'], [ - // 'token' => $token, - // 'remove_token' => $remove_token, - // 'runners' => $runners->json(), - // 'runners_downloads' => $runners_downloads->json() - // ]); - // } - - // } - public function mount() { try { @@ -343,7 +344,10 @@ public function createGithubAppManually() $this->github_app->app_id = '1234567890'; $this->github_app->installation_id = '1234567890'; $this->github_app->save(); - $this->dispatch('success', 'Github App updated.'); + + // Redirect to avoid Livewire morphing issues when view structure changes + return redirect()->route('source.github.show', ['github_app_uuid' => $this->github_app->uuid]) + ->with('success', 'Github App updated. You can now configure the details.'); } public function instantSave() diff --git a/app/Livewire/Source/Github/Create.php b/app/Livewire/Source/Github/Create.php index f5d851b64..2f1482c89 100644 --- a/app/Livewire/Source/Github/Create.php +++ b/app/Livewire/Source/Github/Create.php @@ -50,11 +50,9 @@ public function createGitHubApp() 'html_url' => $this->html_url, 'custom_user' => $this->custom_user, 'custom_port' => $this->custom_port, + 'is_system_wide' => $this->is_system_wide, 'team_id' => currentTeam()->id, ]; - if (isCloud()) { - $payload['is_system_wide'] = $this->is_system_wide; - } $github_app = GithubApp::create($payload); if (session('from')) { session(['from' => session('from') + ['source_id' => $github_app->id]]); diff --git a/app/Models/GithubApp.php b/app/Models/GithubApp.php index 5550df81f..0d643306c 100644 --- a/app/Models/GithubApp.php +++ b/app/Models/GithubApp.php @@ -12,6 +12,7 @@ class GithubApp extends BaseModel protected $casts = [ 'is_public' => 'boolean', + 'is_system_wide' => 'boolean', 'type' => 'string', ]; diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 7e6256259..6e1da2a02 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -1,7 +1,7 @@
@if (data_get($github_app, 'app_id'))
-
+

GitHub App

@if (data_get($github_app, 'installation_id')) @@ -40,8 +40,8 @@ @else
-
-
+
+
Sync Name @@ -73,23 +73,23 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans instantSave id="isSystemWide" />
@endif -
+
-
+
-
+
-
+
+

Permissions

@can('view', $github_app) Refetch @@ -120,7 +120,7 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans @endcan
-
+
@endif @else -
+

GitHub App

@can('delete', $github_app) @@ -228,7 +228,7 @@ class=""
@can('create', $github_app) @if (!isCloud() || isDev()) -
+
@if ($ipv4) @@ -250,7 +250,7 @@ class=""
@else -
+

Register a GitHub App

@@ -261,11 +261,11 @@ class="" @endif
- - - {{-- --}}
@else diff --git a/tests/Feature/GithubSourceChangeTest.php b/tests/Feature/GithubSourceChangeTest.php new file mode 100644 index 000000000..06c04dd41 --- /dev/null +++ b/tests/Feature/GithubSourceChangeTest.php @@ -0,0 +1,208 @@ +team = Team::factory()->create(); + $this->user = User::factory()->create(); + $this->team->members()->attach($this->user->id, ['role' => 'owner']); + + // Set current team + $this->actingAs($this->user); + session(['currentTeam' => $this->team]); +}); + +describe('GitHub Source Change Component', function () { + test('can mount with newly created github app with null app_id', function () { + // Create a GitHub app without app_id (simulating a newly created source) + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + // app_id is intentionally not set (null in database) + ]); + + // Test that the component can mount without errors + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->assertSet('appId', null) + ->assertSet('installationId', null) + ->assertSet('clientId', null) + ->assertSet('clientSecret', null) + ->assertSet('webhookSecret', null) + ->assertSet('privateKeyId', null); + }); + + test('can mount with fully configured github app', function () { + $privateKey = PrivateKey::create([ + 'name' => 'Test Key', + 'private_key' => 'test-private-key-content', + 'team_id' => $this->team->id, + ]); + + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'app_id' => 12345, + 'installation_id' => 67890, + 'client_id' => 'test-client-id', + 'client_secret' => 'test-client-secret', + 'webhook_secret' => 'test-webhook-secret', + 'private_key_id' => $privateKey->id, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->assertSet('appId', 12345) + ->assertSet('installationId', 67890) + ->assertSet('clientId', 'test-client-id') + ->assertSet('clientSecret', 'test-client-secret') + ->assertSet('webhookSecret', 'test-webhook-secret') + ->assertSet('privateKeyId', $privateKey->id); + }); + + test('can update github app from null to valid values', function () { + $privateKey = PrivateKey::create([ + 'name' => 'Test Key', + 'private_key' => 'test-private-key-content', + 'team_id' => $this->team->id, + ]); + + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->set('appId', 12345) + ->set('installationId', 67890) + ->set('clientId', 'new-client-id') + ->set('clientSecret', 'new-client-secret') + ->set('webhookSecret', 'new-webhook-secret') + ->set('privateKeyId', $privateKey->id) + ->call('submit') + ->assertDispatched('success'); + + // Verify the database was updated + $githubApp->refresh(); + expect($githubApp->app_id)->toBe(12345); + expect($githubApp->installation_id)->toBe(67890); + expect($githubApp->client_id)->toBe('new-client-id'); + expect($githubApp->private_key_id)->toBe($privateKey->id); + }); + + test('validation allows nullable values for app configuration', function () { + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + // Test that validation passes with null values + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->call('submit') + ->assertHasNoErrors(); + }); + + test('createGithubAppManually redirects to avoid morphing issues', function () { + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + // Test that createGithubAppManually redirects instead of updating in place + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->call('createGithubAppManually') + ->assertRedirect(route('source.github.show', ['github_app_uuid' => $githubApp->uuid])); + + // Verify the database was updated + $githubApp->refresh(); + expect($githubApp->app_id)->toBe('1234567890'); + expect($githubApp->installation_id)->toBe('1234567890'); + }); + + test('checkPermissions validates required fields', function () { + // Create a GitHub app without app_id and private_key_id + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + // Test that checkPermissions fails with appropriate error + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->call('checkPermissions') + ->assertDispatched('error', function ($event, $message) { + return str_contains($message, 'App ID') && str_contains($message, 'Private Key'); + }); + }); + + test('checkPermissions validates private key exists', function () { + $githubApp = GithubApp::create([ + 'name' => 'Test GitHub App', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'custom_user' => 'git', + 'custom_port' => 22, + 'app_id' => 12345, + 'private_key_id' => 99999, // Non-existent private key ID + 'team_id' => $this->team->id, + 'is_system_wide' => false, + ]); + + // Test that checkPermissions fails when private key doesn't exist + Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid]) + ->test(Change::class) + ->assertSuccessful() + ->call('checkPermissions') + ->assertDispatched('error', function ($event, $message) { + return str_contains($message, 'Private Key not found'); + }); + }); +}); diff --git a/tests/Feature/GithubSourceCreateTest.php b/tests/Feature/GithubSourceCreateTest.php new file mode 100644 index 000000000..82343092c --- /dev/null +++ b/tests/Feature/GithubSourceCreateTest.php @@ -0,0 +1,108 @@ +team = Team::factory()->create(); + $this->user = User::factory()->create(); + $this->team->members()->attach($this->user->id, ['role' => 'owner']); + + // Set current team + $this->actingAs($this->user); + session(['currentTeam' => $this->team]); +}); + +describe('GitHub Source Create Component', function () { + test('creates github app with default values', function () { + Livewire::test(Create::class) + ->assertSuccessful() + ->set('name', 'my-test-app') + ->call('createGitHubApp') + ->assertRedirect(); + + $githubApp = GithubApp::where('name', 'my-test-app')->first(); + + expect($githubApp)->not->toBeNull(); + expect($githubApp->name)->toBe('my-test-app'); + expect($githubApp->api_url)->toBe('https://api.github.com'); + expect($githubApp->html_url)->toBe('https://github.com'); + expect($githubApp->custom_user)->toBe('git'); + expect($githubApp->custom_port)->toBe(22); + expect($githubApp->is_system_wide)->toBeFalse(); + expect($githubApp->team_id)->toBe($this->team->id); + }); + + test('creates github app with system wide enabled', function () { + Livewire::test(Create::class) + ->assertSuccessful() + ->set('name', 'system-wide-app') + ->set('is_system_wide', true) + ->call('createGitHubApp') + ->assertRedirect(); + + $githubApp = GithubApp::where('name', 'system-wide-app')->first(); + + expect($githubApp)->not->toBeNull(); + expect($githubApp->is_system_wide)->toBeTrue(); + }); + + test('creates github app with custom organization', function () { + Livewire::test(Create::class) + ->assertSuccessful() + ->set('name', 'org-app') + ->set('organization', 'my-org') + ->call('createGitHubApp') + ->assertRedirect(); + + $githubApp = GithubApp::where('name', 'org-app')->first(); + + expect($githubApp)->not->toBeNull(); + expect($githubApp->organization)->toBe('my-org'); + }); + + test('creates github app with custom git settings', function () { + Livewire::test(Create::class) + ->assertSuccessful() + ->set('name', 'enterprise-app') + ->set('api_url', 'https://github.enterprise.com/api/v3') + ->set('html_url', 'https://github.enterprise.com') + ->set('custom_user', 'git-custom') + ->set('custom_port', 2222) + ->call('createGitHubApp') + ->assertRedirect(); + + $githubApp = GithubApp::where('name', 'enterprise-app')->first(); + + expect($githubApp)->not->toBeNull(); + expect($githubApp->api_url)->toBe('https://github.enterprise.com/api/v3'); + expect($githubApp->html_url)->toBe('https://github.enterprise.com'); + expect($githubApp->custom_user)->toBe('git-custom'); + expect($githubApp->custom_port)->toBe(2222); + }); + + test('validates required fields', function () { + Livewire::test(Create::class) + ->assertSuccessful() + ->set('name', '') + ->call('createGitHubApp') + ->assertHasErrors(['name']); + }); + + test('redirects to github app show page after creation', function () { + $component = Livewire::test(Create::class) + ->set('name', 'redirect-test') + ->call('createGitHubApp'); + + $githubApp = GithubApp::where('name', 'redirect-test')->first(); + + $component->assertRedirect(route('source.github.show', ['github_app_uuid' => $githubApp->uuid])); + }); +}); From a69339804c8a2b3598f50cefcf6e4ab0565e18e1 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:50:50 +0200 Subject: [PATCH 04/18] feat: add warnings for system-wide GitHub Apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added warning callouts to inform users that system-wide GitHub Apps are not recommended for security reasons. Changes: - Added warning callout in Create view when system-wide checkbox is enabled - Added warning callout in Change view when GitHub App is system-wide - Warning explains that system-wide apps are shared across all teams and can access repositories from any team - Recommends creating team-specific GitHub Apps for better security and isolation The warnings only appear on self-hosted instances where system-wide option is available (not on cloud). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- resources/views/livewire/source/github/change.blade.php | 5 +++++ resources/views/livewire/source/github/create.blade.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 6e1da2a02..4f660bc94 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -72,6 +72,11 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans helper="If checked, this GitHub App will be available for everyone in this Coolify instance." instantSave id="isSystemWide" />
+ @if ($isSystemWide) + + System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. + + @endif @endif
diff --git a/resources/views/livewire/source/github/create.blade.php b/resources/views/livewire/source/github/create.blade.php index f47575784..7681e0fd9 100644 --- a/resources/views/livewire/source/github/create.blade.php +++ b/resources/views/livewire/source/github/create.blade.php @@ -13,6 +13,11 @@
+ @if ($is_system_wide) + + System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. + + @endif @endif
--- .../livewire/source/github/change.blade.php | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 4f660bc94..0758afb70 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -149,51 +149,56 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans
Here you can find all resources that are using this source.
-
+ @if ($applications->isEmpty()) +
+ No resources are currently using this GitHub App. +
+ @else
-
-
-
- - - - - - - - - - - @forelse ($applications->sortBy('name',SORT_NATURAL) as $resource) +
+
+
+
+
- Project - - EnvironmentName - Type -
+ - - - - + + + + - @empty - @endforelse - -
- {{ data_get($resource->project(), 'name') }} - - {{ data_get($resource, 'environment.name') }} - {{ $resource->name }} - - - {{ str($resource->type())->headline() }} + Project + + EnvironmentName + Type +
+ + + @foreach ($applications->sortBy('name',SORT_NATURAL) as $resource) + + + {{ data_get($resource->project(), 'name') }} + + + {{ data_get($resource, 'environment.name') }} + + {{ $resource->name }} + + + + {{ str($resource->type())->headline() }} + + @endforeach + + +
-
+ @endif
@endif From 6746e44dba5c22fa4c052c314f84ea5233c4a13e Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:53:25 +0200 Subject: [PATCH 06/18] fix: make system-wide warning reactive in Create view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The system-wide warning callout was not appearing when the checkbox was toggled because it was only evaluated on initial render. Changes: - Wrapped checkbox and warning in Alpine.js x-data scope - Used @entangle to bind showWarning to the is_system_wide Livewire property - Added x-show directive to reactively show/hide warning based on checkbox state - Added x-transition for smooth appearance/disappearance - Added style="display: none;" to prevent flash of content on load Now the warning appears immediately when the System Wide checkbox is checked and disappears when unchecked. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../livewire/source/github/create.blade.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/resources/views/livewire/source/github/create.blade.php b/resources/views/livewire/source/github/create.blade.php index 7681e0fd9..108c243e1 100644 --- a/resources/views/livewire/source/github/create.blade.php +++ b/resources/views/livewire/source/github/create.blade.php @@ -9,15 +9,17 @@ placeholder="If empty, your GitHub user will be used." id="organization" label="Organization (on GitHub)" />
@if (!isCloud()) -
- +
+
+ +
+
+ + System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. + +
- @if ($is_system_wide) - - System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. - - @endif @endif
@if ($isSystemWide) - - System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. - +
+ + System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. + +
@endif @endif
diff --git a/resources/views/livewire/source/github/create.blade.php b/resources/views/livewire/source/github/create.blade.php index 108c243e1..361e8b520 100644 --- a/resources/views/livewire/source/github/create.blade.php +++ b/resources/views/livewire/source/github/create.blade.php @@ -14,8 +14,8 @@
-
- + From 2f2ab6d775c500f28742e9a8e121f9a59ef220dc Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:58:26 +0200 Subject: [PATCH 08/18] fix: constrain callout width with max-w-2xl and wrap text properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set explicit max-width constraint (max-w-2xl) on callout wrapper and added whitespace-normal to ensure text wraps properly within the modal instead of expanding it horizontally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- resources/views/livewire/source/github/change.blade.php | 8 +++++--- resources/views/livewire/source/github/create.blade.php | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 9530ccbfd..5b8c6241a 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -73,9 +73,11 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans instantSave id="isSystemWide" />
@if ($isSystemWide) -
- - System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. +
+ +
+ System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. +
@endif diff --git a/resources/views/livewire/source/github/create.blade.php b/resources/views/livewire/source/github/create.blade.php index 361e8b520..ebc9c1566 100644 --- a/resources/views/livewire/source/github/create.blade.php +++ b/resources/views/livewire/source/github/create.blade.php @@ -14,9 +14,11 @@
- From fc285625c204d035d19ae595160334e79d181846 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 25 Oct 2025 11:19:52 +0200 Subject: [PATCH 09/18] fix: center system-wide warning callout in modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added mx-auto to center the callout horizontally within the modal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- resources/views/livewire/source/github/change.blade.php | 2 +- resources/views/livewire/source/github/create.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 5b8c6241a..635c8c3cb 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -73,7 +73,7 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans instantSave id="isSystemWide" />
@if ($isSystemWide) -
+
System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead. diff --git a/resources/views/livewire/source/github/create.blade.php b/resources/views/livewire/source/github/create.blade.php index ebc9c1566..54cb426cb 100644 --- a/resources/views/livewire/source/github/create.blade.php +++ b/resources/views/livewire/source/github/create.blade.php @@ -14,7 +14,7 @@
-