Skip to content

Commit

Permalink
Use tasks for high severity report on BitBucket
Browse files Browse the repository at this point in the history
  • Loading branch information
prymitive committed Dec 8, 2023
1 parent 2110197 commit 2ba76de
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 56 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
To avoid any errors or slowdowns from scanning unrelated files you might need
to add `ci` section to `.pint.hcl` with `include` and/or `exclude` options set.
See [examples/ci.hcl](examples/ci.hcl) for an example config.
- `Bug` and `Fatal` severity problems are now reported as tasks when using
BitBucket.

## v0.50.1

Expand Down
185 changes: 142 additions & 43 deletions internal/reporter/bitbucket_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,22 +124,26 @@ type BitBucketFileDiffs struct {
}

type bitBucketComment struct {
id int
version int
text string
anchor BitBucketCommentAnchor
id int
version int
text string
severity string
anchor BitBucketCommentAnchor
replies int
}

type BitBucketCommentAuthor struct {
Name string `json:"name"`
}

type BitBucketPullRequestComment struct {
ID int `json:"id"`
Version int `json:"version"`
State string `json:"state"`
Author BitBucketCommentAuthor `json:"author"`
Text string `json:"text"`
ID int `json:"id"`
Version int `json:"version"`
State string `json:"state"`
Author BitBucketCommentAuthor `json:"author"`
Text string `json:"text"`
Severity string `json:"severity"`
Comments []BitBucketPullRequestComment `json:"comments"`
}

type BitBucketCommentAnchor struct {
Expand Down Expand Up @@ -181,10 +185,11 @@ type BitBucketPullRequestActivities struct {
}

type pendingComment struct {
text string
path string
line int
anchor checks.Anchor
severity string
text string
path string
line int
anchor checks.Anchor
}

func (pc pendingComment) toBitBucketComment(changes *bitBucketPRChanges) BitBucketPendingComment {
Expand All @@ -197,7 +202,7 @@ func (pc pendingComment) toBitBucketComment(changes *bitBucketPRChanges) BitBuck
FileType: "FROM",
},
Text: pc.text,
Severity: "NORMAL",
Severity: pc.severity,
}

if pc.anchor == checks.AnchorBefore {
Expand Down Expand Up @@ -233,6 +238,16 @@ type BitBucketPendingComment struct {
Anchor BitBucketPendingCommentAnchor `json:"anchor"`
}

type BitBucketCommentStateUpdate struct {
State string `json:"state"`
Version int `json:"version"`
}

type BitBucketCommentSeverityUpdate struct {
Severity string `json:"severity"`
Version int `json:"version"`
}

func newBitBucketAPI(pintVersion, uri string, timeout time.Duration, token, project, repo string) *bitBucketAPI {
return &bitBucketAPI{
pintVersion: pintVersion,
Expand Down Expand Up @@ -538,10 +553,12 @@ func (bb bitBucketAPI) getPullRequestComments(pr *bitBucketPR) ([]bitBucketComme
act.Comment.Author.Name == username &&
!act.CommentAnchor.Orphaned {
comments = append(comments, bitBucketComment{
id: act.Comment.ID,
version: act.Comment.Version,
text: act.Comment.Text,
anchor: act.CommentAnchor,
id: act.Comment.ID,
version: act.Comment.Version,
text: act.Comment.Text,
anchor: act.CommentAnchor,
severity: act.Comment.Severity,
replies: len(act.Comment.Comments),
})
}
}
Expand Down Expand Up @@ -590,11 +607,21 @@ func (bb bitBucketAPI) makeComments(summary Summary, changes *bitBucketPRChanges
buf.WriteString(reports[0].Problem.Reporter)
buf.WriteString(".html).\n")

var severity string
// nolint:exhaustive
switch reports[0].Problem.Severity {
case checks.Bug, checks.Fatal:
severity = "BLOCKER"
default:
severity = "NORMAL"
}

pending := pendingComment{
path: reports[0].ReportedPath,
line: reports[0].Problem.Lines[0],
text: buf.String(),
anchor: reports[0].Problem.Anchor,
severity: severity,
path: reports[0].ReportedPath,
line: reports[0].Problem.Lines[0],
text: buf.String(),
anchor: reports[0].Problem.Anchor,
}
comments = append(comments, pending.toBitBucketComment(changes))
}
Expand All @@ -614,32 +641,104 @@ func (bb bitBucketAPI) pruneComments(pr *bitBucketPR, currentComments []bitBucke
}
}
if !keep {
slog.Debug(
"Deleting stale comment",
slog.Int("id", cur.id),
slog.String("path", cur.anchor.Path),
slog.Int("line", cur.anchor.Line),
)
_, err := bb.request(
http.MethodDelete,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/comments/%d?version=%d",
bb.project, bb.repo,
pr.ID,
cur.id, cur.version,
),
nil,
)
if err != nil {
slog.Error(
"Failed to delete stale BitBucket pull request comment",
slog.Int("id", cur.id),
slog.Any("err", err),
)
switch {
case cur.replies == 0:
bb.deleteComment(pr, cur)
case cur.severity == "BLOCKER":
bb.resolveTask(pr, cur)
default:
bb.updateSeverity(pr, cur, "BLOCKER")
bb.resolveTask(pr, cur)
}
}
}
}

func (bb bitBucketAPI) deleteComment(pr *bitBucketPR, cur bitBucketComment) {
slog.Debug(
"Deleting stale comment",
slog.Int("id", cur.id),
slog.String("path", cur.anchor.Path),
slog.Int("line", cur.anchor.Line),
)
_, err := bb.request(
http.MethodDelete,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/comments/%d?version=%d",
bb.project, bb.repo,
pr.ID,
cur.id, cur.version,
),
nil,
)
if err != nil {
slog.Error(
"Failed to delete stale BitBucket pull request comment",
slog.Int("id", cur.id),
slog.Any("err", err),
)
}
}

func (bb bitBucketAPI) resolveTask(pr *bitBucketPR, cur bitBucketComment) {
slog.Debug(
"Resolving stale blocker comment",
slog.Int("id", cur.id),
slog.String("path", cur.anchor.Path),
slog.Int("line", cur.anchor.Line),
)
payload, _ := json.Marshal(BitBucketCommentStateUpdate{
State: "RESOLVED",
Version: cur.version,
})
_, err := bb.request(
http.MethodPut,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/comments/%d",
bb.project, bb.repo,
pr.ID,
cur.id,
),
bytes.NewReader(payload),
)
if err != nil {
slog.Error(
"Failed to resolve stale blocker BitBucket pull request comment",
slog.Int("id", cur.id),
slog.Any("err", err),
)
}
}

func (bb bitBucketAPI) updateSeverity(pr *bitBucketPR, cur bitBucketComment, severity string) {
slog.Debug(
"Updating comment severity",
slog.Int("id", cur.id),
slog.String("path", cur.anchor.Path),
slog.Int("line", cur.anchor.Line),
slog.String("from", cur.severity),
slog.String("to", severity),
)
payload, _ := json.Marshal(BitBucketCommentSeverityUpdate{
Severity: severity,
Version: cur.version,
})
_, err := bb.request(
http.MethodPut,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/comments/%d",
bb.project, bb.repo,
pr.ID,
cur.id,
),
bytes.NewReader(payload),
)
if err != nil {
slog.Error(
"Failed to update BitBucket pull request comment severity",
slog.Int("id", cur.id),
slog.Any("err", err),
)
}
}

func (bb bitBucketAPI) addComments(pr *bitBucketPR, currentComments []bitBucketComment, pendingComments []BitBucketPendingComment) error {
var added int
for _, pend := range pendingComments {
Expand Down
21 changes: 12 additions & 9 deletions internal/reporter/bitbucket_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ func TestPendingCommentToBitBucketComment(t *testing.T) {
{
description: "nil changes",
input: pendingComment{
text: "this is text",
path: "foo.yaml",
line: 5,
severity: "NORMAL",
text: "this is text",
path: "foo.yaml",
line: 5,
},
output: BitBucketPendingComment{
Text: "this is text",
Expand All @@ -42,9 +43,10 @@ func TestPendingCommentToBitBucketComment(t *testing.T) {
{
description: "path not found in changes",
input: pendingComment{
text: "this is text",
path: "foo.yaml",
line: 5,
severity: "NORMAL",
text: "this is text",
path: "foo.yaml",
line: 5,
},
output: BitBucketPendingComment{
Text: "this is text",
Expand All @@ -65,9 +67,10 @@ func TestPendingCommentToBitBucketComment(t *testing.T) {
{
description: "path found in changes",
input: pendingComment{
text: "this is text",
path: "foo.yaml",
line: 5,
severity: "NORMAL",
text: "this is text",
path: "foo.yaml",
line: 5,
},
output: BitBucketPendingComment{
Text: "this is text",
Expand Down
8 changes: 4 additions & 4 deletions internal/reporter/bitbucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ func TestBitBucketReporter(t *testing.T) {
pullRequestComments: []reporter.BitBucketPendingComment{
{
Text: ":stop_sign: **Bug** reported by [pint](https://cloudflare.github.io/pint/) **mock** check.\n\n------\n\nthis should be ignored, line is not part of the diff\n\n------\n\n:information_source: To see documentation covering this check and instructions on how to resolve it [click here](https://cloudflare.github.io/pint/checks/mock.html).\n",
Severity: "NORMAL",
Severity: "BLOCKER",
Anchor: reporter.BitBucketPendingCommentAnchor{
Path: "foo.txt",
Line: 1,
Expand All @@ -907,7 +907,7 @@ func TestBitBucketReporter(t *testing.T) {
},
{
Text: ":stop_sign: **Fatal** reported by [pint](https://cloudflare.github.io/pint/) **mock** check.\n\n------\n\nbad name\n\n------\n\n:information_source: To see documentation covering this check and instructions on how to resolve it [click here](https://cloudflare.github.io/pint/checks/mock.html).\n",
Severity: "NORMAL",
Severity: "BLOCKER",
Anchor: reporter.BitBucketPendingCommentAnchor{
Path: "foo.txt",
Line: 2,
Expand All @@ -918,7 +918,7 @@ func TestBitBucketReporter(t *testing.T) {
},
{
Text: ":stop_sign: **Bug** reported by [pint](https://cloudflare.github.io/pint/) **mock** check.\n\n------\n\nmock text\n\nmock details\n\n------\n\n:information_source: To see documentation covering this check and instructions on how to resolve it [click here](https://cloudflare.github.io/pint/checks/mock.html).\n",
Severity: "NORMAL",
Severity: "BLOCKER",
Anchor: reporter.BitBucketPendingCommentAnchor{
Path: "foo.txt",
Line: 2,
Expand Down Expand Up @@ -1630,7 +1630,7 @@ func TestBitBucketReporter(t *testing.T) {
pullRequestComments: []reporter.BitBucketPendingComment{
{
Text: ":stop_sign: **Bug** reported by [pint](https://cloudflare.github.io/pint/) **mock** check.\n\n------\n\nthis should be ignored, line is not part of the diff\n\n------\n\nthis should be ignored, line is not part of the diff\n\n------\n\n:information_source: To see documentation covering this check and instructions on how to resolve it [click here](https://cloudflare.github.io/pint/checks/mock.html).\n",
Severity: "NORMAL",
Severity: "BLOCKER",
Anchor: reporter.BitBucketPendingCommentAnchor{
Path: "foo.txt",
Line: 1,
Expand Down

0 comments on commit 2ba76de

Please # to comment.