You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
feat(sonar): create combined report for Sonar scans (#5427)
Co-authored-by: Yuriy.Tereshchuk <astro.lutsk.aa@gmail.com>
This commit is contained in:
committed by
GitHub
parent
fcd167b2e6
commit
eedfeccc88
@@ -251,12 +251,17 @@ func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runne
|
||||
return err
|
||||
}
|
||||
|
||||
err = getStaticCodeCheckResults(config, &taskReport, serverUrl, influx, apiClient)
|
||||
codeCheckData, err := getStaticCodeCheckResults(config, &taskReport, serverUrl, influx, apiClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = getHotSpotSecurityCheckResults(config, &taskReport, serverUrl, apiClient)
|
||||
hotSpotData, err := getHotSpotSecurityCheckResults(config, &taskReport, serverUrl, apiClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = getCombinedReport(&codeCheckData, &hotSpotData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -264,30 +269,30 @@ func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runne
|
||||
return nil
|
||||
}
|
||||
|
||||
func getStaticCodeCheckResults(config sonarExecuteScanOptions, taskReport *SonarUtils.TaskReportData, serverUrl string, influx *sonarExecuteScanInflux, apiClient SonarUtils.Sender) error {
|
||||
func getStaticCodeCheckResults(config sonarExecuteScanOptions, taskReport *SonarUtils.TaskReportData, serverUrl string, influx *sonarExecuteScanInflux, apiClient SonarUtils.Sender) (SonarUtils.ReportCodeCheckData, error) {
|
||||
// fetch number of issues by severity
|
||||
issueService := SonarUtils.NewIssuesService(serverUrl, config.Token, taskReport.ProjectKey, config.Organization, config.BranchName, config.ChangeID, apiClient)
|
||||
var categories []SonarUtils.Severity
|
||||
var err error
|
||||
influx.sonarqube_data.fields.blocker_issues, err = issueService.GetNumberOfBlockerIssues(&categories)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportCodeCheckData{}, err
|
||||
}
|
||||
influx.sonarqube_data.fields.critical_issues, err = issueService.GetNumberOfCriticalIssues(&categories)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportCodeCheckData{}, err
|
||||
}
|
||||
influx.sonarqube_data.fields.major_issues, err = issueService.GetNumberOfMajorIssues(&categories)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportCodeCheckData{}, err
|
||||
}
|
||||
influx.sonarqube_data.fields.minor_issues, err = issueService.GetNumberOfMinorIssues(&categories)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportCodeCheckData{}, err
|
||||
}
|
||||
influx.sonarqube_data.fields.info_issues, err = issueService.GetNumberOfInfoIssues(&categories)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportCodeCheckData{}, err
|
||||
}
|
||||
|
||||
reportData := SonarUtils.ReportCodeCheckData{
|
||||
@@ -297,7 +302,7 @@ func getStaticCodeCheckResults(config sonarExecuteScanOptions, taskReport *Sonar
|
||||
ChangeID: config.ChangeID,
|
||||
BranchName: config.BranchName,
|
||||
Organization: config.Organization,
|
||||
Errors: categories[:],
|
||||
ScanResults: categories[:],
|
||||
NumberOfIssues: &SonarUtils.Issues{
|
||||
Blocker: influx.sonarqube_data.fields.blocker_issues,
|
||||
Critical: influx.sonarqube_data.fields.critical_issues,
|
||||
@@ -323,16 +328,16 @@ func getStaticCodeCheckResults(config sonarExecuteScanOptions, taskReport *Sonar
|
||||
|
||||
log.Entry().Debugf("Influx values: %v", influx.sonarqube_data.fields)
|
||||
|
||||
return SonarUtils.WriteCodeCheckReport(reportData, sonar.workingDir, os.WriteFile)
|
||||
return reportData, SonarUtils.WriteCodeCheckReport(reportData, sonar.workingDir, os.WriteFile)
|
||||
}
|
||||
|
||||
func getHotSpotSecurityCheckResults(config sonarExecuteScanOptions, taskReport *SonarUtils.TaskReportData, serverUrl string, apiClient SonarUtils.Sender) error {
|
||||
func getHotSpotSecurityCheckResults(config sonarExecuteScanOptions, taskReport *SonarUtils.TaskReportData, serverUrl string, apiClient SonarUtils.Sender) (SonarUtils.ReportHotSpotData, error) {
|
||||
// fetch number of issues by severity
|
||||
issueService := SonarUtils.NewIssuesService(serverUrl, config.Token, taskReport.ProjectKey, config.Organization, config.BranchName, config.ChangeID, apiClient)
|
||||
var hotspotissues []SonarUtils.SecurityHotspot
|
||||
err := issueService.GetHotSpotSecurityIssues(&hotspotissues)
|
||||
if err != nil {
|
||||
return err
|
||||
return SonarUtils.ReportHotSpotData{}, err
|
||||
}
|
||||
|
||||
reportData := SonarUtils.ReportHotSpotData{
|
||||
@@ -345,7 +350,17 @@ func getHotSpotSecurityCheckResults(config sonarExecuteScanOptions, taskReport *
|
||||
SecurityHotspots: hotspotissues[:],
|
||||
}
|
||||
|
||||
return SonarUtils.WriteHotSpotReport(reportData, sonar.workingDir, os.WriteFile)
|
||||
return reportData, SonarUtils.WriteHotSpotReport(reportData, sonar.workingDir, os.WriteFile)
|
||||
}
|
||||
|
||||
func getCombinedReport(codeCheckData *SonarUtils.ReportCodeCheckData, hotSpotData *SonarUtils.ReportHotSpotData) error {
|
||||
reportData := SonarUtils.ReportCombinedData{
|
||||
NumberOfIssues: codeCheckData.NumberOfIssues,
|
||||
ScanResults: codeCheckData.ScanResults,
|
||||
SecurityHotspots: hotSpotData.SecurityHotspots,
|
||||
}
|
||||
|
||||
return SonarUtils.WriteCombinedReport(reportData, sonar.workingDir, os.WriteFile)
|
||||
}
|
||||
|
||||
// isInOptions returns true, if the given property is already provided in config.Options.
|
||||
|
@@ -6,7 +6,8 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const reportCodeCheckFileName = "sonarscan.json"
|
||||
const reportCodeCheckFileName = "codecheck.json"
|
||||
const reportCombinedFileName = "sonarscan.json"
|
||||
const reportHotSpotFileName = "hotspot.json"
|
||||
|
||||
// ReportCodeCheckData is representing the data of the step report JSON
|
||||
@@ -18,7 +19,7 @@ type ReportCodeCheckData struct {
|
||||
BranchName string `json:"branchName,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
NumberOfIssues *Issues `json:"numberOfIssues"`
|
||||
Errors []Severity `json:"errors"`
|
||||
ScanResults []Severity `json:"scanResults"`
|
||||
Coverage *SonarCoverage `json:"coverage,omitempty"`
|
||||
LinesOfCode *SonarLinesOfCode `json:"linesOfCode,omitempty"`
|
||||
}
|
||||
@@ -34,6 +35,12 @@ type ReportHotSpotData struct {
|
||||
SecurityHotspots []SecurityHotspot `json:"securityHotspots"`
|
||||
}
|
||||
|
||||
type ReportCombinedData struct {
|
||||
NumberOfIssues *Issues `json:"numberOfIssues"`
|
||||
ScanResults []Severity `json:"scanResults"`
|
||||
SecurityHotspots []SecurityHotspot `json:"securityHotspots"`
|
||||
}
|
||||
|
||||
// HotSpot Security Issues
|
||||
type SecurityHotspot struct {
|
||||
Priority string `json:"priority"`
|
||||
@@ -71,3 +78,11 @@ func WriteHotSpotReport(data ReportHotSpotData, reportPath string, writeToFile f
|
||||
}
|
||||
return writeToFile(filepath.Join(reportPath, reportHotSpotFileName), jsonData, 0644)
|
||||
}
|
||||
|
||||
func WriteCombinedReport(data ReportCombinedData, reportPath string, writeToFile func(f string, d []byte, p os.FileMode) error) error {
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeToFile(filepath.Join(reportPath, reportCombinedFileName), jsonData, 0644)
|
||||
}
|
||||
|
@@ -22,12 +22,12 @@ func writeToFileMock(f string, d []byte, p os.FileMode) error {
|
||||
|
||||
func TestWriteCodeCheckReport(t *testing.T) {
|
||||
// init
|
||||
const expected = `{"serverUrl":"https://sonarcloud.io","projectKey":"Piper-Validation/Golang","taskId":"mock.Anything","numberOfIssues":{"blocker":0,"critical":1,"major":2,"minor":3,"info":4},"errors":[{"severity":"CRITICAL","error_type":"CODE_SMELL","issues":10}],"coverage":{"coverage":13.7,"lineCoverage":37.1,"linesToCover":123,"uncoveredLines":23,"branchCoverage":42,"branchesToCover":30,"uncoveredBranches":3},"linesOfCode":{"total":327,"languageDistribution":[{"languageKey":"java","linesOfCode":327}]}}`
|
||||
const expected = `{"serverUrl":"https://sonarcloud.io","projectKey":"Piper-Validation/Golang","taskId":"mock.Anything","numberOfIssues":{"blocker":0,"critical":1,"major":2,"minor":3,"info":4},"scanResults":[{"severity":"CRITICAL","error_type":"CODE_SMELL","issues":10}],"coverage":{"coverage":13.7,"lineCoverage":37.1,"linesToCover":123,"uncoveredLines":23,"branchCoverage":42,"branchesToCover":30,"uncoveredBranches":3},"linesOfCode":{"total":327,"languageDistribution":[{"languageKey":"java","linesOfCode":327}]}}`
|
||||
testData := ReportCodeCheckData{
|
||||
ServerURL: "https://sonarcloud.io",
|
||||
ProjectKey: "Piper-Validation/Golang",
|
||||
TaskID: mock.Anything,
|
||||
Errors: []Severity{
|
||||
ScanResults: []Severity{
|
||||
{
|
||||
SeverityType: "CRITICAL",
|
||||
IssueType: "CODE_SMELL",
|
||||
@@ -81,3 +81,33 @@ func TestWriteHotSpotReport(t *testing.T) {
|
||||
assert.Equal(t, expected, fileContent)
|
||||
assert.Equal(t, reportHotSpotFileName, fileName)
|
||||
}
|
||||
|
||||
func TestWriteCombinedReport(t *testing.T) {
|
||||
// init
|
||||
const expected = `{"numberOfIssues":{"blocker":0,"critical":1,"major":2,"minor":3,"info":4},"scanResults":[{"severity":"CRITICAL","error_type":"CODE_SMELL","issues":10}],"securityHotspots":[{"priority":"HIGH","hotspots":1},{"priority":"LOW","hotspots":4}]}`
|
||||
combinedData := ReportCombinedData{
|
||||
ScanResults: []Severity{
|
||||
{
|
||||
SeverityType: "CRITICAL",
|
||||
IssueType: "CODE_SMELL",
|
||||
IssueCount: 10,
|
||||
},
|
||||
},
|
||||
NumberOfIssues: &Issues{
|
||||
Critical: 1,
|
||||
Major: 2,
|
||||
Minor: 3,
|
||||
Info: 4,
|
||||
},
|
||||
SecurityHotspots: []SecurityHotspot{
|
||||
{Priority: "HIGH", Hotspots: 1},
|
||||
{Priority: "LOW", Hotspots: 4},
|
||||
},
|
||||
}
|
||||
// test
|
||||
err := WriteCombinedReport(combinedData, "", writeToFileMock)
|
||||
// assert
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, fileContent)
|
||||
assert.Equal(t, reportCombinedFileName, fileName)
|
||||
}
|
||||
|
Reference in New Issue
Block a user