138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
package webhook
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// EventHandler processes webhook events
|
|
type EventHandler interface {
|
|
HandlePullRequest(event *PullRequestEvent)
|
|
HandlePullRequestReview(event *PullRequestReviewEvent)
|
|
HandlePullRequestComment(event *PullRequestCommentEvent)
|
|
HandleIssue(event *IssueEvent)
|
|
HandleIssueComment(event *IssueCommentEvent)
|
|
}
|
|
|
|
// Handler handles incoming Gitea webhooks
|
|
type Handler struct {
|
|
validator *Validator
|
|
eventHandler EventHandler
|
|
logger zerolog.Logger
|
|
}
|
|
|
|
// NewHandler creates a new webhook handler
|
|
func NewHandler(secret string, eventHandler EventHandler, logger zerolog.Logger) *Handler {
|
|
return &Handler{
|
|
validator: NewValidator(secret),
|
|
eventHandler: eventHandler,
|
|
logger: logger.With().Str("component", "webhook").Logger(),
|
|
}
|
|
}
|
|
|
|
// ServeHTTP handles the webhook HTTP request
|
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
// Only accept POST requests
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
// Get event metadata
|
|
eventType := GetEventType(r)
|
|
deliveryID := GetDeliveryID(r)
|
|
|
|
logger := h.logger.With().
|
|
Str("delivery_id", deliveryID).
|
|
Str("event_type", string(eventType)).
|
|
Logger()
|
|
|
|
// Validate signature and read body
|
|
body, err := h.validator.ValidateRequest(r)
|
|
if err != nil {
|
|
logger.Warn().Err(err).Msg("webhook validation failed")
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Respond immediately with 200 OK
|
|
// Process the event asynchronously
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"status":"accepted"}`))
|
|
|
|
// Process the event in a goroutine
|
|
go h.processEvent(logger, eventType, body)
|
|
}
|
|
|
|
// processEvent parses and routes the event to the appropriate handler
|
|
func (h *Handler) processEvent(logger zerolog.Logger, eventType GiteaEventType, body []byte) {
|
|
var err error
|
|
|
|
switch eventType {
|
|
case EventPullRequest:
|
|
var event PullRequestEvent
|
|
if err = json.Unmarshal(body, &event); err == nil {
|
|
logger.Info().
|
|
Str("action", event.Action).
|
|
Int64("pr_number", event.Number).
|
|
Str("repo", event.Repository.FullName).
|
|
Msg("processing pull request event")
|
|
h.eventHandler.HandlePullRequest(&event)
|
|
}
|
|
|
|
case EventPullRequestReview:
|
|
var event PullRequestReviewEvent
|
|
if err = json.Unmarshal(body, &event); err == nil {
|
|
logger.Info().
|
|
Str("action", event.Action).
|
|
Str("review_state", event.Review.State).
|
|
Str("repo", event.Repository.FullName).
|
|
Msg("processing pull request review event")
|
|
h.eventHandler.HandlePullRequestReview(&event)
|
|
}
|
|
|
|
case EventPullRequestComment:
|
|
var event PullRequestCommentEvent
|
|
if err = json.Unmarshal(body, &event); err == nil {
|
|
logger.Info().
|
|
Str("action", event.Action).
|
|
Int64("pr_number", event.PullRequest.Number).
|
|
Str("repo", event.Repository.FullName).
|
|
Msg("processing pull request comment event")
|
|
h.eventHandler.HandlePullRequestComment(&event)
|
|
}
|
|
|
|
case EventIssues:
|
|
var event IssueEvent
|
|
if err = json.Unmarshal(body, &event); err == nil {
|
|
logger.Info().
|
|
Str("action", event.Action).
|
|
Int64("issue_number", event.Issue.Number).
|
|
Str("repo", event.Repository.FullName).
|
|
Msg("processing issue event")
|
|
h.eventHandler.HandleIssue(&event)
|
|
}
|
|
|
|
case EventIssueComment:
|
|
var event IssueCommentEvent
|
|
if err = json.Unmarshal(body, &event); err == nil {
|
|
logger.Info().
|
|
Str("action", event.Action).
|
|
Int64("issue_number", event.Issue.Number).
|
|
Str("repo", event.Repository.FullName).
|
|
Msg("processing issue comment event")
|
|
h.eventHandler.HandleIssueComment(&event)
|
|
}
|
|
|
|
default:
|
|
logger.Debug().Msg("ignoring unknown event type")
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Error().Err(err).Msg("failed to parse event payload")
|
|
}
|
|
}
|