cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.13.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/reporter/github.go

124lines · modecode

1package reporter
2
3import (
4 "context"
5 "fmt"
6 "sort"
7 "time"
8
9 "github.com/google/go-github/v37/github"
10 "github.com/rs/zerolog/log"
11 "golang.org/x/oauth2"
12
13 "github.com/cloudflare/pint/internal/git"
14)
15
16type GithubReporter struct {
17 baseURL string
18 uploadURL string
19 timeout time.Duration
20 authToken string
21 owner string
22 repo string
23 prNum int
24 gitCmd git.CommandRunner
25}
26
27// NewGithubReporter creates a new GitHub reporter that reports
28// problems via comments on a given pull request number (integer).
29func NewGithubReporter(baseURL, uploadURL string, timeout time.Duration, token, owner, repo string, prNum int, gitCmd git.CommandRunner) GithubReporter {
30 return GithubReporter{
31 baseURL: baseURL,
32 uploadURL: uploadURL,
33 timeout: timeout,
34 authToken: token,
35 owner: owner,
36 repo: repo,
37 prNum: prNum,
38 gitCmd: gitCmd,
39 }
40}
41
42// Submit submits the summary to GitHub.
43func (gr GithubReporter) Submit(summary Summary) error {
44 ctx, cancel := context.WithTimeout(context.Background(), gr.timeout)
45 defer cancel()
46
47 ts := oauth2.StaticTokenSource(
48 &oauth2.Token{AccessToken: gr.authToken},
49 )
50 tc := oauth2.NewClient(ctx, ts)
51
52 var client *github.Client
53
54 if gr.uploadURL != "" && gr.baseURL != "" {
55 ec, err := github.NewEnterpriseClient(gr.baseURL, gr.uploadURL, tc)
56 if err != nil {
57 return fmt.Errorf("creating new GitHub client: %w", err)
58 }
59 client = ec
60 } else {
61 client = github.NewClient(tc)
62 }
63
64 pb, err := blameReports(summary.Reports, gr.gitCmd)
65 if err != nil {
66 return fmt.Errorf("failed to run git blame: %w", err)
67 }
68
69 comments := []*github.DraftReviewComment{}
70 for _, rep := range summary.Reports {
71 rep := rep
72
73 gitBlames, ok := pb[rep.Path]
74 if !ok {
75 continue
76 }
77
78 linesWithBlame := []int{}
79 for _, pl := range rep.Problem.Lines {
80 commit := gitBlames.GetCommit(pl)
81 if summary.FileChanges.HasCommit(commit) {
82 linesWithBlame = append(linesWithBlame, pl)
83 }
84 }
85
86 if len(linesWithBlame) == 0 {
87 continue
88 }
89
90 var comment *github.DraftReviewComment
91
92 if len(linesWithBlame) == 1 {
93 comment = &github.DraftReviewComment{
94 Path: github.String(rep.Path),
95 Body: github.String(rep.Problem.Text),
96 Line: github.Int(linesWithBlame[0]),
97 }
98 } else if len(linesWithBlame) > 1 {
99 sort.Ints(linesWithBlame)
100 start, end := linesWithBlame[0], linesWithBlame[len(linesWithBlame)-1]
101 comment = &github.DraftReviewComment{
102 Path: github.String(rep.Path),
103 Body: github.String(rep.Problem.Text),
104 Line: github.Int(end),
105 StartLine: github.Int(start),
106 }
107 }
108
109 comments = append(comments, comment)
110 }
111
112 if len(comments) > 0 {
113 _, resp, err := client.PullRequests.CreateReview(ctx, gr.owner, gr.repo, gr.prNum, &github.PullRequestReviewRequest{
114 Event: github.String("COMMENT"),
115 Comments: comments,
116 })
117 if err != nil {
118 return fmt.Errorf("creating review: %w", err)
119 }
120 log.Info().Str("status", resp.Status).Msg("Report submitted")
121 }
122
123 return nil
124}
125