gitea-sonarqube-bot/internal/clients/sonarqube/sonarqube.go
justusbunsi 369edfcfae
Fetch actual quality gate status on bot comment
Signed-off-by: Steven Kriegler <61625851+justusbunsi@users.noreply.github.com>
2021-10-10 19:01:48 +02:00

119 lines
3.1 KiB
Go

package sonarqube
import (
"encoding/base64"
"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 {
client *http.Client
baseUrl string
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)
if err != nil {
return nil, fmt.Errorf("cannot initialize Request: %w", err)
}
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 := &MeasuresResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
return nil, fmt.Errorf("cannot parse response from SonarQube: %w", err)
}
return response, nil
}
func (sdk *SonarQubeSdk) basicAuth() string {
auth := []byte(fmt.Sprintf("%s:", sdk.token))
return fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(auth))
}
func New() *SonarQubeSdk {
return &SonarQubeSdk{
client: &http.Client{},
baseUrl: settings.SonarQube.Url,
token: settings.SonarQube.Token.Value,
}
}