Refracto webhook
This commit is contained in:
parent
c87fb882b4
commit
44ac4deecf
@ -2,87 +2,58 @@ package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
hmacService "git.sebclem.fr/sebclem/renovate-manager/services/hmac"
|
||||
giteaService "git.sebclem.fr/sebclem/renovate-manager/services/webhook/gitea"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type WebhookController struct{}
|
||||
type WebhookController struct {
|
||||
WebhookSecret string
|
||||
RenovateUsername string
|
||||
}
|
||||
|
||||
func (ctl WebhookController) HandleGiteaWebhook(c *gin.Context) {
|
||||
func (ctrl WebhookController) HandleGiteaWebhook(c *gin.Context) {
|
||||
r := c.Request
|
||||
signature := r.Header.Get("X-Gitea-Signature")
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(500)
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
expectedSignature := hmacService.CalculateHMAC("test", body)
|
||||
|
||||
if signature == "" || !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
|
||||
logrus.Error("Signature missmatch, Abort !")
|
||||
c.AbortWithStatus(401)
|
||||
if !hmacService.CompareSignature(body, signature, ctrl.WebhookSecret) {
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Reset the request body so it can be Bind to json
|
||||
// Reset the request body so it can be read again by BindJSON
|
||||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
|
||||
switch r.Header.Get("X-Gitea-Event") {
|
||||
case "push":
|
||||
logrus.Info("Received PUSH webhook")
|
||||
case "create":
|
||||
logrus.Info("Received CREATE webhook")
|
||||
case "delete":
|
||||
logrus.Info("Received DELETE webhook")
|
||||
case "issues":
|
||||
logrus.Info("Received ISSUES webhook")
|
||||
logrus.Debug("Received PUSH webhook")
|
||||
case "issue_comment":
|
||||
logrus.Info("Received ISSUE_COMMENT webhook")
|
||||
case "pull_request":
|
||||
logrus.Info("Received PULL_REQUEST webhook")
|
||||
var data PullRequestWebhook
|
||||
logrus.Debug("Received ISSUE_COMMENT webhook")
|
||||
var data giteaService.IssueComentWebhook
|
||||
if err := c.BindJSON(&data); err == nil {
|
||||
logrus.Info("All good")
|
||||
giteaService.HandleGiteaIssueComment(data, ctrl.RenovateUsername)
|
||||
c.String(201, "")
|
||||
} else {
|
||||
logrus.Error("Fail to parse json")
|
||||
}
|
||||
default:
|
||||
logrus.Warn("Received UNKNOWN webhook")
|
||||
case "pull_request":
|
||||
logrus.Debug("Received PULL_REQUEST webhook")
|
||||
var data giteaService.PullRequestWebhook
|
||||
if err := c.BindJSON(&data); err == nil {
|
||||
giteaService.HandleGiteaPullRequest(data, ctrl.RenovateUsername)
|
||||
c.String(201, "")
|
||||
} else {
|
||||
logrus.Error("Fail to parse json")
|
||||
}
|
||||
// ctx.String(201, "")
|
||||
}
|
||||
|
||||
type PullRequestWebhook struct {
|
||||
Action string `json:"action"`
|
||||
Number int `json:"number"`
|
||||
PullRequest PullRequest `json:"pull_request"`
|
||||
Repository Repository `json:"repository"`
|
||||
Sender User `json:"sender"`
|
||||
}
|
||||
|
||||
type PullRequest struct {
|
||||
Id int `json:"id"`
|
||||
Url string `json:"url"`
|
||||
Number uint64 `json:"number"`
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Id int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Id int `json:"id"`
|
||||
Owner User `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
}
|
||||
|
@ -6,6 +6,6 @@ import (
|
||||
)
|
||||
|
||||
func LoadWebhook(g *gin.RouterGroup) {
|
||||
controller := new(controllers.WebhookController)
|
||||
controller := controllers.WebhookController{WebhookSecret: "test", RenovateUsername: "renovate-bot"}
|
||||
g.POST("gitea", controller.HandleGiteaWebhook)
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func CalculateHMAC(secret string, message []byte) string {
|
||||
@ -12,3 +14,13 @@ func CalculateHMAC(secret string, message []byte) string {
|
||||
h.Write(message)
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func CompareSignature(body []byte, signature string, secret string) bool {
|
||||
expectedSignature := CalculateHMAC(secret, body)
|
||||
|
||||
if signature == "" || !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
|
||||
logrus.Error("Signature missmatch, Abort !")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
82
src/backend/services/webhook/gitea/gitea.go
Normal file
82
src/backend/services/webhook/gitea/gitea.go
Normal file
@ -0,0 +1,82 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func HandleGiteaPullRequest(data PullRequestWebhook, renovateUsername string) {
|
||||
if !isFromRenovate(data.Sender, renovateUsername) {
|
||||
if isEditOnRenovatePR(data, renovateUsername) {
|
||||
logrus.Info("Edit on renovate PR, launch renovate")
|
||||
logrus.Info("Repo: ", data.Repository.FullName, " PR: ", data.Number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func HandleGiteaIssueComment(data IssueComentWebhook, renovateUsername string) {
|
||||
if !isFromRenovate(data.Sender, renovateUsername) {
|
||||
if strings.Contains(data.Comment.Body, "@"+renovateUsername) {
|
||||
logrus.Info("Mention in comment, launch renovate")
|
||||
logrus.Info("Repo: ", data.Repository.FullName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isFromRenovate(sender User, renovateUsername string) bool {
|
||||
return sender.Username == renovateUsername
|
||||
}
|
||||
|
||||
func isRenovatePR(data PullRequest, renovateUsername string) bool {
|
||||
return data.User.Username == renovateUsername
|
||||
}
|
||||
|
||||
func isEditOnRenovatePR(data PullRequestWebhook, renovateUsername string) bool {
|
||||
if data.Action == "edited" {
|
||||
return isRenovatePR(data.PullRequest, renovateUsername)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PullRequestWebhook struct {
|
||||
Action string `json:"action"`
|
||||
Number int `json:"number"`
|
||||
PullRequest PullRequest `json:"pull_request"`
|
||||
Repository Repository `json:"repository"`
|
||||
Sender User `json:"sender"`
|
||||
}
|
||||
|
||||
type IssueComentWebhook struct {
|
||||
Action string `json:"action"`
|
||||
Comment Comment `json:"comment"`
|
||||
Repository Repository `json:"repository"`
|
||||
Sender User `json:"sender"`
|
||||
IsPull bool `json:"is_pull"`
|
||||
}
|
||||
|
||||
type PullRequest struct {
|
||||
Id int `json:"id"`
|
||||
Url string `json:"url"`
|
||||
Number uint64 `json:"number"`
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
Id int `json:"id"`
|
||||
User User `json:"user"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Id int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Id int `json:"id"`
|
||||
Owner User `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
}
|
Loading…
Reference in New Issue
Block a user