Refracto webhook
This commit is contained in:
parent
c87fb882b4
commit
44ac4deecf
@ -2,87 +2,58 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/hmac"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
hmacService "git.sebclem.fr/sebclem/renovate-manager/services/hmac"
|
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/gin-gonic/gin"
|
||||||
"github.com/sirupsen/logrus"
|
"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
|
r := c.Request
|
||||||
signature := r.Header.Get("X-Gitea-Signature")
|
signature := r.Header.Get("X-Gitea-Signature")
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatus(500)
|
c.AbortWithStatus(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedSignature := hmacService.CalculateHMAC("test", body)
|
if !hmacService.CompareSignature(body, signature, ctrl.WebhookSecret) {
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
if signature == "" || !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
|
|
||||||
logrus.Error("Signature missmatch, Abort !")
|
|
||||||
c.AbortWithStatus(401)
|
|
||||||
return
|
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))
|
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||||
|
|
||||||
switch r.Header.Get("X-Gitea-Event") {
|
switch r.Header.Get("X-Gitea-Event") {
|
||||||
case "push":
|
case "push":
|
||||||
logrus.Info("Received PUSH webhook")
|
logrus.Debug("Received PUSH webhook")
|
||||||
case "create":
|
|
||||||
logrus.Info("Received CREATE webhook")
|
|
||||||
case "delete":
|
|
||||||
logrus.Info("Received DELETE webhook")
|
|
||||||
case "issues":
|
|
||||||
logrus.Info("Received ISSUES webhook")
|
|
||||||
case "issue_comment":
|
case "issue_comment":
|
||||||
logrus.Info("Received ISSUE_COMMENT webhook")
|
logrus.Debug("Received ISSUE_COMMENT webhook")
|
||||||
case "pull_request":
|
var data giteaService.IssueComentWebhook
|
||||||
logrus.Info("Received PULL_REQUEST webhook")
|
|
||||||
var data PullRequestWebhook
|
|
||||||
if err := c.BindJSON(&data); err == nil {
|
if err := c.BindJSON(&data); err == nil {
|
||||||
logrus.Info("All good")
|
giteaService.HandleGiteaIssueComment(data, ctrl.RenovateUsername)
|
||||||
c.String(201, "")
|
c.String(201, "")
|
||||||
} else {
|
} else {
|
||||||
logrus.Error("Fail to parse json")
|
logrus.Error("Fail to parse json")
|
||||||
}
|
}
|
||||||
default:
|
case "pull_request":
|
||||||
logrus.Warn("Received UNKNOWN webhook")
|
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) {
|
func LoadWebhook(g *gin.RouterGroup) {
|
||||||
controller := new(controllers.WebhookController)
|
controller := controllers.WebhookController{WebhookSecret: "test", RenovateUsername: "renovate-bot"}
|
||||||
g.POST("gitea", controller.HandleGiteaWebhook)
|
g.POST("gitea", controller.HandleGiteaWebhook)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CalculateHMAC(secret string, message []byte) string {
|
func CalculateHMAC(secret string, message []byte) string {
|
||||||
@ -12,3 +14,13 @@ func CalculateHMAC(secret string, message []byte) string {
|
|||||||
h.Write(message)
|
h.Write(message)
|
||||||
return hex.EncodeToString(h.Sum(nil))
|
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