Repository navigation
Add webhook event parsing for GitHub, GitLab and Gitea/Forgejo - #184
Conversation
andrew
left a comment
There was a problem hiding this comment.
Thanks, this is a solid base. Three things before merge:
-
gitea/webhook_events.go: Gitea hooks can be configured to deliver with GET. Gitea then sends the JSON in apayloadquery parameter with no body, soParseWebhookcurrently fails withdecoding webhook payload: unexpected end of JSON input. Gitea signs that same JSON, so whenr.Method == http.MethodGettake the payload fromr.URL.Query().Get("payload")and verify it as usual. Please add a test for a signed GET delivery. -
README: the example passes
os.Getenv("WEBHOOK_SECRET")straight toParseEvent, so if that variable is unset in a deployment, verification is silently skipped and unsigned deliveries are accepted. Keep the empty-secret behaviour inParseEvent, but have the example read the secret up front and refuse to start when it's empty. -
gitlab/webhook_events.go: the parser only uses the standard library andhookutil, so it doesn't need the//go:build !tinygotag. Drop the tag, move thegitLabWebhookService.ParseEventmethod intogitlab/webhooks.go, have the TinyGoParseEventcallParseWebhook, and remove the stubParseWebhookfromgitlab/gitlab_tinygo.go. GitLab webhook parsing then works under TinyGo, and the tinygo CI job covers it.
|
Thanks, all three fixed.
|
Closes #50
Adds verification and parsing of incoming webhook deliveries into a normalized
WebhookEvent, so consumers can handle GitHub, GitLab and Gitea/Forgejo events without forge-specific code. It builds on the webhook management from #182 and uses the same event names.API
github,gitlabandgiteaalso exportParseWebhook(r, secret), which needs no API client. This matters for Gitea, wheregitea.Newcontacts the server on construction.A new
ErrInvalidWebhookSignatureis returned when a delivery's signature or token does not match, so handlers can answer 401.WebhookEvent
TypeWebhook.EventsActionDeliveryIDRepository,SenderPushpushandtag_push: ref, before/after, created/deleted, commitsPullRequestpull_requestplusissue_commenton a pull requestIssueissuesplusissue_commenton an issueCommentissue_commentReleasereleasePayloadThe typed fields reuse the existing
PullRequest,Issue,Comment,ReleaseandRepositorytypes and, on GitHub and Gitea, the existing converters.Verification
X-Hub-Signature-256over the raw body (X-Hub-Signatureaccepted as a fallback)X-Gitlab-Tokencompared to the secret in constant timeX-Forgejo-Signature/X-Gitea-Signatureover the JSON payloadpayloadquery parameter with no body. It is read from there and verified the same way.X-GitHub-*headers for compatibility, so the Gitea parser reads only its own headers, preferring Forgejo's.Event and action mapping
GitLab (
X-Gitlab-Event):Push Hook/Tag Push Hookpush/tag_pushMerge Request Hookpull_requestIssue Hook,Confidential Issue HookissuesNote Hookon an issue or merge requestissue_commentNote Hookon a commitcommit_commentRelease HookreleasePipeline Hook/Job Hookworkflow_run/workflow_jobDeployment Hook/Wiki Page Hookdeployment/gollumGitLab actions map to GitHub's:
open→opened,close→closed,reopen→reopened,update→edited(orsynchronizewhen the update brings new commits),merge→closedwithMergedset. Releasecreate→published, since GitLab releases are public once created. Actions with no equivalent, such asapproved, are kept as sent.Gitea / Forgejo: the event header already groups sub-events (
issue_labelarrives asissues).wiki→gollumand the review events (pull_request_approved,pull_request_rejected,pull_request_comment) →pull_request_review. Actionssynchronized→synchronizeandupdated→edited.GitHub names and actions are used as is.
Backend support
ErrNotSupported, but webhook parsing worksErrNotSupportedNotes for review
ParseEventtoWebhookServicechanges an interface that landed in Add webhook management service #182. Happy to move it to a separate optional interface instead if you prefer.author_id, soAuthoris empty there. The acting user is inSender.internal/hookutilto keep the public API small.Tests
payloadparameter rejected. Also checks that Forgejo headers take precedence.synchronizeandmerge, fork detection and every note target.internal/hookutilunit tests, plusParseEventcoverage for Bitbucket.go test -race ./...,go test -tags=tinygo ./gitlab, the js/wasip1 WebAssembly builds andgolangci-lintv2.14.0 all pass locally.