Fetch actual quality gate status on bot comment
Signed-off-by: Steven Kriegler <61625851+justusbunsi@users.noreply.github.com>
This commit is contained in:
parent
895dfe92e0
commit
369edfcfae
|
@ -47,6 +47,14 @@ func (h *SQSdkMock) GetMeasures(project string, branch string) (*sqSdk.MeasuresR
|
|||
return &sqSdk.MeasuresResponse{}, nil
|
||||
}
|
||||
|
||||
func (h *SQSdkMock) GetPullRequestUrl(project string, index int64) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (h *SQSdkMock) GetPullRequest(project string, index int64) (*sqSdk.PullRequest, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func defaultMockPreparation(h *HandlerPartialMock) {
|
||||
h.On("fetchDetails", mock.Anything).Return(nil)
|
||||
}
|
||||
|
|
21
internal/clients/sonarqube/pulls.go
Normal file
21
internal/clients/sonarqube/pulls.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package sonarqube
|
||||
|
||||
type PullRequest struct {
|
||||
Key string `json:"key"`
|
||||
Status struct {
|
||||
QualityGateStatus string `json:"qualityGateStatus"`
|
||||
} `json:"status"`
|
||||
}
|
||||
|
||||
type PullsResponse struct {
|
||||
PullRequests []PullRequest `json:"pullRequests"`
|
||||
}
|
||||
|
||||
func (r *PullsResponse) GetPullRequest(name string) *PullRequest {
|
||||
for _, pr := range r.PullRequests {
|
||||
if pr.Key == name {
|
||||
return &pr
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -5,13 +5,32 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"gitea-sonarqube-pr-bot/internal/settings"
|
||||
)
|
||||
|
||||
func ParsePRIndex(name string) (int, error) {
|
||||
re := regexp.MustCompile(`^PR-(\d+)$`)
|
||||
res := re.FindSubmatch([]byte(name))
|
||||
if len(res) != 2 {
|
||||
return 0, fmt.Errorf("branch name '%s' does not match regex '%s'", name, re.String())
|
||||
}
|
||||
|
||||
return strconv.Atoi(string(res[1]))
|
||||
}
|
||||
|
||||
func PRNameFromIndex(index int64) string {
|
||||
return fmt.Sprintf("PR-%d", index)
|
||||
}
|
||||
|
||||
type SonarQubeSdkInterface interface {
|
||||
GetMeasures(string, string) (*MeasuresResponse, error)
|
||||
GetPullRequestUrl(string, int64) string
|
||||
GetPullRequest(string, int64) (*PullRequest, error)
|
||||
}
|
||||
|
||||
type SonarQubeSdk struct {
|
||||
|
@ -20,6 +39,49 @@ type SonarQubeSdk struct {
|
|||
token string
|
||||
}
|
||||
|
||||
func (sdk *SonarQubeSdk) GetPullRequestUrl(project string, index int64) string {
|
||||
return fmt.Sprintf("%s/dashboard?id=%s&pullRequest=%s", sdk.baseUrl, project, PRNameFromIndex(index))
|
||||
}
|
||||
|
||||
func (sdk *SonarQubeSdk) fetchPullRequests(project string) *PullsResponse {
|
||||
url := fmt.Sprintf("%s/api/project_pull_requests/list?project=%s", sdk.baseUrl, project)
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
log.Printf("Cannot initialize Request: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
req.Header.Add("Authorization", sdk.basicAuth())
|
||||
rawResp, _ := sdk.client.Do(req)
|
||||
if rawResp.Body != nil {
|
||||
defer rawResp.Body.Close()
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(rawResp.Body)
|
||||
response := &PullsResponse{}
|
||||
err = json.Unmarshal(body, &response)
|
||||
if err != nil {
|
||||
log.Printf("cannot parse response from SonarQube: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func (sdk *SonarQubeSdk) GetPullRequest(project string, index int64) (*PullRequest, error) {
|
||||
response := sdk.fetchPullRequests(project)
|
||||
if response == nil {
|
||||
return nil, fmt.Errorf("unable to retrieve pull requests from SonarQube")
|
||||
}
|
||||
|
||||
name := PRNameFromIndex(index)
|
||||
pr := response.GetPullRequest(name)
|
||||
if pr == nil {
|
||||
return nil, fmt.Errorf("no pull request found with name '%s'", name)
|
||||
}
|
||||
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
func (sdk *SonarQubeSdk) GetMeasures(project string, branch string) (*MeasuresResponse, error) {
|
||||
url := fmt.Sprintf("%s/api/measures/component?additionalFields=metrics&metricKeys=bugs,vulnerabilities,new_security_hotspots,code_smells&component=%s&pullRequest=%s", sdk.baseUrl, project, branch)
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
|
|
|
@ -72,10 +72,21 @@ func (w *CommentWebhook) ProcessData(gSDK giteaSdk.GiteaSdkInterface, sqSDK sqSd
|
|||
}
|
||||
log.Printf("Fetching SonarQube data...")
|
||||
|
||||
pr, err := sqSDK.GetPullRequest(w.ConfiguredProject.SonarQube.Key, w.Issue.Number)
|
||||
if err != nil {
|
||||
log.Printf("Error loading PR data from SonarQube: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
status := giteaSdk.StatusOK
|
||||
if pr.Status.QualityGateStatus != "OK" {
|
||||
status = giteaSdk.StatusFailure
|
||||
}
|
||||
|
||||
_ = gSDK.UpdateStatus(w.ConfiguredProject.Gitea, headRef, giteaSdk.StatusDetails{
|
||||
Url: "",
|
||||
Message: "OK",
|
||||
State: giteaSdk.StatusOK,
|
||||
Url: sqSDK.GetPullRequestUrl(w.ConfiguredProject.SonarQube.Key, w.Issue.Number),
|
||||
Message: pr.Status.QualityGateStatus,
|
||||
State: status,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
sqSdk "gitea-sonarqube-pr-bot/internal/clients/sonarqube"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
@ -55,7 +55,7 @@ func New(raw []byte) (*Webhook, bool) {
|
|||
return w, false
|
||||
}
|
||||
|
||||
idx, err1 := parsePRIndex(w)
|
||||
idx, err1 := sqSdk.ParsePRIndex(w.Branch.Name)
|
||||
if err1 != nil {
|
||||
log.Printf("Error parsing PR index: %s", err1.Error())
|
||||
return w, false
|
||||
|
@ -65,13 +65,3 @@ func New(raw []byte) (*Webhook, bool) {
|
|||
|
||||
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(string(res[1]))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue