github.com/jfrog/frogbot@v1.1.1-0.20231221090046-821a26f50338/scanpullrequest/scanallpullrequests.go (about) 1 package scanpullrequest 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 8 "github.com/jfrog/frogbot/utils" 9 "github.com/jfrog/frogbot/utils/outputwriter" 10 "github.com/jfrog/jfrog-client-go/utils/log" 11 12 "github.com/jfrog/froggit-go/vcsclient" 13 ) 14 15 var errPullRequestScan = "pull request #%d scan in the '%s' repository returned the following error:\n%s" 16 17 type ScanAllPullRequestsCmd struct { 18 } 19 20 func (cmd ScanAllPullRequestsCmd) Run(configAggregator utils.RepoAggregator, client vcsclient.VcsClient, frogbotRepoConnection *utils.UrlAccessChecker) error { 21 for _, config := range configAggregator { 22 log.Info("Scanning all open pull requests for repository:", config.RepoName) 23 log.Info("-----------------------------------------------------------") 24 config.OutputWriter.SetHasInternetConnection(frogbotRepoConnection.IsConnected()) 25 err := scanAllPullRequests(config, client) 26 if err != nil { 27 return err 28 } 29 } 30 return nil 31 } 32 33 // Scan pull requests as follows: 34 // a. Retrieve all open pull requests 35 // b. Find the ones that should be scanned (new PRs or PRs with a 're-scan' comment) 36 // c. Audit the dependencies of the source and the target branches. 37 // d. Compare the vulnerabilities found in source and target branches, and show only the new vulnerabilities added by the pull request. 38 func scanAllPullRequests(repo utils.Repository, client vcsclient.VcsClient) (err error) { 39 openPullRequests, err := client.ListOpenPullRequests(context.Background(), repo.RepoOwner, repo.RepoName) 40 if err != nil { 41 return err 42 } 43 for _, pr := range openPullRequests { 44 shouldScan, e := shouldScanPullRequest(repo, client, int(pr.ID)) 45 if e != nil { 46 err = errors.Join(err, fmt.Errorf(errPullRequestScan, int(pr.ID), repo.RepoName, e.Error())) 47 } 48 if !shouldScan { 49 log.Info("Pull Request", pr.ID, "has already been scanned before. If you wish to scan it again, please comment \"rescan\".") 50 return 51 } 52 repo.PullRequestDetails = pr 53 if e = scanPullRequest(&repo, client); e != nil { 54 // If error, write it in errList and continue to the next PR. 55 err = errors.Join(err, fmt.Errorf(errPullRequestScan, int(pr.ID), repo.RepoName, e.Error())) 56 } 57 } 58 return 59 } 60 61 func shouldScanPullRequest(repo utils.Repository, client vcsclient.VcsClient, prID int) (shouldScan bool, err error) { 62 pullRequestsComments, err := utils.GetSortedPullRequestComments(client, repo.RepoOwner, repo.RepoName, prID) 63 if err != nil { 64 return 65 } 66 67 for _, comment := range pullRequestsComments { 68 // If this a 're-scan' request comment 69 if utils.IsFrogbotRescanComment(comment.Content) { 70 return true, nil 71 } 72 // if this is a Frogbot 'scan results' comment and not 're-scan' request comment, do not scan this pull request. 73 if outputwriter.IsFrogbotSummaryComment(repo.OutputWriter, comment.Content) { 74 return false, nil 75 } 76 } 77 // This is a new pull request, and it therefore should be scanned. 78 return true, nil 79 }