From f325e02eb12de8a7f47b3ac67a65ca7d7f8b6abd Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 21 Apr 2025 08:56:40 +0530 Subject: [PATCH 1/8] Added sonar qube as external evidence --- evidence/external/sonarqube/sonarqube.go | 179 +++++++++++++++++++++++ evidence/manager.go | 11 ++ 2 files changed, 190 insertions(+) create mode 100644 evidence/external/sonarqube/sonarqube.go diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go new file mode 100644 index 000000000..9005af803 --- /dev/null +++ b/evidence/external/sonarqube/sonarqube.go @@ -0,0 +1,179 @@ +package sonarqube + +import ( + "bufio" + "errors" + "github.com/jfrog/jfrog-client-go/utils/log" + "io" + "net/http" + "os" + "strings" + "time" +) + +type SonarQube struct { + componentName string + ServiceConfig +} + +type ServiceConfig struct { + url string + taskAPIPath string + projectStatusAPIPath string + auth Authentication +} + +type Authentication struct { + AccessToken string +} + +func NewSonarQubeEvidence() *SonarQube { + sonarQubeURL := os.Getenv("JF_SONARQUBE_URL") + componentName := os.Getenv("JF_SONARQUBE_COMPONENT_NAME") + + return &SonarQube{ + componentName: componentName, + ServiceConfig: ServiceConfig{ + url: sonarQubeURL, + //apiPath: "/api/measures/component", // Example API path + //apiPath: "/api/project_analyses/search", // Example API path + taskAPIPath: "/api/ce/task", // Example API path + projectStatusAPIPath: "/api/qualitygates/project_status", + auth: Authentication{ + AccessToken: "", + }, + }, + } +} + +func (sqe *SonarQube) createQueryParam(params map[string]string, key, value string) map[string]string { + if params != nil { + params[key] = value + return params + } + return map[string]string{ + //"metricKeys": "coverage,bugs,vulnerabilities", + //"component": sqe.componentName, + //"project": sqe.componentName, + //"buildString": "mvn-sonar-2", + key: value, + } +} + +func getCeTaskUrlFromFile(filePath string) (string, error) { + file, err := os.Open(filePath) + if err != nil { + panic("Failed to open file: " + err.Error()) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "ceTaskUrl=") { + taskIDs := strings.Split(line, "?id=") + if len(taskIDs) < 2 { + log.Error("Invalid ceTaskUrl format in file") + return "", errors.New("invalid ceTaskUrl format in file") + } + return strings.Split(line, "?id=")[1], nil + } + } + + if err := scanner.Err(); err != nil { + panic("Error reading file: " + err.Error()) + } + + log.Error("ceTaskUrl not found in file") + return "", errors.New("ceTaskUrl not found in file") +} + +func createHttpClient() *http.Client { + // Create a new HTTP client with custom settings + client := &http.Client{ + Timeout: 30 * time.Second, // Set a timeout for requests + Transport: &http.Transport{ + MaxIdleConns: 10, // Maximum idle connections + IdleConnTimeout: 30 * time.Second, // Idle connection timeout + DisableKeepAlives: false, // Enable keep-alive + }, + } + return client +} + +func (sqe *SonarQube) GetSonarQubeProjectStatus(analysisID string) ([]byte, error) { + log.Debug("Getting sonarqube project status for analysis: " + analysisID) + queryParams := sqe.createQueryParam(nil, "analysisId", analysisID) + url := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath + log.Debug("SonarQube URL: " + url) + // Create a new HTTP request + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + // Add query parameters to the request + q := req.URL.Query() + for key, value := range queryParams { + q.Add(key, value) + } + req.URL.RawQuery = q.Encode() + resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req) + if err != nil { + return bytes, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return body, nil +} + +func (sqe *SonarQube) CollectSonarQubePredicate() ([]byte, error) { + taskID, err := getCeTaskUrlFromFile("target/sonar/report-task.txt") + if err != nil { + log.Error("Failed to get ceTaskUrl: " + err.Error()) + return nil, err + } + queryParams := sqe.createQueryParam(nil, "id", taskID) + url := sqe.ServiceConfig.url + sqe.ServiceConfig.taskAPIPath + + // Create a new HTTP request + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + // Add query parameters to the request + q := req.URL.Query() + for key, value := range queryParams { + q.Add(key, value) + } + req.URL.RawQuery = q.Encode() + + resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req) + if err != nil { + return bytes, err + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return body, nil +} + +func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request) (*http.Response, []byte, error) { + // Add Authorization header + sonarQubeToken := os.Getenv("JF_SONARQUBE_TOKEN") + req.Header.Set("Authorization", "Bearer "+sonarQubeToken) + httpClient := createHttpClient() + + // Send the request using the standard HTTP client + resp, err := httpClient.Do(req) + if err != nil { + return nil, nil, err + } + return resp, nil, nil +} diff --git a/evidence/manager.go b/evidence/manager.go index e4a8ce45c..add0c6834 100644 --- a/evidence/manager.go +++ b/evidence/manager.go @@ -2,6 +2,7 @@ package evidence import ( "github.com/jfrog/jfrog-client-go/config" + "github.com/jfrog/jfrog-client-go/evidence/external/sonarqube" "github.com/jfrog/jfrog-client-go/evidence/services" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" ) @@ -39,3 +40,13 @@ func (esm *EvidenceServicesManager) UploadEvidence(evidenceDetails services.Evid evidenceService := services.NewEvidenceService(esm.config.GetServiceDetails(), esm.client) return evidenceService.UploadEvidence(evidenceDetails) } + +func (esm *EvidenceServicesManager) CreateSonarQubeEvidence() ([]byte, error) { + sonarqubeReport := sonarqube.NewSonarQubeEvidence() + return sonarqubeReport.CollectSonarQubePredicate() +} + +func (esm *EvidenceServicesManager) GetSonarQubeProjectStatus(analysisID string) ([]byte, error) { + sonarqubeReport := sonarqube.NewSonarQubeEvidence() + return sonarqubeReport.GetSonarQubeProjectStatus(analysisID) +} From a9eea06094aefefce9ef509c70774ae5fdd25551 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Thu, 15 May 2025 00:54:53 +0530 Subject: [PATCH 2/8] Updated to use taskID & analysisID to fetch reports --- evidence/external/sonarqube/sonarqube.go | 129 +++++++++-------------- evidence/manager.go | 10 +- 2 files changed, 55 insertions(+), 84 deletions(-) diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index 9005af803..baefc45ee 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -1,18 +1,16 @@ package sonarqube import ( - "bufio" - "errors" "github.com/jfrog/jfrog-client-go/utils/log" "io" "net/http" + "net/url" "os" - "strings" "time" ) type SonarQube struct { - componentName string + Proxy string ServiceConfig } @@ -20,28 +18,15 @@ type ServiceConfig struct { url string taskAPIPath string projectStatusAPIPath string - auth Authentication } -type Authentication struct { - AccessToken string -} - -func NewSonarQubeEvidence() *SonarQube { - sonarQubeURL := os.Getenv("JF_SONARQUBE_URL") - componentName := os.Getenv("JF_SONARQUBE_COMPONENT_NAME") - +func NewSonarQubeEvidence(sonarQubeURL, proxy string) *SonarQube { return &SonarQube{ - componentName: componentName, + Proxy: proxy, ServiceConfig: ServiceConfig{ - url: sonarQubeURL, - //apiPath: "/api/measures/component", // Example API path - //apiPath: "/api/project_analyses/search", // Example API path - taskAPIPath: "/api/ce/task", // Example API path + url: sonarQubeURL, + taskAPIPath: "/api/ce/task", projectStatusAPIPath: "/api/qualitygates/project_status", - auth: Authentication{ - AccessToken: "", - }, }, } } @@ -52,62 +37,42 @@ func (sqe *SonarQube) createQueryParam(params map[string]string, key, value stri return params } return map[string]string{ - //"metricKeys": "coverage,bugs,vulnerabilities", - //"component": sqe.componentName, - //"project": sqe.componentName, - //"buildString": "mvn-sonar-2", key: value, } } -func getCeTaskUrlFromFile(filePath string) (string, error) { - file, err := os.Open(filePath) - if err != nil { - panic("Failed to open file: " + err.Error()) +func createHttpClient(proxy string) *http.Client { + transport := &http.Transport{ + MaxIdleConns: 10, + IdleConnTimeout: 30 * time.Second, + DisableKeepAlives: false, } - defer file.Close() - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "ceTaskUrl=") { - taskIDs := strings.Split(line, "?id=") - if len(taskIDs) < 2 { - log.Error("Invalid ceTaskUrl format in file") - return "", errors.New("invalid ceTaskUrl format in file") - } - return strings.Split(line, "?id=")[1], nil + if proxy == "" { + return &http.Client{ + Timeout: 30 * time.Second, + Transport: transport, + } + } else { + proxyURL, err := url.Parse(proxy) + if err != nil { + log.Error("Failed to parse proxy URL: " + err.Error()) + return nil + } + transport.Proxy = http.ProxyURL(proxyURL) + return &http.Client{ + Timeout: 30 * time.Second, + Transport: transport, } } - - if err := scanner.Err(); err != nil { - panic("Error reading file: " + err.Error()) - } - - log.Error("ceTaskUrl not found in file") - return "", errors.New("ceTaskUrl not found in file") -} - -func createHttpClient() *http.Client { - // Create a new HTTP client with custom settings - client := &http.Client{ - Timeout: 30 * time.Second, // Set a timeout for requests - Transport: &http.Transport{ - MaxIdleConns: 10, // Maximum idle connections - IdleConnTimeout: 30 * time.Second, // Idle connection timeout - DisableKeepAlives: false, // Enable keep-alive - }, - } - return client } func (sqe *SonarQube) GetSonarQubeProjectStatus(analysisID string) ([]byte, error) { log.Debug("Getting sonarqube project status for analysis: " + analysisID) queryParams := sqe.createQueryParam(nil, "analysisId", analysisID) - url := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath - log.Debug("SonarQube URL: " + url) + sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath + log.Debug("SonarQube URL: " + sonarServerURL) // Create a new HTTP request - req, err := http.NewRequest("GET", url, nil) + req, err := http.NewRequest("GET", sonarServerURL, nil) if err != nil { return nil, err } @@ -117,11 +82,16 @@ func (sqe *SonarQube) GetSonarQubeProjectStatus(analysisID string) ([]byte, erro q.Add(key, value) } req.URL.RawQuery = q.Encode() - resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req) + resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req, sqe.Proxy) if err != nil { return bytes, err } - defer resp.Body.Close() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + log.Error("Failed to close response body: " + err.Error()) + } + }(resp.Body) body, err := io.ReadAll(resp.Body) if err != nil { return nil, err @@ -129,17 +99,12 @@ func (sqe *SonarQube) GetSonarQubeProjectStatus(analysisID string) ([]byte, erro return body, nil } -func (sqe *SonarQube) CollectSonarQubePredicate() ([]byte, error) { - taskID, err := getCeTaskUrlFromFile("target/sonar/report-task.txt") - if err != nil { - log.Error("Failed to get ceTaskUrl: " + err.Error()) - return nil, err - } +func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { queryParams := sqe.createQueryParam(nil, "id", taskID) - url := sqe.ServiceConfig.url + sqe.ServiceConfig.taskAPIPath + sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.taskAPIPath // Create a new HTTP request - req, err := http.NewRequest("GET", url, nil) + req, err := http.NewRequest("GET", sonarServerURL, nil) if err != nil { return nil, err } @@ -150,25 +115,31 @@ func (sqe *SonarQube) CollectSonarQubePredicate() ([]byte, error) { } req.URL.RawQuery = q.Encode() - resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req) + resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req, sqe.Proxy) if err != nil { return bytes, err } - defer resp.Body.Close() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + log.Error("Failed to close response body: " + err.Error()) + } + }(resp.Body) body, err := io.ReadAll(resp.Body) + log.Debug("SonarQube response: " + string(body)) if err != nil { return nil, err } return body, nil } -func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request) (*http.Response, []byte, error) { +func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request, proxy string) (*http.Response, []byte, error) { // Add Authorization header - sonarQubeToken := os.Getenv("JF_SONARQUBE_TOKEN") + sonarQubeToken := os.Getenv("JF_SONARQUBE_ACCESS_TOKEN") req.Header.Set("Authorization", "Bearer "+sonarQubeToken) - httpClient := createHttpClient() + httpClient := createHttpClient(proxy) // Send the request using the standard HTTP client resp, err := httpClient.Do(req) diff --git a/evidence/manager.go b/evidence/manager.go index add0c6834..aaf7ea8f2 100644 --- a/evidence/manager.go +++ b/evidence/manager.go @@ -41,12 +41,12 @@ func (esm *EvidenceServicesManager) UploadEvidence(evidenceDetails services.Evid return evidenceService.UploadEvidence(evidenceDetails) } -func (esm *EvidenceServicesManager) CreateSonarQubeEvidence() ([]byte, error) { - sonarqubeReport := sonarqube.NewSonarQubeEvidence() - return sonarqubeReport.CollectSonarQubePredicate() +func (esm *EvidenceServicesManager) CreateSonarQubeEvidence(taskID, sonarQubeURL, proxy string) ([]byte, error) { + sonarqubeReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) + return sonarqubeReport.CollectSonarQubePredicate(taskID) } -func (esm *EvidenceServicesManager) GetSonarQubeProjectStatus(analysisID string) ([]byte, error) { - sonarqubeReport := sonarqube.NewSonarQubeEvidence() +func (esm *EvidenceServicesManager) GetSonarQubeProjectStatus(analysisID, sonarQubeURL, proxy string) ([]byte, error) { + sonarqubeReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) return sonarqubeReport.GetSonarQubeProjectStatus(analysisID) } From 94c8d4a486ef4dbd073a7e6d96a98c5ffb72759a Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Fri, 16 May 2025 21:56:50 +0530 Subject: [PATCH 3/8] Added validation for token and check status code --- evidence/external/sonarqube/sonarqube.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index baefc45ee..fd2481893 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -1,6 +1,7 @@ package sonarqube import ( + "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" "io" "net/http" @@ -119,6 +120,9 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { if err != nil { return bytes, err } + if resp.StatusCode != http.StatusOK { + return nil, errorutils.CheckErrorf("Failed to get SonarQube task report. Status code: %d", resp.StatusCode) + } defer func(Body io.ReadCloser) { err := Body.Close() @@ -138,6 +142,9 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request, proxy string) (*http.Response, []byte, error) { // Add Authorization header sonarQubeToken := os.Getenv("JF_SONARQUBE_ACCESS_TOKEN") + if sonarQubeToken == "" { + return nil, nil, errorutils.CheckErrorf("SonarQube access token not found in environment variable JF_SONARQUBE_ACCESS_TOKEN") + } req.Header.Set("Authorization", "Bearer "+sonarQubeToken) httpClient := createHttpClient(proxy) From 681a69c252adf7932e2e5757211a1dae6eca363b Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 19 May 2025 21:08:11 +0530 Subject: [PATCH 4/8] Code cleanup and function renaming --- evidence/external/sonarqube/sonarqube.go | 5 ++--- evidence/manager.go | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index fd2481893..e38574047 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -67,11 +67,10 @@ func createHttpClient(proxy string) *http.Client { } } -func (sqe *SonarQube) GetSonarQubeProjectStatus(analysisID string) ([]byte, error) { - log.Debug("Getting sonarqube project status for analysis: " + analysisID) +func (sqe *SonarQube) GetSonarAnalysis(analysisID string) ([]byte, error) { + log.Debug("Fetching sonar analysis for given analysisID: " + analysisID) queryParams := sqe.createQueryParam(nil, "analysisId", analysisID) sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath - log.Debug("SonarQube URL: " + sonarServerURL) // Create a new HTTP request req, err := http.NewRequest("GET", sonarServerURL, nil) if err != nil { diff --git a/evidence/manager.go b/evidence/manager.go index aaf7ea8f2..5ab977533 100644 --- a/evidence/manager.go +++ b/evidence/manager.go @@ -41,12 +41,12 @@ func (esm *EvidenceServicesManager) UploadEvidence(evidenceDetails services.Evid return evidenceService.UploadEvidence(evidenceDetails) } -func (esm *EvidenceServicesManager) CreateSonarQubeEvidence(taskID, sonarQubeURL, proxy string) ([]byte, error) { - sonarqubeReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) - return sonarqubeReport.CollectSonarQubePredicate(taskID) +func (esm *EvidenceServicesManager) FetchSonarTaskStatus(taskID, sonarQubeURL, proxy string) ([]byte, error) { + sonarTaskStatus := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) + return sonarTaskStatus.CollectSonarQubePredicate(taskID) } -func (esm *EvidenceServicesManager) GetSonarQubeProjectStatus(analysisID, sonarQubeURL, proxy string) ([]byte, error) { - sonarqubeReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) - return sonarqubeReport.GetSonarQubeProjectStatus(analysisID) +func (esm *EvidenceServicesManager) FetchSonarComponentAnalysis(analysisID, sonarQubeURL, proxy string) ([]byte, error) { + sonarAnalysisReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) + return sonarAnalysisReport.GetSonarAnalysis(analysisID) } From 88059221ee0c8fd0518b39a110c580a037f50fca Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Tue, 20 May 2025 19:50:03 +0530 Subject: [PATCH 5/8] Improved http client creation and added README --- README.md | 23 +++++++++++ evidence/external/sonarqube/sonarqube.go | 50 +++++++++++------------- evidence/manager.go | 2 +- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index faaa4a225..cb7176097 100644 --- a/README.md +++ b/README.md @@ -3048,6 +3048,29 @@ evidenceDetails := evidenceService.EvidenceDetails{ } body, err = evideceManager.UploadEvidence(evidenceDetails) ``` + +#### Fetch Sonar Task Report + +```go +// Fetches the status of a SonarQube task by its task ID. +taskID := "your-task-id" +// sonarQubeURL is the URL of the SonarQube server. +sonarQubeURL := "http://localhost:9000" +// proxy is optional and can be used to specify a proxy server. +proxy := "" +body, err := evidenceManager.FetchSonarTaskStatus(taskID, sonarQubeURL, proxy) +``` +#### Fetch Sonar Task Report with Proxy + +```go +// Retrieves the analysis report from SonarQube by analysis ID. +analysisID := "your-analysis-id" +// sonarQubeURL is the URL of the SonarQube server. +sonarQubeURL := "http://localhost:9000" +// proxy is optional and can be used to specify a proxy server. +proxy := "" +body, err := evidenceManager.GetSonarAnalysisReport(analysisID, sonarQubeURL, proxy) +``` ## Metadata APIs ### Creating Metadata Service Manager diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index e38574047..d7e9df821 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -10,6 +10,8 @@ import ( "time" ) +const sonarAccessTokenKey = "JF_SONARQUBE_ACCESS_TOKEN" + type SonarQube struct { Proxy string ServiceConfig @@ -47,35 +49,35 @@ func createHttpClient(proxy string) *http.Client { MaxIdleConns: 10, IdleConnTimeout: 30 * time.Second, DisableKeepAlives: false, + Proxy: http.ProxyFromEnvironment, } - if proxy == "" { - return &http.Client{ - Timeout: 30 * time.Second, - Transport: transport, - } - } else { + if proxy != "" { proxyURL, err := url.Parse(proxy) if err != nil { + + // Fallback to environment proxy or no proxy log.Error("Failed to parse proxy URL: " + err.Error()) - return nil - } - transport.Proxy = http.ProxyURL(proxyURL) - return &http.Client{ - Timeout: 30 * time.Second, - Transport: transport, + } else { + transport.Proxy = http.ProxyURL(proxyURL) } } + return &http.Client{ + Timeout: 30 * time.Second, + Transport: transport, + } } func (sqe *SonarQube) GetSonarAnalysis(analysisID string) ([]byte, error) { log.Debug("Fetching sonar analysis for given analysisID: " + analysisID) queryParams := sqe.createQueryParam(nil, "analysisId", analysisID) sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath + // Create a new HTTP request req, err := http.NewRequest("GET", sonarServerURL, nil) if err != nil { return nil, err } + // Add query parameters to the request q := req.URL.Query() for key, value := range queryParams { @@ -102,36 +104,28 @@ func (sqe *SonarQube) GetSonarAnalysis(analysisID string) ([]byte, error) { func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { queryParams := sqe.createQueryParam(nil, "id", taskID) sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.taskAPIPath - - // Create a new HTTP request - req, err := http.NewRequest("GET", sonarServerURL, nil) + req, err := http.NewRequest(http.MethodGet, sonarServerURL, nil) if err != nil { return nil, err } - // Add query parameters to the request q := req.URL.Query() for key, value := range queryParams { q.Add(key, value) } req.URL.RawQuery = q.Encode() - resp, bytes, err := sqe.sendRequestUsingSonarQubeToken(req, sqe.Proxy) if err != nil { return bytes, err } + defer func() { + if cerr := resp.Body.Close(); cerr != nil { + log.Error("Failed to close response body: " + cerr.Error()) + } + }() if resp.StatusCode != http.StatusOK { return nil, errorutils.CheckErrorf("Failed to get SonarQube task report. Status code: %d", resp.StatusCode) } - - defer func(Body io.ReadCloser) { - err := Body.Close() - if err != nil { - log.Error("Failed to close response body: " + err.Error()) - } - }(resp.Body) - body, err := io.ReadAll(resp.Body) - log.Debug("SonarQube response: " + string(body)) if err != nil { return nil, err } @@ -140,9 +134,9 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request, proxy string) (*http.Response, []byte, error) { // Add Authorization header - sonarQubeToken := os.Getenv("JF_SONARQUBE_ACCESS_TOKEN") + sonarQubeToken := os.Getenv(sonarAccessTokenKey) if sonarQubeToken == "" { - return nil, nil, errorutils.CheckErrorf("SonarQube access token not found in environment variable JF_SONARQUBE_ACCESS_TOKEN") + return nil, nil, errorutils.CheckErrorf("Sonar access token not found in environment variable " + sonarAccessTokenKey) } req.Header.Set("Authorization", "Bearer "+sonarQubeToken) httpClient := createHttpClient(proxy) diff --git a/evidence/manager.go b/evidence/manager.go index 5ab977533..0b59d2de9 100644 --- a/evidence/manager.go +++ b/evidence/manager.go @@ -46,7 +46,7 @@ func (esm *EvidenceServicesManager) FetchSonarTaskStatus(taskID, sonarQubeURL, p return sonarTaskStatus.CollectSonarQubePredicate(taskID) } -func (esm *EvidenceServicesManager) FetchSonarComponentAnalysis(analysisID, sonarQubeURL, proxy string) ([]byte, error) { +func (esm *EvidenceServicesManager) GetSonarAnalysisReport(analysisID, sonarQubeURL, proxy string) ([]byte, error) { sonarAnalysisReport := sonarqube.NewSonarQubeEvidence(sonarQubeURL, proxy) return sonarAnalysisReport.GetSonarAnalysis(analysisID) } From c881b076205f5ac486729ecdce6690772ce46573 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Wed, 21 May 2025 15:27:14 +0530 Subject: [PATCH 6/8] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb7176097..df8109059 100644 --- a/README.md +++ b/README.md @@ -3060,7 +3060,7 @@ sonarQubeURL := "http://localhost:9000" proxy := "" body, err := evidenceManager.FetchSonarTaskStatus(taskID, sonarQubeURL, proxy) ``` -#### Fetch Sonar Task Report with Proxy +#### Fetch Sonar Analysis Report ```go // Retrieves the analysis report from SonarQube by analysis ID. From 6a4cfafe18654be5b7a6dbb6b0667ebbbb98a664 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Sun, 8 Jun 2025 19:04:57 +0530 Subject: [PATCH 7/8] Renamed the constant --- evidence/external/sonarqube/sonarqube.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index d7e9df821..5d5b6b7f0 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -10,7 +10,7 @@ import ( "time" ) -const sonarAccessTokenKey = "JF_SONARQUBE_ACCESS_TOKEN" +const SonarAccessTokenKey = "JF_SONARQUBE_ACCESS_TOKEN" type SonarQube struct { Proxy string @@ -134,9 +134,9 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request, proxy string) (*http.Response, []byte, error) { // Add Authorization header - sonarQubeToken := os.Getenv(sonarAccessTokenKey) + sonarQubeToken := os.Getenv(SonarAccessTokenKey) if sonarQubeToken == "" { - return nil, nil, errorutils.CheckErrorf("Sonar access token not found in environment variable " + sonarAccessTokenKey) + return nil, nil, errorutils.CheckErrorf("Sonar access token not found in environment variable " + SonarAccessTokenKey) } req.Header.Set("Authorization", "Bearer "+sonarQubeToken) httpClient := createHttpClient(proxy) From 5056698f2bee4254ba838b3c70d604e5c3a35ac5 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 7 Jul 2025 12:17:44 +0530 Subject: [PATCH 8/8] Improved log message and commen --- evidence/external/sonarqube/sonarqube.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/evidence/external/sonarqube/sonarqube.go b/evidence/external/sonarqube/sonarqube.go index 5d5b6b7f0..9000b906f 100644 --- a/evidence/external/sonarqube/sonarqube.go +++ b/evidence/external/sonarqube/sonarqube.go @@ -68,17 +68,15 @@ func createHttpClient(proxy string) *http.Client { } func (sqe *SonarQube) GetSonarAnalysis(analysisID string) ([]byte, error) { - log.Debug("Fetching sonar analysis for given analysisID: " + analysisID) + log.Debug("Fetching quality gate analysis for analysisID" + analysisID) queryParams := sqe.createQueryParam(nil, "analysisId", analysisID) sonarServerURL := sqe.ServiceConfig.url + sqe.ServiceConfig.projectStatusAPIPath - // Create a new HTTP request req, err := http.NewRequest("GET", sonarServerURL, nil) if err != nil { return nil, err } - // Add query parameters to the request q := req.URL.Query() for key, value := range queryParams { q.Add(key, value) @@ -91,7 +89,7 @@ func (sqe *SonarQube) GetSonarAnalysis(analysisID string) ([]byte, error) { defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - log.Error("Failed to close response body: " + err.Error()) + log.Error("Failed to close response body" + err.Error()) } }(resp.Body) body, err := io.ReadAll(resp.Body) @@ -119,7 +117,7 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { } defer func() { if cerr := resp.Body.Close(); cerr != nil { - log.Error("Failed to close response body: " + cerr.Error()) + log.Error("Failed to close response body" + cerr.Error()) } }() if resp.StatusCode != http.StatusOK { @@ -133,15 +131,12 @@ func (sqe *SonarQube) CollectSonarQubePredicate(taskID string) ([]byte, error) { } func (sqe *SonarQube) sendRequestUsingSonarQubeToken(req *http.Request, proxy string) (*http.Response, []byte, error) { - // Add Authorization header sonarQubeToken := os.Getenv(SonarAccessTokenKey) if sonarQubeToken == "" { return nil, nil, errorutils.CheckErrorf("Sonar access token not found in environment variable " + SonarAccessTokenKey) } req.Header.Set("Authorization", "Bearer "+sonarQubeToken) httpClient := createHttpClient(proxy) - - // Send the request using the standard HTTP client resp, err := httpClient.Do(req) if err != nil { return nil, nil, err