feat: add GitHub and GitLab webhook support #170
Reference in New Issue
Block a user
Delete Branch "feature/github-gitlab-webhook-support"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds GitHub and GitLab push webhook support alongside the existing Gitea support.
closes #68
What Changed
Auto-detection of webhook source
The webhook handler now auto-detects which platform sent the webhook by examining HTTP headers:
X-Gitea-EventX-GitHub-EventX-Gitlab-EventExisting Gitea webhooks continue to work unchanged. Unknown sources fall back to Gitea format for backward compatibility.
Normalized push event
All three payload formats are parsed into a unified
PushEventstruct containing:New files
internal/service/webhook/payloads.go: Source-specific payload structs (GiteaPushPayload,GitHubPushPayload,GitLabPushPayload),ParsePushPayload()dispatcher, per-platform parsers, branch extraction, and commit URL extraction functions.Modified files
internal/service/webhook/types.go: AddedSourcetype (gitea/github/gitlab/unknown),DetectWebhookSource(),DetectEventType(), andPushEventnormalized type. MovedGiteaPushPayloadto payloads.go.internal/service/webhook/webhook.go:HandleWebhooknow accepts aSourceparameter and usesParsePushPayload()for unified parsing instead of directly unmarshaling Gitea payloads.internal/handlers/webhook.go: CallsDetectWebhookSource()andDetectEventType()to auto-detect the platform before delegating to the webhook service.internal/service/webhook/webhook_test.go: Comprehensive tests for source detection, event type extraction, payload parsing (all 3 platforms), commit URL fallback paths, and integration tests throughHandleWebhookfor GitHub and GitLab sources.README.md: Updated description, features, non-goals, and architecture to reflect multi-platform webhook support.Test coverage
Webhook package: 96.9% statement coverage. Tests cover:
DetectWebhookSourcewith all header combinations and precedenceDetectEventTypefor each platformParsePushPayloadfor Gitea, GitHub, GitLab, unknown source, invalid JSON, empty payloadsHandleWebhookintegration tests with GitHub and GitLab sourcesCode Review: PR #170 — GitHub and GitLab webhook support
Policy Compliance Check
go.mod/go.sumunchanged. All Docker base images in Dockerfile remain pinned by SHA256..golangci.yml,Makefile,Dockerfile,.gitea/workflows/— zero changes.nolintcomments justified//nolint:tagliatelleon payload structs (JSON field names match external API snake_case — standard justification, consistent with existingGiteaPushPayloadpattern).//nolint:funlenon table-driven tests — consistent with pre-existing pattern.example.comdomains.Requirements Checklist (Issue #68)
GitHubPushPayloadstruct +parseGitHubPush()inpayloads.goGitLabPushPayloadstruct +parseGitLabPush()inpayloads.goDetectWebhookSource()intypes.go— checksX-Gitea-Event,X-GitHub-Event,X-Gitlab-Eventwith defined precedenceextractBranch()inpayloads.go, applied uniformly across all three parsersTest Coverage Check
All new exported types and functions have tests:
Sourcetype + constantsTestWebhookSourceStringDetectWebhookSource()TestDetectWebhookSource(7 cases: each platform, unknown, empty, precedence)DetectEventType()TestDetectEventType(5 cases: each platform, unknown, missing header)ParsePushPayload()TestParsePushPayloadGitea,TestParsePushPayloadGitHub,TestParsePushPayloadGitLab,TestParsePushPayloadUnknownFallsBackToGitea,TestParsePushPayloadInvalidJSON,TestParsePushPayloadEmptyPayloadPushEventstructTestPushEventConstructionGiteaPushPayloadTestGiteaPushPayloadParsingGitHubPushPayloadTestGitHubPushPayloadParsingGitLabPushPayloadTestGitLabPushPayloadParsingTestGitHubCommitURLFallback(3 paths),TestGitLabCommitURLFallback(2 paths)TestHandleWebhookGitHubSource,TestHandleWebhookGitLabSource— full end-to-end through service layerClaimed 96.9% statement coverage for the webhook package.
Code Quality Assessment
types.go, payload parsing inpayloads.go, service logic inwebhook.go. Handler inhandlers/webhook.godoes detection, delegates to service.PushEvent{Source: source}, allowing webhook events to still be recorded (graceful degradation, consistent with existing Gitea behavior).SourceUnknownfalls back to Gitea format — existing integrations sending webhooks without recognized headers continue working.Build Result
Verdict: ✅ PASS
Clean, well-structured implementation that meets all requirements from issue #68, follows all repo policies, and has comprehensive test coverage. No policy violations found.