2024-02-11 08:56:32 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"code.gitea.io/gitea/modules/structs"
|
|
|
|
"encoding/json"
|
|
|
|
"git.lumeweb.com/LumeWeb/gitea-github-proxy/config"
|
|
|
|
"git.lumeweb.com/LumeWeb/gitea-github-proxy/db/model"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
type WebhookManager struct {
|
|
|
|
config *config.Config
|
|
|
|
db *gorm.DB
|
|
|
|
logger *zap.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
type IncomingWebhookData struct {
|
|
|
|
Headers http.Header
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewWebhookManager(cfg *config.Config, db *gorm.DB, logger *zap.Logger) *WebhookManager {
|
|
|
|
return &WebhookManager{config: cfg, db: db, logger: logger}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (whm *WebhookManager) HandlePullRequest(request *structs.PullRequestPayload, r *http.Request) {
|
2024-02-11 09:42:01 +00:00
|
|
|
ghEvent := convertPullRequestEvent(request)
|
|
|
|
githubAction := translatePrAction(request.Action)
|
2024-02-11 08:56:32 +00:00
|
|
|
r.Header.Set("X-GitHub-Event", githubAction)
|
|
|
|
|
|
|
|
whm.sendWebhooks(ghEvent, r)
|
|
|
|
}
|
|
|
|
func (whm *WebhookManager) sendWebhooks(request interface{}, r *http.Request) {
|
|
|
|
var apps []model.Apps
|
|
|
|
result := whm.db.Find(&apps)
|
|
|
|
if result.Error != nil {
|
|
|
|
whm.logger.Error("Failed to query apps", zap.Error(result.Error))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, app := range apps {
|
|
|
|
go func(app model.Apps) {
|
|
|
|
payloadBytes, err := json.Marshal(request)
|
|
|
|
if err != nil {
|
|
|
|
whm.logger.Error("Failed to marshal payload", zap.Error(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequest("POST", app.WebhookUrl, bytes.NewBuffer(payloadBytes))
|
|
|
|
if err != nil {
|
|
|
|
whm.logger.Error("Failed to create request", zap.Error(err), zap.String("url", app.WebhookUrl))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
|
|
|
|
for key, values := range r.Header {
|
|
|
|
for _, value := range values {
|
|
|
|
req.Header.Add(key, value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
payload := getWebhookData(r, whm.logger)
|
|
|
|
signature := generatePayloadSignature(payload, app.WebhookSecret)
|
|
|
|
req.Header.Add("X-Hub-Signature-256", signature)
|
|
|
|
|
|
|
|
client := &http.Client{}
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
whm.logger.Error("Failed to send webhook", zap.Error(err), zap.String("url", app.WebhookUrl))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer func(Body io.ReadCloser) {
|
|
|
|
err := Body.Close()
|
|
|
|
if err != nil {
|
|
|
|
whm.logger.Error("Failed to close response body", zap.Error(err))
|
|
|
|
}
|
|
|
|
}(resp.Body)
|
|
|
|
|
|
|
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
|
|
whm.logger.Info("Webhook sent successfully", zap.String("url", app.WebhookUrl))
|
|
|
|
} else {
|
|
|
|
whm.logger.Error("Webhook failed", zap.String("url", app.WebhookUrl), zap.Int("status", resp.StatusCode))
|
|
|
|
}
|
|
|
|
}(app)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|