Skip to content

Commit 0ec8f9d

Browse files
committed
feat(github)!: Do not comment on draft pull requests
Detect draft PRs and only comment on those if --comment-drafts is enabled. Users may use draft pull requests as form of communication within teams and to test stuff, having convcommitlint commenting all the time is probably too spammy.
1 parent 8d397f1 commit 0ec8f9d

5 files changed

Lines changed: 226 additions & 148 deletions

File tree

cmd/github.go

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"fmt"
66
"github.com/google/go-github/v72/github"
77
"log"
8-
"os"
9-
"strconv"
108
"strings"
119
)
1210

@@ -19,29 +17,7 @@ const (
1917

2018
// reviewGHPR creates a github pull request review
2119
// If no PR Number is provided in flags or env variable, tries to guess it from github actions context
22-
func createPrReview(issuesMessage string) (err error) {
23-
token, exists := os.LookupEnv("GITHUB_TOKEN")
24-
if !exists {
25-
return errMissingGHToken
26-
}
27-
28-
if prNumber == 0 {
29-
if !githubAction() {
30-
return errMissingPRNum
31-
}
32-
33-
prNumber, err = getPRNumber()
34-
if err != nil {
35-
return fmt.Errorf("failed to get pull request number from github context GITHUB_REF_NAME, %v", err)
36-
}
37-
}
38-
39-
if repository == "" {
40-
if repository, exists = os.LookupEnv("GITHUB_REPOSITORY"); !exists {
41-
return errMissingRepository
42-
}
43-
}
44-
20+
func createPrReview(c *github.Client, issuesMessage string) (err error) {
4521
owner, repo := splitOwnerRepo(repository)
4622
event := "REQUEST_CHANGES"
4723
if commentOnly {
@@ -51,14 +27,13 @@ func createPrReview(issuesMessage string) (err error) {
5127
markdownIssues := strings.ReplaceAll(issuesMessage, "\t", "")
5228
reviewMessage := reviewTitle + reviewTitleText + markdownIssues + whatNowTitle + whatNowText
5329

54-
client := github.NewClient(nil).WithAuthToken(token)
5530
review := github.PullRequestReviewRequest{
5631
Body: &reviewMessage,
5732
Event: &event,
5833
}
5934

6035
fmt.Println(owner + " " + repo)
61-
_, resp, err := client.PullRequests.CreateReview(context.TODO(), owner, repo, prNumber, &review)
36+
_, resp, err := c.PullRequests.CreateReview(context.TODO(), owner, repo, prNumber, &review)
6237
if err != nil {
6338
log.Fatal("failed to create pull request review: ", err)
6439
}
@@ -71,29 +46,3 @@ func createPrReview(issuesMessage string) (err error) {
7146
return nil
7247
}
7348

74-
func splitOwnerRepo(repository string) (owner, repo string) {
75-
owner = strings.Split(repository, "/")[0]
76-
repo = strings.Split(repository, "/")[1]
77-
78-
return owner, repo
79-
}
80-
81-
func getPRNumber() (n int, err error) {
82-
return strconv.Atoi(strings.Split(os.Getenv("GITHUB_REF_NAME"), "/")[0])
83-
}
84-
85-
func githubAction() bool {
86-
if _, e := os.LookupEnv("GITHUB_ACTIONS"); e {
87-
return true
88-
}
89-
90-
return false
91-
}
92-
93-
func pullRequest() bool {
94-
if v := os.Getenv("GITHUB_EVENT_TYPE"); v == "pull_request" {
95-
return true
96-
}
97-
98-
return false
99-
}

cmd/root.go

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"os"
77
"slices"
88
"strings"
9+
"context"
910

1011
"github.com/go-git/go-git/v5"
1112
"github.com/go-git/go-git/v5/plumbing"
1213
"github.com/go-git/go-git/v5/plumbing/object"
14+
"github.com/google/go-github/v72/github"
1315
"github.com/spf13/cobra"
1416
"github.com/spf13/viper"
1517
)
@@ -21,6 +23,7 @@ type message struct {
2123
}
2224

2325
var (
26+
Version = "DEV"
2427
path = "./"
2528
baseBranch = "main"
2629
lintAll bool
@@ -29,7 +32,8 @@ var (
2932
prNumber int
3033
repository string
3134
commentOnly bool
32-
Version = "DEV"
35+
commentDrafts bool
36+
token string
3337
)
3438

3539
var rootCmd = &cobra.Command{
@@ -50,6 +54,12 @@ var versionCmd = &cobra.Command{
5054
}
5155

5256
func lint() {
57+
if createReview {
58+
if err := initGHSettings(); err != nil {
59+
log.Fatal(err)
60+
}
61+
}
62+
5363
r, err := git.PlainOpen(path)
5464
if err != nil {
5565
log.Fatal("Failed to open repository")
@@ -113,7 +123,19 @@ func lint() {
113123
if issuesFound {
114124
fmt.Print(issuesMessage)
115125
if createReview {
116-
err := createPrReview(issuesMessage)
126+
client := github.NewClient(nil).WithAuthToken(token)
127+
owner, repo := splitOwnerRepo(repository)
128+
pr, r, err := client.PullRequests.Get(context.TODO(), owner, repo, prNumber)
129+
if err != nil || r.StatusCode != 200 {
130+
log.Fatalf("failed to get pull request data, response: %v, err: %v", fmt.Sprintf(r.Status, r.Response.Body), err)
131+
}
132+
133+
if prIsDraft(pr) && !commentDrafts {
134+
log.Println("PR is a draft, if you want to comment on draft PRs, use --comment-drafts flag")
135+
os.Exit(1)
136+
}
137+
138+
err = createPrReview(client, issuesMessage)
117139
if err != nil {
118140
log.Println("Failed to create pull request review: ", err)
119141
}
@@ -122,18 +144,6 @@ func lint() {
122144
}
123145
}
124146

125-
func getBaseRef(r *git.Repository, branchName string) (baseRef *plumbing.Reference, err error) {
126-
if !lintAll {
127-
baseRefName := plumbing.NewBranchReferenceName(branchName)
128-
baseRef, err = r.Reference(baseRefName, true)
129-
if err != nil {
130-
return nil, err
131-
}
132-
}
133-
134-
return baseRef, nil
135-
}
136-
137147
func printIssues(issues []error, c *object.Commit) string {
138148
header := fmt.Sprintf("%s Commit %s by %s:\n", "⛔", c.Hash.String()[:7], c.Author.Name)
139149
subHeader := fmt.Sprintf(" Message: %s\n", strings.Split(strings.TrimSpace(c.Message), "\n")[0])
@@ -209,14 +219,6 @@ func lintCommitMessage(msg message) (errs []error) {
209219
return errs
210220
}
211221

212-
func emptyLine(s string) bool {
213-
if s == "" || s == " " || s == "\n" {
214-
return true
215-
}
216-
217-
return false
218-
}
219-
220222
func Execute() {
221223
err := rootCmd.Execute()
222224
if err != nil {
@@ -263,5 +265,9 @@ func init() {
263265
_ = viper.BindPFlag("repository", rootCmd.Flags().Lookup("repository"))
264266
repository = viper.GetString("repository")
265267

268+
rootCmd.PersistentFlags().BoolVar(&commentDrafts, "comment-drafts", false, "Comment on draft pull requests")
269+
_ = viper.BindPFlag("comment-drafts", rootCmd.Flags().Lookup("comment-drafts"))
270+
commentDrafts = viper.GetBool("comment-drafts")
271+
266272
rootCmd.MarkFlagsMutuallyExclusive("lint-all", "current", "base-branch")
267273
}

cmd/root_test.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -226,22 +226,3 @@ the convention`
226226
}
227227
})
228228
}
229-
230-
func TestEmptyLine(t *testing.T) {
231-
testsCases := []struct {
232-
want bool
233-
string string
234-
}{
235-
{want: true, string: ""},
236-
{want: true, string: " "},
237-
{want: true, string: "\n"},
238-
{want: false, string: "foo"},
239-
}
240-
241-
for i, testCase := range testsCases {
242-
got := emptyLine(testCase.string)
243-
if testCase.want != got {
244-
t.Fatalf("case [ %v ]: want [ %v ], got [ %v ]", i, testCase.want, got)
245-
}
246-
}
247-
}

cmd/utils.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
"strconv"
8+
9+
"github.com/go-git/go-git/v5"
10+
"github.com/go-git/go-git/v5/plumbing"
11+
"github.com/google/go-github/v72/github"
12+
)
13+
14+
// This function could use a better name
15+
func initGHSettings() (err error) {
16+
token, err = getGHToken()
17+
if err != nil {
18+
return err
19+
}
20+
21+
if prNumber == 0 {
22+
if !githubAction() {
23+
return errMissingPRNum
24+
}
25+
26+
prNumber, err = getPRNumber()
27+
if err != nil {
28+
return fmt.Errorf("failed to get pull request number from github context GITHUB_REF_NAME, %v", err)
29+
}
30+
}
31+
32+
if repository == "" {
33+
repository, err = getRepository()
34+
if err != nil {
35+
return err
36+
}
37+
}
38+
39+
return nil
40+
}
41+
42+
func getGHToken() (string, error) {
43+
token, exists := os.LookupEnv("GITHUB_TOKEN")
44+
if !exists {
45+
return "", errMissingGHToken
46+
}
47+
48+
return token, nil
49+
}
50+
51+
func getRepository() (string, error) {
52+
repo, exists := os.LookupEnv("GITHUB_REPOSITORY")
53+
if !exists {
54+
return "", errMissingRepository
55+
}
56+
57+
return repo, nil
58+
}
59+
60+
func prIsDraft(pr *github.PullRequest) bool {
61+
return pr.GetDraft()
62+
}
63+
64+
func getPRNumber() (n int, err error) {
65+
return strconv.Atoi(strings.Split(os.Getenv("GITHUB_REF_NAME"), "/")[0])
66+
}
67+
68+
func githubAction() bool {
69+
if _, e := os.LookupEnv("GITHUB_ACTIONS"); e {
70+
return true
71+
}
72+
73+
return false
74+
}
75+
76+
func pullRequest() bool {
77+
if v := os.Getenv("GITHUB_EVENT_TYPE"); v == "pull_request" {
78+
return true
79+
}
80+
81+
return false
82+
}
83+
84+
func splitOwnerRepo(repository string) (owner, repo string) {
85+
owner = strings.Split(repository, "/")[0]
86+
repo = strings.Split(repository, "/")[1]
87+
88+
return owner, repo
89+
}
90+
91+
func getBaseRef(r *git.Repository, branchName string) (baseRef *plumbing.Reference, err error) {
92+
if !lintAll {
93+
baseRefName := plumbing.NewBranchReferenceName(branchName)
94+
baseRef, err = r.Reference(baseRefName, true)
95+
if err != nil {
96+
return nil, err
97+
}
98+
}
99+
100+
return baseRef, nil
101+
}
102+
103+
func emptyLine(s string) bool {
104+
if s == "" || s == " " || s == "\n" {
105+
return true
106+
}
107+
108+
return false
109+
}

0 commit comments

Comments
 (0)