Allow customizing metrics fetch from SonarQube
Signed-off-by: Steven Kriegler <sk.bunsenbrenner@gmail.com>
This commit is contained in:
parent
a2d68ccc12
commit
f187d4f8c6
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@
|
||||||
/coverage.html
|
/coverage.html
|
||||||
/*.log
|
/*.log
|
||||||
/cover.out
|
/cover.out
|
||||||
|
/cover.html
|
||||||
|
|
|
@ -7,8 +7,8 @@ gitea:
|
||||||
# User needs "Read project" permissions with access to "Pull Requests"
|
# User needs "Read project" permissions with access to "Pull Requests"
|
||||||
token:
|
token:
|
||||||
value: ""
|
value: ""
|
||||||
# # or path to file containing the plain text secret
|
# # or path to file containing the plain text secret
|
||||||
# file: /path/to/gitea/token
|
# file: /path/to/gitea/token
|
||||||
|
|
||||||
# If the sent webhook has a signature header, the bot validates the request payload. If the value does not match, the
|
# If the sent webhook has a signature header, the bot validates the request payload. If the value does not match, the
|
||||||
# request will be ignored.
|
# request will be ignored.
|
||||||
|
@ -16,8 +16,8 @@ gitea:
|
||||||
# exists and no webhookSecret is defined here, the bot will ignore the request, because it cannot be validated.
|
# exists and no webhookSecret is defined here, the bot will ignore the request, because it cannot be validated.
|
||||||
webhook:
|
webhook:
|
||||||
secret: ""
|
secret: ""
|
||||||
# # or path to file containing the plain text secret
|
# # or path to file containing the plain text secret
|
||||||
# secretFile: /path/to/gitea/webhook/secret
|
# secretFile: /path/to/gitea/webhook/secret
|
||||||
|
|
||||||
# SonarQube related configuration. Necessary for requesting data from the API and processing the webhook.
|
# SonarQube related configuration. Necessary for requesting data from the API and processing the webhook.
|
||||||
sonarqube:
|
sonarqube:
|
||||||
|
@ -28,8 +28,8 @@ sonarqube:
|
||||||
# User needs "Browse on project" permissions
|
# User needs "Browse on project" permissions
|
||||||
token:
|
token:
|
||||||
value: ""
|
value: ""
|
||||||
# # or path to file containing the plain text secret
|
# # or path to file containing the plain text secret
|
||||||
# file: /path/to/sonarqube/token
|
# file: /path/to/sonarqube/token
|
||||||
|
|
||||||
# If the sent webhook has a signature header, the bot validates the request payload. If the value does not match, the
|
# If the sent webhook has a signature header, the bot validates the request payload. If the value does not match, the
|
||||||
# request will be ignored.
|
# request will be ignored.
|
||||||
|
@ -38,8 +38,14 @@ sonarqube:
|
||||||
# validated.
|
# validated.
|
||||||
webhook:
|
webhook:
|
||||||
secret: ""
|
secret: ""
|
||||||
# # or path to file containing the plain text secret
|
# # or path to file containing the plain text secret
|
||||||
# secretFile: /path/to/sonarqube/webhook/secret
|
# secretFile: /path/to/sonarqube/webhook/secret
|
||||||
|
|
||||||
|
# Some useful metrics depend on the edition in use. There are various ones like code_smells, vulnerabilities, bugs, etc.
|
||||||
|
# By default the bot will extract "bugs,vulnerabilities,code_smells"
|
||||||
|
# Setting this option you can extend that default list by your own metrics.
|
||||||
|
additionalMetrics: []
|
||||||
|
# - "new_security_hotspots"
|
||||||
|
|
||||||
# List of project mappings to take care of. Webhooks for other projects will be ignored.
|
# List of project mappings to take care of. Webhooks for other projects will be ignored.
|
||||||
# At least one must be configured. Otherwise all webhooks (no matter which source) because the bot cannot map on its own.
|
# At least one must be configured. Otherwise all webhooks (no matter which source) because the bot cannot map on its own.
|
||||||
|
|
|
@ -55,6 +55,12 @@ app:
|
||||||
secret: ""
|
secret: ""
|
||||||
# # or path to file containing the plain text secret
|
# # or path to file containing the plain text secret
|
||||||
# secretFile: /bot/secrets/sonarqube/webhook-secret
|
# secretFile: /bot/secrets/sonarqube/webhook-secret
|
||||||
|
|
||||||
|
# Some useful metrics depend on the edition in use. There are various ones like code_smells, vulnerabilities, bugs, etc.
|
||||||
|
# By default the bot will extract "bugs,vulnerabilities,code_smells"
|
||||||
|
# Setting this option you can extend that default list by your own metrics.
|
||||||
|
additionalMetrics: []
|
||||||
|
# - "new_security_hotspots"
|
||||||
|
|
||||||
# List of project mappings to take care of. Webhooks for other projects will be ignored.
|
# List of project mappings to take care of. Webhooks for other projects will be ignored.
|
||||||
# At least one must be configured. Otherwise all webhooks (no matter which source) because the bot cannot map on its own.
|
# At least one must be configured. Otherwise all webhooks (no matter which source) because the bot cannot map on its own.
|
||||||
|
|
|
@ -102,7 +102,7 @@ func (sdk *SonarQubeSdk) GetPullRequest(project string, index int64) (*PullReque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdk *SonarQubeSdk) GetMeasures(project string, branch string) (*MeasuresResponse, error) {
|
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)
|
url := fmt.Sprintf("%s/api/measures/component?additionalFields=metrics&metricKeys=%s&component=%s&pullRequest=%s", sdk.baseUrl, settings.SonarQube.GetMetricsList(), project, branch)
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot initialize Request: %w", err)
|
return nil, fmt.Errorf("cannot initialize Request: %w", err)
|
||||||
|
|
|
@ -32,6 +32,7 @@ func newConfigReader() *viper.Viper {
|
||||||
v.SetDefault("sonarqube.token.file", "")
|
v.SetDefault("sonarqube.token.file", "")
|
||||||
v.SetDefault("sonarqube.webhook.secret", "")
|
v.SetDefault("sonarqube.webhook.secret", "")
|
||||||
v.SetDefault("sonarqube.webhook.secretFile", "")
|
v.SetDefault("sonarqube.webhook.secretFile", "")
|
||||||
|
v.SetDefault("sonarqube.additionalMetrics", []string{})
|
||||||
v.SetDefault("projects", []Project{})
|
v.SetDefault("projects", []Project{})
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
@ -43,14 +44,14 @@ func Load(configPath string) {
|
||||||
|
|
||||||
err := r.ReadInConfig()
|
err := r.ReadInConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("Fatal error while reading config file: %w \n", err))
|
panic(fmt.Errorf("fatal error while reading config file: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
var projects []Project
|
var projects []Project
|
||||||
|
|
||||||
err = r.UnmarshalKey("projects", &projects)
|
err = r.UnmarshalKey("projects", &projects)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("Unable to load project mapping: %s", err.Error()))
|
panic(fmt.Errorf("unable to load project mapping: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(projects) == 0 {
|
if len(projects) == 0 {
|
||||||
|
@ -67,8 +68,9 @@ func Load(configPath string) {
|
||||||
Webhook: NewWebhook(r, "gitea", errCallback),
|
Webhook: NewWebhook(r, "gitea", errCallback),
|
||||||
}
|
}
|
||||||
SonarQube = sonarQubeConfig{
|
SonarQube = sonarQubeConfig{
|
||||||
Url: r.GetString("sonarqube.url"),
|
Url: r.GetString("sonarqube.url"),
|
||||||
Token: NewToken(r, "sonarqube", errCallback),
|
Token: NewToken(r, "sonarqube", errCallback),
|
||||||
Webhook: NewWebhook(r, "sonarqube", errCallback),
|
Webhook: NewWebhook(r, "sonarqube", errCallback),
|
||||||
|
AdditionalMetrics: r.GetStringSlice("sonarqube.additionalMetrics"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ sonarqube:
|
||||||
value: a09eb5785b25bb2cbacf48808a677a0709f02d8e
|
value: a09eb5785b25bb2cbacf48808a677a0709f02d8e
|
||||||
webhook:
|
webhook:
|
||||||
secret: haxxor-sonarqube-secret
|
secret: haxxor-sonarqube-secret
|
||||||
|
additionalMetrics: []
|
||||||
projects:
|
projects:
|
||||||
- sonarqube:
|
- sonarqube:
|
||||||
key: gitea-sonarqube-pr-bot
|
key: gitea-sonarqube-pr-bot
|
||||||
|
@ -107,6 +108,45 @@ func TestLoadSonarQubeStructure(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.EqualValues(t, expected, SonarQube)
|
assert.EqualValues(t, expected, SonarQube)
|
||||||
|
assert.EqualValues(t, expected.GetMetricsList(), "bugs,vulnerabilities,code_smells")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadSonarQubeStructureWithAdditionalMetrics(t *testing.T) {
|
||||||
|
WriteConfigFile(t, []byte(
|
||||||
|
`gitea:
|
||||||
|
url: https://example.com/gitea
|
||||||
|
token:
|
||||||
|
value: fake-gitea-token
|
||||||
|
sonarqube:
|
||||||
|
url: https://example.com/sonarqube
|
||||||
|
token:
|
||||||
|
value: fake-sonarqube-token
|
||||||
|
additionalMetrics: "new_security_hotspots"
|
||||||
|
projects:
|
||||||
|
- sonarqube:
|
||||||
|
key: gitea-sonarqube-pr-bot
|
||||||
|
gitea:
|
||||||
|
owner: example-organization
|
||||||
|
name: pr-bot
|
||||||
|
`))
|
||||||
|
Load(os.TempDir())
|
||||||
|
|
||||||
|
expected := sonarQubeConfig{
|
||||||
|
Url: "https://example.com/sonarqube",
|
||||||
|
Token: &token{
|
||||||
|
Value: "fake-sonarqube-token",
|
||||||
|
},
|
||||||
|
Webhook: &webhook{
|
||||||
|
Secret: "",
|
||||||
|
},
|
||||||
|
AdditionalMetrics: []string{
|
||||||
|
"new_security_hotspots",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.EqualValues(t, expected, SonarQube)
|
||||||
|
assert.EqualValues(t, expected.AdditionalMetrics, []string{"new_security_hotspots"})
|
||||||
|
assert.EqualValues(t, "bugs,vulnerabilities,code_smells,new_security_hotspots", SonarQube.GetMetricsList())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadSonarQubeStructureInjectedEnvs(t *testing.T) {
|
func TestLoadSonarQubeStructureInjectedEnvs(t *testing.T) {
|
||||||
|
@ -189,6 +229,7 @@ projects:
|
||||||
Secret: "sonarqube-totally-secret",
|
Secret: "sonarqube-totally-secret",
|
||||||
secretFile: sonarqubeWebhookSecretFile,
|
secretFile: sonarqubeWebhookSecretFile,
|
||||||
},
|
},
|
||||||
|
AdditionalMetrics: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
Load(os.TempDir())
|
Load(os.TempDir())
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
type sonarQubeConfig struct {
|
type sonarQubeConfig struct {
|
||||||
Url string
|
Url string
|
||||||
Token *token
|
Token *token
|
||||||
Webhook *webhook
|
Webhook *webhook
|
||||||
|
AdditionalMetrics []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sonarQubeConfig) GetMetricsList() string {
|
||||||
|
metrics := []string{
|
||||||
|
"bugs",
|
||||||
|
"vulnerabilities",
|
||||||
|
"code_smells",
|
||||||
|
}
|
||||||
|
if len(c.AdditionalMetrics) != 0 {
|
||||||
|
metrics = append(metrics, c.AdditionalMetrics...)
|
||||||
|
}
|
||||||
|
return strings.Join(metrics, ",")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue