diff --git a/app/Livewire/Project/Shared/Webhooks.php b/app/Livewire/Project/Shared/Webhooks.php index 172d91fc5e..b43ea471b0 100644 --- a/app/Livewire/Project/Shared/Webhooks.php +++ b/app/Livewire/Project/Shared/Webhooks.php @@ -2,11 +2,14 @@ namespace App\Livewire\Project\Shared; +use App\Models\Application; +use App\Models\GitlabApp; use App\Rules\ManualWebhookSecret; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; use Livewire\Component; +use Spatie\Url\Url; // Refactored ✅ class Webhooks extends Component @@ -25,6 +28,12 @@ class Webhooks extends Component public ?string $giteaManualWebhook; + /** + * Source-level endpoint for GitLab App sources. GitLab has no app-level webhooks, + * so users add this URL to each GitLab project themselves. + */ + public ?string $gitlabAppWebhook = null; + public ?string $githubManualWebhookSecret = null; public ?string $gitlabManualWebhookSecret = null; @@ -60,6 +69,10 @@ class Webhooks extends Component $this->gitlabManualWebhook = generateGitManualWebhook($this->resource, 'gitlab'); $this->bitbucketManualWebhook = generateGitManualWebhook($this->resource, 'bitbucket'); $this->giteaManualWebhook = generateGitManualWebhook($this->resource, 'gitea'); + + if ($this->resource instanceof Application && $this->resource->source instanceof GitlabApp) { + $this->gitlabAppWebhook = Url::fromString(base_url()).'/webhooks/source/gitlab/events'; + } } public function canViewSecrets(): bool diff --git a/resources/views/livewire/project/shared/webhooks.blade.php b/resources/views/livewire/project/shared/webhooks.blade.php index 8e5483b283..a004d83796 100644 --- a/resources/views/livewire/project/shared/webhooks.blade.php +++ b/resources/views/livewire/project/shared/webhooks.blade.php @@ -99,6 +99,37 @@ + @elseif ($gitlabAppWebhook) + + + @can('view', $resource->source) + + Source settings + + @endcan + @if (filled($resource?->gitWebhook)) + + Repository settings + + + @endif + + +
+
+

GitLab

+

+ Add this URL in the GitLab project under Settings → Webhooks. Set the Secret token to + the Webhook secret token from the source settings, and enable Push events and Merge + request events. +

+
+ +
+
@else diff --git a/tests/Feature/Webhook/GitAppWebhookSetupTest.php b/tests/Feature/Webhook/GitAppWebhookSetupTest.php new file mode 100644 index 0000000000..22007f24f6 --- /dev/null +++ b/tests/Feature/Webhook/GitAppWebhookSetupTest.php @@ -0,0 +1,82 @@ + 0]); + + $this->team = Team::factory()->create(); + $this->admin = User::factory()->create(); + $this->team->members()->attach($this->admin->id, ['role' => 'admin']); + + $server = Server::factory()->create(['team_id' => $this->team->id]); + $destination = StandaloneDocker::query()->where('server_id', $server->id)->firstOrFail(); + $project = Project::factory()->create(['team_id' => $this->team->id]); + $environment = Environment::factory()->create(['project_id' => $project->id]); + + $this->application = Application::factory()->create([ + 'environment_id' => $environment->id, + 'destination_id' => $destination->id, + 'destination_type' => $destination->getMorphClass(), + 'git_repository' => 'test-org/test-repo', + 'git_branch' => 'main', + ]); + + $this->actingAs($this->admin); + session(['currentTeam' => $this->team]); +}); + +afterEach(function () { + Server::flushIdentityMap(); +}); + +test('GitLab App sources show the source webhook instead of claiming automatic setup', function () { + $gitlabApp = GitlabApp::create([ + 'name' => 'gitlab-app-webhook-setup-test', + 'api_url' => 'https://gitlab.example.com/api/v4', + 'html_url' => 'https://gitlab.example.com', + 'webhook_token' => 'test-webhook-token', + 'team_id' => $this->team->id, + ]); + $this->application->update(['source_id' => $gitlabApp->id, 'source_type' => GitlabApp::class]); + + Livewire::test(Webhooks::class, ['resource' => $this->application->fresh()]) + ->assertSet('gitlabAppWebhook', url('/webhooks/source/gitlab/events')) + ->assertSee(url('/webhooks/source/gitlab/events')) + ->assertSee(route('source.gitlab.show', ['gitlab_app_uuid' => $gitlabApp->uuid])) + ->assertDontSee('test-webhook-token') + ->assertDontSee('Managed by your Git App'); +}); + +test('GitHub App sources still show that webhooks are managed by the app', function () { + $githubApp = GithubApp::create([ + 'name' => 'github-app-webhook-setup-test', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'app_id' => 1234567890, + 'webhook_secret' => 'test-secret', + 'is_public' => false, + 'team_id' => $this->team->id, + ]); + $this->application->update(['source_id' => $githubApp->id, 'source_type' => GithubApp::class]); + + Livewire::test(Webhooks::class, ['resource' => $this->application->fresh()]) + ->assertSet('gitlabAppWebhook', null) + ->assertSee('Managed by your Git App') + ->assertDontSee('/webhooks/source/gitlab/events'); +});