Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor output writer #514

Merged
merged 53 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
b62cdee
Add Sast and Review tests
attiasas Sep 21, 2023
9fe0e79
add sast test, fix other jas
attiasas Sep 21, 2023
213885a
start adding review tests
attiasas Sep 21, 2023
bb45375
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Sep 27, 2023
cf521d3
done output tests
attiasas Sep 27, 2023
9e12379
done tests implementation, start combine writer
attiasas Sep 28, 2023
e7f823a
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Sep 28, 2023
55359f4
fix tests
attiasas Sep 28, 2023
9fcc04f
combine Jas output
attiasas Sep 28, 2023
e1d5a1c
combine more
attiasas Sep 28, 2023
da4f7bb
more combine
attiasas Oct 1, 2023
31ee4f4
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 1, 2023
a743ed6
rename subTitleDepth
attiasas Oct 3, 2023
b3f0a3c
combine more
attiasas Oct 3, 2023
96cbf22
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 3, 2023
3040fda
combine more
attiasas Oct 3, 2023
007822e
combine more
attiasas Oct 4, 2023
2c3ffaf
finish markdown table
attiasas Oct 4, 2023
648f50e
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 4, 2023
5d217ee
tidy
attiasas Oct 4, 2023
55e06f0
done combine implementations
attiasas Oct 5, 2023
b5457f1
done merge
attiasas Oct 5, 2023
25f72be
combine sast tests
attiasas Oct 5, 2023
cdfd14e
combine iac tests
attiasas Oct 5, 2023
845b917
combine applicable tests
attiasas Oct 5, 2023
a2d580c
finish combine review comment content
attiasas Oct 5, 2023
1d6d3a1
fix static test
attiasas Oct 5, 2023
1fac667
combine more, add tests for summary structure
attiasas Oct 8, 2023
7828e24
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 8, 2023
07fe11c
fix merge
attiasas Oct 8, 2023
6437b98
done content tests
attiasas Oct 8, 2023
ed1ed43
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 8, 2023
1d82c6b
add tests to comment content filter
attiasas Oct 8, 2023
35a32a6
cleanup
attiasas Oct 8, 2023
b8b4a82
fix scan all pull requests tests
attiasas Oct 9, 2023
7bd8dcd
start fix scan pull request
attiasas Oct 9, 2023
b438381
fix tests
attiasas Oct 9, 2023
6bdb0d1
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 9, 2023
c77c9fc
finish all output writer tests
attiasas Oct 9, 2023
fa8142c
start adjust content format, spaces and new lines
attiasas Oct 9, 2023
196b149
fix tests
attiasas Oct 9, 2023
5f2072a
fix all tests
attiasas Oct 10, 2023
8d3c082
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 10, 2023
8953f81
fix tests
attiasas Oct 10, 2023
e2b188d
fix tests
attiasas Oct 10, 2023
d578f57
fix pip tests
attiasas Oct 10, 2023
618bf91
fix
attiasas Oct 10, 2023
75fadb3
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 11, 2023
2d45ff2
fix merge
attiasas Oct 11, 2023
5d0698c
remove unused
attiasas Oct 11, 2023
ed92fd2
Merge remote-tracking branch 'upstream/dev' into add_sast_and_review_…
attiasas Oct 15, 2023
f0cce5a
review changes
attiasas Oct 16, 2023
96ca263
remove comments
attiasas Oct 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix merge
  • Loading branch information
attiasas committed Oct 11, 2023
commit 2d45ff219c56c4e52390faef970150a118d75f13
1 change: 0 additions & 1 deletion scanpullrequest/scanpullrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"os"

"golang.org/x/exp/slices"
"os"

"github.com/jfrog/frogbot/utils"
"github.com/jfrog/froggit-go/vcsclient"
Expand Down
98 changes: 48 additions & 50 deletions utils/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,69 @@ const (
SastComment ReviewCommentType = "Sast"

RescanRequestComment = "rescan"

frogbotCommentNotFound = -1
)

