@@ -3,13 +3,10 @@ package commands
3
3
import (
4
4
"context"
5
5
"errors"
6
- "fmt "
6
+ coreconfig "github.com/jfrog/jfrog-cli-core/v2/utils/config "
7
7
"os"
8
8
"os/exec"
9
9
"path/filepath"
10
- "strings"
11
-
12
- coreconfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
13
10
14
11
"github.com/jfrog/frogbot/commands/utils"
15
12
"github.com/jfrog/froggit-go/vcsclient"
@@ -28,8 +25,7 @@ const (
28
25
noGitHubEnvReviewersErr = "frogbot did not scan this PR, because the existing GitHub Environment named 'frogbot' doesn't have reviewers selected. Please refer to the Frogbot documentation for instructions on how to create the Environment"
29
26
)
30
27
31
- type ScanPullRequestCmd struct {
32
- }
28
+ type ScanPullRequestCmd struct {}
33
29
34
30
// Run ScanPullRequest method only works for single repository scan.
35
31
// Therefore, the first repository config represents the repository on which Frogbot runs, and it is the only one that matters.
@@ -55,49 +51,58 @@ func scanPullRequest(repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsCl
55
51
if len (repoConfig .Branches ) == 0 {
56
52
return & utils.ErrMissingEnv {VariableName : utils .GitBaseBranchEnv }
57
53
}
54
+
58
55
// Audit PR code
56
+ vulnerabilitiesRows , err := auditPullRequest (repoConfig , client )
57
+ if err != nil {
58
+ return err
59
+ }
60
+
61
+ // Create pull request message
62
+ message := createPullRequestMessage (vulnerabilitiesRows , repoConfig .OutputWriter )
63
+
64
+ // Add comment to the pull request
65
+ if err = client .AddPullRequestComment (context .Background (), repoConfig .RepoOwner , repoConfig .RepoName , message , repoConfig .PullRequestID ); err != nil {
66
+ return errors .New ("couldn't add pull request comment: " + err .Error ())
67
+ }
68
+
69
+ // Fail the Frogbot task, if a security issue is found and Frogbot isn't configured to avoid the failure.
70
+ if repoConfig .FailOnSecurityIssues != nil && * repoConfig .FailOnSecurityIssues && len (vulnerabilitiesRows ) > 0 {
71
+ err = errors .New (securityIssueFoundErr )
72
+ }
73
+ return err
74
+ }
75
+
76
+ func auditPullRequest (repoConfig * utils.FrogbotRepoConfig , client vcsclient.VcsClient ) ([]formats.VulnerabilityOrViolationRow , error ) {
59
77
xrayScanParams := createXrayScanParams (repoConfig .Watches , repoConfig .JFrogProjectKey )
60
78
var vulnerabilitiesRows []formats.VulnerabilityOrViolationRow
61
79
for _ , project := range repoConfig .Projects {
62
80
currentScan , isMultipleRoot , err := auditSource (xrayScanParams , project , & repoConfig .Server )
63
81
if err != nil {
64
- return err
82
+ return nil , err
65
83
}
66
84
if repoConfig .IncludeAllVulnerabilities {
67
85
log .Info ("Frogbot is configured to show all vulnerabilities" )
68
86
allIssuesRows , err := createAllIssuesRows (currentScan , isMultipleRoot )
69
87
if err != nil {
70
- return err
88
+ return nil , err
71
89
}
72
90
vulnerabilitiesRows = append (vulnerabilitiesRows , allIssuesRows ... )
73
91
continue
74
92
}
75
93
// Audit target code
76
94
previousScan , isMultipleRoot , err := auditTarget (client , xrayScanParams , project , repoConfig .Branches [0 ], & repoConfig .Git , & repoConfig .Server )
77
95
if err != nil {
78
- return err
96
+ return nil , err
79
97
}
80
98
newIssuesRows , err := createNewIssuesRows (previousScan , currentScan , isMultipleRoot )
81
99
if err != nil {
82
- return err
100
+ return nil , err
83
101
}
84
102
vulnerabilitiesRows = append (vulnerabilitiesRows , newIssuesRows ... )
85
103
}
86
-
87
104
log .Info ("Xray scan completed" )
88
-
89
- // Frogbot adds a comment on the PR.
90
- getTitleFunc , getSeverityTagFunc := getCommentFunctions (repoConfig .SimplifiedOutput )
91
- message := createPullRequestMessage (vulnerabilitiesRows , getTitleFunc , getSeverityTagFunc )
92
- err := client .AddPullRequestComment (context .Background (), repoConfig .RepoOwner , repoConfig .RepoName , message , repoConfig .PullRequestID )
93
- if err != nil {
94
- return errors .New ("couldn't add pull request comment: " + err .Error ())
95
- }
96
- // Fail the Frogbot task, if a security issue is found and Frogbot isn't configured to avoid the failure.
97
- if repoConfig .FailOnSecurityIssues != nil && * repoConfig .FailOnSecurityIssues && len (vulnerabilitiesRows ) > 0 {
98
- err = errors .New (securityIssueFoundErr )
99
- }
100
- return err
105
+ return vulnerabilitiesRows , nil
101
106
}
102
107
103
108
// Verify that the 'frogbot' GitHub environment was properly configured on the repository
@@ -132,15 +137,6 @@ func verifyGitHubFrogbotEnvironment(client vcsclient.VcsClient, repoConfig *util
132
137
return nil
133
138
}
134
139
135
- func getCommentFunctions (simplifiedOutput bool ) (utils.GetTitleFunc , utils.GetSeverityTagFunc ) {
136
- if simplifiedOutput {
137
- return utils .GetSimplifiedTitle , func (name utils.IconName ) string {
138
- return ""
139
- }
140
- }
141
- return utils .GetBanner , utils .GetSeverityTag
142
- }
143
-
144
140
// Create vulnerabilities rows. The rows should contain only the new issues added by this PR
145
141
func createNewIssuesRows (previousScan , currentScan []services.ScanResponse , isMultipleRoot bool ) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow , err error ) {
146
142
previousScanAggregatedResults := aggregateScanResults (previousScan )
@@ -337,33 +333,18 @@ func getUniqueID(vulnerability formats.VulnerabilityOrViolationRow) string {
337
333
return vulnerability .ImpactedDependencyName + vulnerability .ImpactedDependencyVersion + vulnerability .IssueId
338
334
}
339
335
340
- func createPullRequestMessage (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow , getBanner utils.GetTitleFunc , getSeverityTag utils. GetSeverityTagFunc ) string {
336
+ func createPullRequestMessage (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow , writer utils.OutputWriter ) string {
341
337
if len (vulnerabilitiesRows ) == 0 {
342
- return getBanner ( utils . NoVulnerabilityBannerSource ) + utils . WhatIsFrogbotMd
338
+ return writer . NoVulnerabilitiesTitle ()
343
339
}
340
+ tableContent := getTableContent (vulnerabilitiesRows , writer )
341
+ return writer .VulnerabiltiesTitle () + writer .TableHeader () + tableContent
342
+ }
343
+
344
+ func getTableContent (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow , writer utils.OutputWriter ) string {
344
345
var tableContent string
345
346
for _ , vulnerability := range vulnerabilitiesRows {
346
- var cve string
347
- var directDependencies , directDependenciesVersions strings.Builder
348
- if len (vulnerability .Components ) > 0 {
349
- for _ , dependency := range vulnerability .Components {
350
- directDependencies .WriteString (fmt .Sprintf ("%s; " , dependency .Name ))
351
- directDependenciesVersions .WriteString (fmt .Sprintf ("%s; " , dependency .Version ))
352
- }
353
- }
354
- if len (vulnerability .Cves ) > 0 {
355
- cve = vulnerability .Cves [0 ].Id
356
- }
357
- fixedVersionString := strings .Join (vulnerability .FixedVersions , " " )
358
- tableContent += fmt .Sprintf ("\n | %s%8s | %s | %s | %s | %s | %s | %s " ,
359
- getSeverityTag (utils .IconName (vulnerability .Severity )),
360
- vulnerability .Severity ,
361
- strings .TrimSuffix (directDependencies .String (), "; " ),
362
- strings .TrimSuffix (directDependenciesVersions .String (), "; " ),
363
- vulnerability .ImpactedDependencyName ,
364
- vulnerability .ImpactedDependencyVersion ,
365
- fixedVersionString ,
366
- cve )
367
- }
368
- return getBanner (utils .VulnerabilitiesBannerSource ) + utils .WhatIsFrogbotMd + utils .TableHeader + tableContent
347
+ tableContent += writer .TableRow (vulnerability )
348
+ }
349
+ return tableContent
369
350
}
0 commit comments