diff --git a/go.mod b/go.mod index 2f1864f..62a80bf 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,9 @@ module gitea-sonarqube-pr-bot go 1.16 require ( - github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect - github.com/coreos/etcd v3.3.10+incompatible // indirect - github.com/coreos/go-etcd v2.0.0+incompatible // indirect - github.com/gorilla/mux v1.8.0 // indirect - github.com/spf13/viper v1.8.0 // indirect - github.com/stretchr/testify v1.7.0 // indirect - github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 // indirect - github.com/urfave/cli/v2 v2.3.0 // indirect - github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 // indirect + code.gitea.io/sdk/gitea v0.14.1 + github.com/gorilla/mux v1.8.0 + github.com/spf13/viper v1.8.0 + github.com/stretchr/testify v1.7.0 + github.com/urfave/cli/v2 v2.3.0 ) diff --git a/go.sum b/go.sum index df5b50f..f96408f 100644 --- a/go.sum +++ b/go.sum @@ -36,12 +36,13 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.gitea.io/sdk/gitea v0.14.1 h1:NaRluse+dAxVM5RmHC7Xktfas5a8WWmcnUBlJLhJycA= +code.gitea.io/sdk/gitea v0.14.1/go.mod h1:89WiyOX1KEcvjP66sRHdu0RafojGo60bT9UqW17VbWs= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -54,8 +55,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= @@ -140,6 +139,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -156,6 +156,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -170,12 +172,15 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -211,7 +216,9 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= @@ -234,10 +241,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -569,6 +574,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= diff --git a/internal/gitea_sdk/gitea_sdk.go b/internal/gitea_sdk/gitea_sdk.go new file mode 100644 index 0000000..0daac70 --- /dev/null +++ b/internal/gitea_sdk/gitea_sdk.go @@ -0,0 +1,36 @@ +package gitea_sdk + +import ( + "fmt" + "log" + "gitea-sonarqube-pr-bot/internal/settings" + "code.gitea.io/sdk/gitea" +) + +type GiteaSdkInterface interface { + PostComment(settings.GiteaRepository, int, string) error +} + +type GiteaSdk struct { + client *gitea.Client +} + +func (sdk *GiteaSdk) PostComment(repo settings.GiteaRepository, idx int, msg string) error { + opt := gitea.CreateIssueCommentOption{ + Body: msg, + } + + log.Printf("Owner: %s | Repo: %s | Index: %d | Options: %s", repo.Owner, repo.Name, idx, opt) + _, _, err := sdk.client.CreateIssueComment(repo.Owner, repo.Name, int64(idx), opt) + + return err +} + +func New() *GiteaSdk { + client, err := gitea.NewClient(settings.Gitea.Url, gitea.SetToken(settings.Gitea.Token.Value)) + if err != nil { + panic(fmt.Errorf("Cannot initialize Gitea client: %w", err)) + } + + return &GiteaSdk{client} +} diff --git a/internal/settings/settings.go b/internal/settings/settings.go index 13f5eab..7005fd6 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/viper" ) -type giteaRepository struct { +type GiteaRepository struct { Owner string Name string } @@ -28,7 +28,7 @@ type Project struct { SonarQube struct { Key string } `mapstructure:"sonarqube"` - Gitea giteaRepository + Gitea GiteaRepository } var ( diff --git a/internal/settings/settings_test.go b/internal/settings/settings_test.go index 14f2154..fa67a9d 100644 --- a/internal/settings/settings_test.go +++ b/internal/settings/settings_test.go @@ -216,7 +216,7 @@ func TestLoadProjectsStructure(t *testing.T) { SonarQube: struct {Key string}{ Key: "gitea-sonarqube-pr-bot", }, - Gitea: giteaRepository{ + Gitea: GiteaRepository{ Owner: "example-organization", Name: "pr-bot", }, diff --git a/internal/webhook_handler/main.go b/internal/webhook_handler/main.go index 016d12a..9f09067 100644 --- a/internal/webhook_handler/main.go +++ b/internal/webhook_handler/main.go @@ -10,6 +10,7 @@ import ( "os/signal" "time" + sdk "gitea-sonarqube-pr-bot/internal/gitea_sdk" "github.com/gorilla/mux" "github.com/urfave/cli/v2" ) @@ -22,7 +23,7 @@ func Serve(c *cli.Context) error { flag.Parse() r := mux.NewRouter() - r.HandleFunc("/hooks/sonarqube", NewSonarQubeWebhookHandler().Handle).Methods("POST").Headers("X-SonarQube-Project", "") + r.HandleFunc("/hooks/sonarqube", NewSonarQubeWebhookHandler(sdk.New()).Handle).Methods("POST").Headers("X-SonarQube-Project", "") srv := &http.Server{ Addr: "0.0.0.0:8080", diff --git a/internal/webhook_handler/sonarqube.go b/internal/webhook_handler/sonarqube.go index 06b56c7..8996ed5 100644 --- a/internal/webhook_handler/sonarqube.go +++ b/internal/webhook_handler/sonarqube.go @@ -9,36 +9,55 @@ import ( "strings" "gitea-sonarqube-pr-bot/internal/settings" + sdk "gitea-sonarqube-pr-bot/internal/gitea_sdk" webhook "gitea-sonarqube-pr-bot/internal/webhooks/sonarqube" ) type SonarQubeWebhookHandler struct { fetchDetails func(w *webhook.Webhook) + giteaSdk sdk.GiteaSdkInterface } -func (_ *SonarQubeWebhookHandler) inProjectsMapping(p []settings.Project, n string) bool { - for _, proj := range p { +func (h *SonarQubeWebhookHandler) composeGiteaComment(w *webhook.Webhook) string { + return fmt.Sprintf("Hello from pr-bot. SonarQube data for '%s' has been processed.", w.Project.Key) +} + +func (_ *SonarQubeWebhookHandler) inProjectsMapping(p []settings.Project, n string) (bool, int) { + for idx, proj := range p { if proj.SonarQube.Key == n { - return true + return true, idx } } - return false + return false, 0 +} + +func (h *SonarQubeWebhookHandler) processData(w *webhook.Webhook, repo settings.GiteaRepository) { + if strings.ToLower(w.Branch.Type) != "pull_request" { + log.Println("Ignore Hook for non-PR") + return + } + + h.fetchDetails(w) + + comment := h.composeGiteaComment(w) + h.giteaSdk.PostComment(repo, w.PRIndex, comment) } func (h *SonarQubeWebhookHandler) Handle(rw http.ResponseWriter, r *http.Request) { rw.Header().Set("Content-Type", "application/json") - project := r.Header.Get("X-SonarQube-Project") - if !h.inProjectsMapping(settings.Projects, project) { - log.Printf("Received hook for project '%s' which is not configured. Request ignored.", project) + projectName := r.Header.Get("X-SonarQube-Project") + found, pIdx := h.inProjectsMapping(settings.Projects, projectName) + if !found { + log.Printf("Received hook for project '%s' which is not configured. Request ignored.", projectName) rw.WriteHeader(http.StatusOK) - io.WriteString(rw, fmt.Sprintf(`{"message": "Project '%s' not in configured list. Request ignored."}`, project)) + io.WriteString(rw, fmt.Sprintf(`{"message": "Project '%s' not in configured list. Request ignored."}`, projectName)) return } - log.Printf("Received hook for project '%s'. Processing data.", project) + log.Printf("Received hook for project '%s'. Processing data.", projectName) raw, err := ioutil.ReadAll(r.Body) defer r.Body.Close() @@ -60,24 +79,13 @@ func (h *SonarQubeWebhookHandler) Handle(rw http.ResponseWriter, r *http.Request rw.WriteHeader(http.StatusOK) io.WriteString(rw, `{"message": "Processing data. See bot logs for details."}`) - if strings.ToLower(w.Branch.Type) != "pull_request" { - log.Print("Ignore Hook for non-PR") - return - } - - h.fetchDetails(w) - if idx, err1 := w.GetPRIndex(); err1 == nil { - log.Printf("New details for Gitea PR %d", idx) - } + h.processData(w, settings.Projects[pIdx].Gitea) } - func fetchDetails(w *webhook.Webhook) { - log.Printf("Hello from the original one: %s", w) + log.Printf("This method will load additional data from SonarQube based on PR %d", w.PRIndex) } -func NewSonarQubeWebhookHandler() *SonarQubeWebhookHandler { - return &SonarQubeWebhookHandler{ - fetchDetails: fetchDetails, - } +func NewSonarQubeWebhookHandler(giteaSdk sdk.GiteaSdkInterface) *SonarQubeWebhookHandler { + return &SonarQubeWebhookHandler{fetchDetails, giteaSdk} } diff --git a/internal/webhook_handler/sonarqube_test.go b/internal/webhook_handler/sonarqube_test.go index 42bb915..c79d76b 100644 --- a/internal/webhook_handler/sonarqube_test.go +++ b/internal/webhook_handler/sonarqube_test.go @@ -20,6 +20,14 @@ func (h *HandlerPartialMock) fetchDetails(w *webhook.Webhook) { h.Called(w) } +type GiteaSdkMock struct { + mock.Mock +} + +func (h *GiteaSdkMock) PostComment(_ settings.GiteaRepository, _ int, _ string) error { + return nil +} + func defaultMockPreparation(h *HandlerPartialMock) { h.On("fetchDetails", mock.Anything).Return(nil) } @@ -28,7 +36,7 @@ func withValidRequestData(t *testing.T, mockPreparation func(*HandlerPartialMock partialMock := new(HandlerPartialMock) mockPreparation(partialMock) - webhookHandler := NewSonarQubeWebhookHandler() + webhookHandler := NewSonarQubeWebhookHandler(new(GiteaSdkMock)) webhookHandler.fetchDetails = partialMock.fetchDetails req, err := http.NewRequest("POST", "/hooks/sonarqube", bytes.NewBuffer(jsonBody)) diff --git a/internal/webhooks/sonarqube/webhook.go b/internal/webhooks/sonarqube/webhook.go index 3dee3e4..5dd0cc9 100644 --- a/internal/webhooks/sonarqube/webhook.go +++ b/internal/webhooks/sonarqube/webhook.go @@ -13,6 +13,11 @@ import ( type Webhook struct { ServerUrl string `mapstructure:"serverUrl"` Revision string + Project struct { + Key string + Name string + Url string + } Branch struct { Name string Type string @@ -25,16 +30,7 @@ type Webhook struct { Status string } } `mapstructure:"qualityGate"` -} - -func (w *Webhook) GetPRIndex() (int, error) { - re := regexp.MustCompile(`^PR-(\d+)$`) - res := re.FindSubmatch([]byte(w.Branch.Name)) - if len(res) != 2 { - return 0, fmt.Errorf("Branch name '%s' does not match regex '%s'. Extracting PR index not possible.", w.Branch.Name, re.String()) - } - - return strconv.Atoi(fmt.Sprintf("%s", res[1])) + PRIndex int } func New(raw []byte) (*Webhook, bool) { @@ -50,5 +46,23 @@ func New(raw []byte) (*Webhook, bool) { return w, false } + idx, err1 := parsePRIndex(w) + if err1 != nil { + log.Printf("Error parsing PR index: %s", err1.Error()) + return w, false + } + + w.PRIndex = idx + return w, true } + +func parsePRIndex(w *Webhook) (int, error) { + re := regexp.MustCompile(`^PR-(\d+)$`) + res := re.FindSubmatch([]byte(w.Branch.Name)) + if len(res) != 2 { + return 0, fmt.Errorf("Branch name '%s' does not match regex '%s'.", w.Branch.Name, re.String()) + } + + return strconv.Atoi(fmt.Sprintf("%s", res[1])) +} diff --git a/internal/webhooks/sonarqube/webhook_test.go b/internal/webhooks/sonarqube/webhook_test.go index ef31b8f..941e48f 100644 --- a/internal/webhooks/sonarqube/webhook_test.go +++ b/internal/webhooks/sonarqube/webhook_test.go @@ -11,6 +11,7 @@ func TestNewWebhook(t *testing.T) { response, ok := New(raw) assert.NotNil(t, response) + assert.Equal(t, 1337, response.PRIndex) assert.True(t, ok) } @@ -21,22 +22,9 @@ func TestNewWebhookInvalidJSON(t *testing.T) { assert.False(t, ok) } -func TestGetPRIndex(t *testing.T) { - raw := []byte(`{ "serverUrl": "https://example.com/sonarqube", "taskId": "AXouyxDpizdp4B1K", "status": "SUCCESS", "analysedAt": "2021-05-21T12:12:07+0000", "revision": "f84442009c09b1adc278b6aa80a3853419f54007", "changedAt": "2021-05-21T12:12:07+0000", "project": { "key": "pr-bot", "name": "PR Bot", "url": "https://example.com/sonarqube/dashboard?id=pr-bot" }, "branch": { "name": "PR-1337", "type": "PULL_REQUEST", "isMain": false, "url": "https://example.com/sonarqube/dashboard?id=pr-bot&pullRequest=PR-1337" }, "qualityGate": { "name": "PR Bot", "status": "OK", "conditions": [ { "metric": "new_reliability_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_security_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_maintainability_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_security_hotspots_reviewed", "operator": "LESS_THAN", "status": "NO_VALUE", "errorThreshold": "100" } ] }, "properties": {} }`) - w, _ := New(raw) - - idx, err := w.GetPRIndex() - - assert.Equal(t, 1337, idx) - assert.Nil(t, err) -} - -func TestGetPRIndexInvalidBranchName(t *testing.T) { +func TestNewWebhookInvalidBranchName(t *testing.T) { raw := []byte(`{ "serverUrl": "https://example.com/sonarqube", "taskId": "AXouyxDpizdp4B1K", "status": "SUCCESS", "analysedAt": "2021-05-21T12:12:07+0000", "revision": "f84442009c09b1adc278b6aa80a3853419f54007", "changedAt": "2021-05-21T12:12:07+0000", "project": { "key": "pr-bot", "name": "PR Bot", "url": "https://example.com/sonarqube/dashboard?id=pr-bot" }, "branch": { "name": "invalid", "type": "PULL_REQUEST", "isMain": false, "url": "https://example.com/sonarqube/dashboard?id=pr-bot&pullRequest=PR-1337" }, "qualityGate": { "name": "PR Bot", "status": "OK", "conditions": [ { "metric": "new_reliability_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_security_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_maintainability_rating", "operator": "GREATER_THAN", "value": "1", "status": "OK", "errorThreshold": "1" }, { "metric": "new_security_hotspots_reviewed", "operator": "LESS_THAN", "status": "NO_VALUE", "errorThreshold": "100" } ] }, "properties": {} }`) - w, _ := New(raw) + _, ok := New(raw) - idx, err := w.GetPRIndex() - - assert.Equal(t, 0, idx) - assert.NotNil(t, err) + assert.False(t, ok) }