func HandlePullRequestCommentsAfterScan(issues *IssuesCollection, repo *Repository, client vcsclient.VcsClient, pullRequestID int) (err error) {
// Delete previous Frogbot pull request message if exists
if err = DeleteExistingPullRequestComment(repo, client); err != nil {
return
if !repo.Params.AvoidPreviousPrCommentsDeletion {
log.Debug("Looking for an existing Frogbot pull request comment. Deleting it if it exists...")
// Delete previous PR regular comments, if exists (not related to location of a change)
if err = DeleteExistingPullRequestComments(repo, client); err != nil {
err = errors.New("couldn't delete pull request comment: " + err.Error())
return
}
// Delete previous PR review comments, if exists (related to location of a change)
if err = DeleteExistingPullRequestReviewComments(repo, pullRequestID, client); err != nil {
err = errors.New("couldn't delete pull request review comment: " + err.Error())
return
}
}

// Create a pull request message
message := GeneratePullRequestSummaryComment(issues, repo.OutputWriter)

// Add SCA scan comment
if err = client.AddPullRequestComment(context.Background(), repo.RepoOwner, repo.RepoName, message, pullRequestID); err != nil {
// Add summary (SCA, license) scan comment
if err = client.AddPullRequestComment(context.Background(), repo.RepoOwner, repo.RepoName, generatePullRequestSummaryComment(issues, repo.OutputWriter), pullRequestID); err != nil {
err = errors.New("couldn't add pull request comment: " + err.Error())
return
}

// Handle review comments at the pull request
if err = AddReviewComments(repo, pullRequestID, client, issues); err != nil {
if err = addReviewComments(repo, pullRequestID, client, issues); err != nil {
err = errors.New("couldn't add review comments: " + err.Error())
return
}
return
}

// Delete existing pull request regular comments (Summary, Fallback review comments)
func DeleteExistingPullRequestComments(repository *Repository, client vcsclient.VcsClient) error {
prDetails := repository.PullRequestDetails
comments, err := GetSortedPullRequestComments(client, prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID))
if err != nil {
return fmt.Errorf(
"failed to get comments. the following details were used in order to fetch the comments: <%s/%s> pull request #%d. the error received: %s",
repository.RepoOwner, repository.RepoName, int(repository.PullRequestDetails.ID), err.Error())
}
// Previous Fallback review comments
commentsToDelete := getFrogbotReviewComments(comments)
// Previous Summary comments
for _, comment := range comments {
if outputwriter.IsFrogbotSummaryComment(repository.OutputWriter, comment.Content) {
commentsToDelete = append(commentsToDelete, comment)
}
}
// Delete
if len(commentsToDelete) > 0 {
for _, commentToDelete := range commentsToDelete {
if err = client.DeletePullRequestComment(context.Background(), prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID), int(commentToDelete.ID)); err != nil {
return err
}
}
}
return err
}

func GenerateFixPullRequestDetails(vulnerabilities []formats.VulnerabilityOrViolationRow, writer outputwriter.OutputWriter) string {
return outputwriter.GetPRSummaryContent(outputwriter.VulnerabilitiesContent(vulnerabilities, writer), true, false, writer)
}

func GeneratePullRequestSummaryComment(issuesCollection *IssuesCollection, writer outputwriter.OutputWriter) string {
func generatePullRequestSummaryComment(issuesCollection *IssuesCollection, writer outputwriter.OutputWriter) string {
issuesExists := false
content := strings.Builder{}

Expand Down Expand Up @@ -86,41 +117,7 @@ func GetSortedPullRequestComments(client vcsclient.VcsClient, repoOwner, repoNam
return pullRequestsComments, nil
}

func DeleteExistingPullRequestComment(repository *Repository, client vcsclient.VcsClient) error {
log.Debug("Looking for an existing Frogbot pull request comment. Deleting it if it exists...")
prDetails := repository.PullRequestDetails
comments, err := GetSortedPullRequestComments(client, prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID))
if err != nil {
return fmt.Errorf(
"failed to get comments. the following details were used in order to fetch the comments: <%s/%s> pull request #%d. the error received: %s",
repository.RepoOwner, repository.RepoName, int(repository.PullRequestDetails.ID), err.Error())
}

commentID := frogbotCommentNotFound
for _, comment := range comments {
if outputwriter.IsFrogbotSummaryComment(repository.OutputWriter, comment.Content) {
log.Debug("Found previous Frogbot comment with the id:", comment.ID)
commentID = int(comment.ID)
break
}
}

if commentID != frogbotCommentNotFound {
err = client.DeletePullRequestComment(context.Background(), prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID), commentID)
}

return err
}

func AddReviewComments(repo *Repository, pullRequestID int, client vcsclient.VcsClient, issues *IssuesCollection) (err error) {
if err = deleteOldReviewComments(repo, pullRequestID, client); err != nil {
err = errors.New("couldn't delete pull request review comment: " + err.Error())
return
}
if err = deleteOldFallbackComments(repo, pullRequestID, client); err != nil {
err = errors.New("couldn't delete pull request comment: " + err.Error())
return
}
func addReviewComments(repo *Repository, pullRequestID int, client vcsclient.VcsClient, issues *IssuesCollection) (err error) {
commentsToAdd := getNewReviewComments(repo, issues)
if len(commentsToAdd) == 0 {
return
Expand All @@ -139,8 +136,9 @@ func AddReviewComments(repo *Repository, pullRequestID int, client vcsclient.Vcs
return
}

func deleteOldReviewComments(repo *Repository, pullRequestID int, client vcsclient.VcsClient) (err error) {
// Get all comments in PR
// Delete existing pull request review comments (Applicable, Sast, Iac)
func DeleteExistingPullRequestReviewComments(repo *Repository, pullRequestID int, client vcsclient.VcsClient) (err error) {
// Get all review comments in PR
var existingComments []vcsclient.CommentInfo
if existingComments, err = client.ListPullRequestReviewComments(context.Background(), repo.RepoOwner, repo.RepoName, pullRequestID); err != nil {
err = errors.New("couldn't list existing review comments: " + err.Error())
Expand Down
111 changes: 0 additions & 111 deletions utils/comment_test.go
Original file line number Diff line number Diff line change
@@ -1,126 +1,15 @@
package utils

import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/jfrog/frogbot/utils/outputwriter"
"github.com/jfrog/froggit-go/vcsclient"
"github.com/jfrog/froggit-go/vcsutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/xray/formats"
"github.com/stretchr/testify/assert"
)

func TestCreatePullRequestMessageNoVulnerabilities(t *testing.T) {
vulnerabilities := []formats.VulnerabilityOrViolationRow{}
message := createPullRequestComment(&IssuesCollection{Vulnerabilities: vulnerabilities}, &outputwriter.StandardOutput{})

expectedMessageByte, err := os.ReadFile(filepath.Join("..", "testdata", "messages", "novulnerabilities.md"))
assert.NoError(t, err)
expectedMessage := strings.ReplaceAll(string(expectedMessageByte), "\r\n", "\n")
assert.Equal(t, expectedMessage, message)

outputWriter := &outputwriter.StandardOutput{}
outputWriter.SetVcsProvider(vcsutils.GitLab)
message = createPullRequestComment(&IssuesCollection{Vulnerabilities: vulnerabilities}, outputWriter)

expectedMessageByte, err = os.ReadFile(filepath.Join("..", "testdata", "messages", "novulnerabilitiesMR.md"))
assert.NoError(t, err)
expectedMessage = strings.ReplaceAll(string(expectedMessageByte), "\r\n", "\n")
assert.Equal(t, expectedMessage, message)
}

func TestCreatePullRequestComment(t *testing.T) {
vulnerabilities := []formats.VulnerabilityOrViolationRow{
{
Summary: "Summary XRAY-122345",
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
SeverityDetails: formats.SeverityDetails{Severity: "High"},
ImpactedDependencyName: "github.com/nats-io/nats-streaming-server",
ImpactedDependencyVersion: "v0.21.0",
Components: []formats.ComponentRow{
{
Name: "github.com/nats-io/nats-streaming-server",
Version: "v0.21.0",
},
},
},
Applicable: "Undetermined",
FixedVersions: []string{"[0.24.1]"},
IssueId: "XRAY-122345",
Cves: []formats.CveRow{{}},
},
{
Summary: "Summary",
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
SeverityDetails: formats.SeverityDetails{Severity: "High"},
ImpactedDependencyName: "github.com/mholt/archiver/v3",
ImpactedDependencyVersion: "v3.5.1",
Components: []formats.ComponentRow{
{
Name: "github.com/mholt/archiver/v3",
Version: "v3.5.1",
},
},
},
Applicable: "Undetermined",
Cves: []formats.CveRow{},
},
{
Summary: "Summary CVE-2022-26652",
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
SeverityDetails: formats.SeverityDetails{Severity: "Medium"},
ImpactedDependencyName: "github.com/nats-io/nats-streaming-server",
ImpactedDependencyVersion: "v0.21.0",
Components: []formats.ComponentRow{
{
Name: "github.com/nats-io/nats-streaming-server",
Version: "v0.21.0",
},
},
},
Applicable: "Undetermined",
FixedVersions: []string{"[0.24.3]"},
Cves: []formats.CveRow{{Id: "CVE-2022-26652"}},
},
}
licenses := []formats.LicenseRow{
{
LicenseKey: "Apache-2.0",
ImpactedDependencyDetails: formats.ImpactedDependencyDetails{
SeverityDetails: formats.SeverityDetails{Severity: "High", SeverityNumValue: 13},
ImpactedDependencyName: "minimatch",
ImpactedDependencyVersion: "1.2.3",
Components: []formats.ComponentRow{
{
Name: "root",
Version: "1.0.0",
},
{
Name: "minimatch",
Version: "1.2.3",
},
},
},
},
}

writerOutput := &outputwriter.StandardOutput{}
writerOutput.SetJasOutputFlags(true, true)
message := createPullRequestComment(&IssuesCollection{Vulnerabilities: vulnerabilities, Licenses: licenses}, writerOutput)

expectedMessage := "<div align='center'>\n\n[![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/vulnerabilitiesBannerPR.png)](https://github.com/jfrog/frogbot#readme)\n\n</div>\n\n\n## 📦 Vulnerable Dependencies\n\n### ✍️ Summary\n\n<div align=\"center\">\n\n| SEVERITY | CONTEXTUAL ANALYSIS | DIRECT DEPENDENCIES | IMPACTED DEPENDENCY | FIXED VERSIONS | CVES |\n| :---------------------: | :----------------------------------: | :----------------------------------: | :-----------------------------------: | :---------------------------------: | :---------------------------------: | \n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableHighSeverity.png)<br> High | Undetermined | github.com/nats-io/nats-streaming-server:v0.21.0 | github.com/nats-io/nats-streaming-server:v0.21.0 | [0.24.1] | - |\n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableHighSeverity.png)<br> High | Undetermined | github.com/mholt/archiver/v3:v3.5.1 | github.com/mholt/archiver/v3:v3.5.1 | - | - |\n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableMediumSeverity.png)<br> Medium | Undetermined | github.com/nats-io/nats-streaming-server:v0.21.0 | github.com/nats-io/nats-streaming-server:v0.21.0 | [0.24.3] | CVE-2022-26652 |\n\n</div>\n\n## 🔬 Research Details\n\n<details>\n<summary> <b>[ XRAY-122345 ] github.com/nats-io/nats-streaming-server v0.21.0</b> </summary>\n<br>\n\n**Description:**\nSummary XRAY-122345\n\n\n</details>\n\n\n<details>\n<summary> <b>github.com/mholt/archiver/v3 v3.5.1</b> </summary>\n<br>\n\n**Description:**\nSummary\n\n\n</details>\n\n\n<details>\n<summary> <b>[ CVE-2022-26652 ] github.com/nats-io/nats-streaming-server v0.21.0</b> </summary>\n<br>\n\n**Description:**\nSummary CVE-2022-26652\n\n\n</details>\n\n\n## ⚖️ Violated Licenses \n\n<div align=\"center\">\n\n\n| LICENSE | DIRECT DEPENDENCIES | IMPACTED DEPENDENCY | \n| :---------------------: | :----------------------------------: | :-----------------------------------: | \n| Apache-2.0 | root 1.0.0<br>minimatch 1.2.3 | minimatch 1.2.3 |\n\n</div>\n\n\n---\n<div align=\"center\">\n\n[🐸 JFrog Frogbot](https://github.com/jfrog/frogbot#readme)\n\n</div>"
assert.Equal(t, expectedMessage, message)

writerOutput.SetVcsProvider(vcsutils.GitLab)
message = createPullRequestComment(&IssuesCollection{Vulnerabilities: vulnerabilities}, writerOutput)
expectedMessage = "<div align='center'>\n\n[![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/vulnerabilitiesBannerMR.png)](https://github.com/jfrog/frogbot#readme)\n\n</div>\n\n\n## 📦 Vulnerable Dependencies\n\n### ✍️ Summary\n\n<div align=\"center\">\n\n| SEVERITY | CONTEXTUAL ANALYSIS | DIRECT DEPENDENCIES | IMPACTED DEPENDENCY | FIXED VERSIONS | CVES |\n| :---------------------: | :----------------------------------: | :----------------------------------: | :-----------------------------------: | :---------------------------------: | :---------------------------------: | \n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableHighSeverity.png)<br> High | Undetermined | github.com/nats-io/nats-streaming-server:v0.21.0 | github.com/nats-io/nats-streaming-server:v0.21.0 | [0.24.1] | - |\n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableHighSeverity.png)<br> High | Undetermined | github.com/mholt/archiver/v3:v3.5.1 | github.com/mholt/archiver/v3:v3.5.1 | - | - |\n| ![](https://raw.githubusercontent.com/jfrog/frogbot/master/resources/v2/applicableMediumSeverity.png)<br> Medium | Undetermined | github.com/nats-io/nats-streaming-server:v0.21.0 | github.com/nats-io/nats-streaming-server:v0.21.0 | [0.24.3] | CVE-2022-26652 |\n\n</div>\n\n## 🔬 Research Details\n\n<details>\n<summary> <b>[ XRAY-122345 ] github.com/nats-io/nats-streaming-server v0.21.0</b> </summary>\n<br>\n\n**Description:**\nSummary XRAY-122345\n\n\n</details>\n\n\n<details>\n<summary> <b>github.com/mholt/archiver/v3 v3.5.1</b> </summary>\n<br>\n\n**Description:**\nSummary\n\n\n</details>\n\n\n<details>\n<summary> <b>[ CVE-2022-26652 ] github.com/nats-io/nats-streaming-server v0.21.0</b> </summary>\n<br>\n\n**Description:**\nSummary CVE-2022-26652\n\n\n</details>\n\n\n---\n<div align=\"center\">\n\n[🐸 JFrog Frogbot](https://github.com/jfrog/frogbot#readme)\n\n</div>"
assert.Equal(t, expectedMessage, message)
}

func TestGetFrogbotReviewComments(t *testing.T) {
testCases := []struct {
name string
Expand Down
Loading