Skip to content

feat(gitlab): add webhook support with getEvent, validateWebhookEvent, createWebhook and createPullRequest#93

Open
jaysomani wants to merge 3 commits intoutopia-php:mainfrom
jaysomani:feat/gitlab-adapter-webhooks
Open

feat(gitlab): add webhook support with getEvent, validateWebhookEvent, createWebhook and createPullRequest#93
jaysomani wants to merge 3 commits intoutopia-php:mainfrom
jaysomani:feat/gitlab-adapter-webhooks

Conversation

@jaysomani
Copy link
Copy Markdown
Contributor

Summary

Implements webhook support for the GitLab adapter, completing the event-driven integration layer.

Changes

New methods implemented

  • createWebhook — registers a webhook on a GitLab project with configurable events (push, pull_request/merge request), returning the webhook ID
  • getEvent — parses incoming GitLab webhook payloads for Push Hook and Merge Request Hook events into a normalized format consistent with other adapters
  • validateWebhookEvent — validates the X-Gitlab-Token header against the configured secret using hash_equals to prevent timing attacks
  • createPullRequest — creates a GitLab merge request; implemented here as a dependency for the webhook E2E test setup

Tests added

  • testCreateWebhook — verifies webhook creation returns a valid ID
  • testWebhookPushEvent — E2E test that creates a repo, registers a webhook, triggers a push, and asserts the payload is received via request-catcher
  • testWebhookPullRequestEvent — E2E test that creates a repo, opens a merge request, and asserts the merge request webhook payload is received
  • testValidateWebhookEvent — unit test for valid and invalid token scenarios
  • testGetEventPush — unit test for push payload parsing
  • testGetEventPullRequest — unit test for merge request payload parsing
  • testGetEventUnknown — unit test for unknown event type returns empty array

Notes

  • GitLab uses a plain token comparison for webhook validation (X-Gitlab-Token), not HMAC like Gitea/GitHub
  • E2E webhook tests use the assertEventually pattern with a request-catcher container, consistent with the Gitea adapter tests
  • createPullRequest full test suite (along with getPullRequest, getPullRequestFiles, createComment etc.

@jaysomani jaysomani marked this pull request as ready for review April 24, 2026 09:43
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR adds createWebhook, getEvent, validateWebhookEvent, and createPullRequest to the GitLab adapter along with unit and E2E tests, completing the event-driven integration layer for GitLab.

  • Env-var mismatch: Base.php helper methods read TESTS_REQUEST_CATCHER_URL, but only TESTS_GITLAB_REQUEST_CATCHER_URL is defined in docker-compose.yml; helpers always fall back to the hardcoded default and explicit URL config is silently ignored.
  • SSL disabled unconditionally: createWebhook hardcodes enable_ssl_verification: false, skipping TLS certificate validation for every registered webhook regardless of environment.

Confidence Score: 4/5

Safe to merge after resolving the env-var mismatch and reviewing the SSL default

One P1 issue (env-var name mismatch means docker-compose config has no effect on tests) and two P2 issues (unconditional SSL bypass and silent 0 return) remain unaddressed

tests/VCS/Base.php (env-var rename) and src/VCS/Adapter/Git/GitLab.php (SSL and ID handling in createWebhook)

Important Files Changed

Filename Overview
src/VCS/Adapter/Git/GitLab.php Implements createWebhook, getEvent, validateWebhookEvent, and createPullRequest; SSL verification hardcoded to false and createWebhook silently returns 0 for a missing ID
tests/VCS/Base.php Helper env-var renamed to TESTS_REQUEST_CATCHER_URL but docker-compose.yml only defines TESTS_GITLAB_REQUEST_CATCHER_URL, so custom URL config is silently ignored
tests/VCS/Adapter/GitLabTest.php New unit and E2E tests for webhook methods; E2E tests do not call validateWebhookEvent to assert token delivery (noted in prior thread)
docker-compose.yml Adds TESTS_GITLAB_REQUEST_CATCHER_URL env var and enables local webhook requests via API; env var name diverges from what Base.php helpers now read

Reviews (3): Last reviewed commit: "updated with suggestions 1" | Re-trigger Greptile

Comment thread src/VCS/Adapter/Git/GitLab.php
Comment thread docker-compose.yml Outdated
Comment thread tests/VCS/Adapter/GitLabTest.php Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f8a0b54f18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

$payload = [
'url' => $url,
'token' => $secret,
'enable_ssl_verification' => false,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve TLS verification for GitLab webhooks

createWebhook() unconditionally sets enable_ssl_verification to false, which disables certificate validation for all HTTPS webhook deliveries. This introduces a production security regression (MITM-friendly delivery path) for any non-local webhook target; this should default to secure verification and only be disabled explicitly when needed.

Useful? React with 👍 / 👎.

Comment on lines +713 to +715
$commits = $payloadArray['commits'] ?? [];
$latestCommit = !empty($commits) ? $commits[0] : [];
$ref = $payloadArray['ref'] ?? '';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse push head commit instead of first commit entry

In getEvent('Push Hook', ...), selecting $commits[0] can return an older commit on multi-commit pushes, while commitHash is taken from checkout_sha (the pushed head). That creates inconsistent event data where hash, author, message, and URL can refer to different commits, which can mislead downstream automation and notifications.

Useful? React with 👍 / 👎.

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Comment thread tests/VCS/Adapter/GitLabTest.php
Comment thread tests/VCS/Base.php
protected function getLastWebhookRequest(): array
{
$catcherUrl = System::getEnv('TESTS_GITEA_REQUEST_CATCHER_URL', 'http://request-catcher:5000');
$catcherUrl = System::getEnv('TESTS_REQUEST_CATCHER_URL', 'http://request-catcher:5000');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Env-var name mismatch — defined config silently ignored

Base.php (both helper methods) now reads TESTS_REQUEST_CATCHER_URL, but docker-compose.yml only defines TESTS_GITLAB_REQUEST_CATCHER_URL (and the unchanged TESTS_GITEA_REQUEST_CATCHER_URL). No service sets TESTS_REQUEST_CATCHER_URL, so the helpers always fall back to the hardcoded default and any value set via TESTS_GITLAB_REQUEST_CATCHER_URL is silently ignored. Either add TESTS_REQUEST_CATCHER_URL to the tests service environment in docker-compose.yml, or revert to reading TESTS_GITLAB_REQUEST_CATCHER_URL for consistency with the per-adapter naming convention already used by Gitea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant