From 3c200a88dab5144829f4c6a3a00c9a7f31b033e4 Mon Sep 17 00:00:00 2001 From: jichangjun Date: Sun, 14 Jan 2024 13:14:23 +0800 Subject: [PATCH] rebase: remove existed comments --- .../rebase-suggestion/rebase-suggestion.go | 83 --------- .../rebase-suggestion/rebase_suggestion.go | 172 ++++++++++++++++++ .../rebase_suggestion_test.go | 22 +++ 3 files changed, 194 insertions(+), 83 deletions(-) delete mode 100644 internal/linters/git-flow/rebase-suggestion/rebase-suggestion.go create mode 100644 internal/linters/git-flow/rebase-suggestion/rebase_suggestion.go create mode 100644 internal/linters/git-flow/rebase-suggestion/rebase_suggestion_test.go diff --git a/internal/linters/git-flow/rebase-suggestion/rebase-suggestion.go b/internal/linters/git-flow/rebase-suggestion/rebase-suggestion.go deleted file mode 100644 index eaa002c8..00000000 --- a/internal/linters/git-flow/rebase-suggestion/rebase-suggestion.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright 2024 Qiniu Cloud (qiniu.com). - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package rebase_suggestion - -import ( - "context" - "fmt" - "regexp" - - "github.com/cr-bot/config" - "github.com/cr-bot/internal/linters" - "github.com/google/go-github/v57/github" - "github.com/qiniu/x/log" -) - -var lintName = "rebase-suggestion" - -func init() { - // register linter - linters.RegisterCommentHandler(lintName, rebaseSuggestionHandler) -} - -func rebaseSuggestionHandler(linterConfig config.Linter, agent linters.Agent, event github.PullRequestEvent) error { - opts := &github.ListOptions{} - commits, response, err := agent.GitHubClient().PullRequests.ListCommits(context.Background(), event.GetRepo().GetOwner().GetLogin(), event.GetRepo().GetName(), event.GetNumber(), opts) - if err != nil { - return err - } - - if response.StatusCode != 200 { - log.Errorf("list commits failed: %v", response) - return fmt.Errorf("list commits failed: %v", response.Body) - } - - comment := checkCommitMessage(commits) - if len(comment) == 0 { - return nil - } - c, resp, err := agent.GitHubClient().Issues.CreateComment(context.Background(), event.GetRepo().GetOwner().GetLogin(), event.GetRepo().GetName(), event.GetNumber(), &github.IssueComment{ - Body: &comment, - }) - if err != nil { - return err - } - - if resp.StatusCode != 201 { - log.Errorf("create comment failed: %v", resp) - return fmt.Errorf("create comment failed: %v", resp.Body) - } - - log.Infof("create comment success: %v", c) - - return nil -} - -func checkCommitMessage(commits []*github.RepositoryCommit) string { - pattern := `^Merge (.*) into (.*)$` - reg := regexp.MustCompile(pattern) - - for _, commit := range commits { - if commit.Commit != nil && commit.Commit.Message != nil { - if reg.MatchString(*commit.Commit.Message) { - return "please rebase your PR" - } - } - } - - return "" -} diff --git a/internal/linters/git-flow/rebase-suggestion/rebase_suggestion.go b/internal/linters/git-flow/rebase-suggestion/rebase_suggestion.go new file mode 100644 index 00000000..d3f97355 --- /dev/null +++ b/internal/linters/git-flow/rebase-suggestion/rebase_suggestion.go @@ -0,0 +1,172 @@ +/* + Copyright 2024 Qiniu Cloud (qiniu.com). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package rebase_suggestion + +import ( + "bytes" + "context" + "fmt" + "regexp" + "strings" + "text/template" + + "github.com/cr-bot/config" + "github.com/cr-bot/internal/linters" + "github.com/google/go-github/v57/github" + "github.com/qiniu/x/log" +) + +var lintName = "rebase-suggestion" + +func init() { + linters.RegisterCommentHandler(lintName, rebaseSuggestionHandler) +} + +func rebaseSuggestionHandler(linterConfig config.Linter, agent linters.Agent, event github.PullRequestEvent) error { + var ( + org = event.GetRepo().GetOwner().GetLogin() + repo = event.GetRepo().GetName() + number = event.GetNumber() + ) + + preFilterCommits, err := listMatchedCommitMessages(context.Background(), agent, org, repo, number) + if err != nil { + return err + } + + existedComments, err := listExistedComments(context.Background(), agent, org, repo, number) + if err != nil { + return err + } + + return handle(context.Background(), agent, org, repo, number, preFilterCommits, existedComments) +} + +var rebaseSuggestionFlag = "**[REBASE SUGGESTION]**" + +var rebaseSuggestionTmpl = rebaseSuggestionFlag + ` This PR has commit message like: +{{range .}} +> {{.}} +{{end}} + +Which seems insignificant, recommend to use ` + "`git rebase `" + `to reorganize your PR. + +
+ +If you have any questions about this comment, feel free to raise an issue here: + +- **https://github.com/qiniu/cr-bot/issues** + +
+ ` + +func handle(ctx context.Context, agent linters.Agent, org, repo string, number int, prefilterCommits []*github.RepositoryCommit, existedComments []*github.IssueComment) error { + var commitMessages []string + for _, commit := range prefilterCommits { + commitMessages = append(commitMessages, *commit.Commit.Message) + } + + tmpl, err := template.New("rebase-suggestion").Parse(rebaseSuggestionTmpl) + if err != nil { + return err + } + + var buf bytes.Buffer + if err = tmpl.Execute(&buf, commitMessages); err != nil { + return err + } + + var expectedComment = buf.String() + + // check if comment already existed + for _, comment := range existedComments { + if comment.Body != nil && *comment.Body == expectedComment { + log.Infof("comment already existed: %v", comment) + return nil + } + } + + // remove old comments + for _, comment := range existedComments { + if comment.Body != nil && strings.Contains(*comment.Body, rebaseSuggestionFlag) { + _, err := agent.GitHubClient().Issues.DeleteComment(context.Background(), org, repo, *comment.ID) + if err != nil { + log.Warnf("delete comment failed: %v", err) + continue + } + } + } + + // add new comment + if len(commitMessages) > 0 { + c, resp, err := agent.GitHubClient().Issues.CreateComment(context.Background(), org, repo, number, &github.IssueComment{ + Body: &expectedComment, + }) + if err != nil { + return err + } + if resp.StatusCode != 201 { + log.Errorf("create comment failed: %v", resp) + return fmt.Errorf("create comment failed: %v", resp.Body) + } + + log.Infof("create comment success: %v", c) + } + + return nil +} + +func listMatchedCommitMessages(ctx context.Context, agent linters.Agent, org, repo string, number int) ([]*github.RepositoryCommit, error) { + var preFilterCommits []*github.RepositoryCommit + opts := &github.ListOptions{} + commits, response, err := agent.GitHubClient().PullRequests.ListCommits(context.Background(), org, repo, number, opts) + if err != nil { + return preFilterCommits, err + } + + if response.StatusCode != 200 { + log.Errorf("list commits failed: %v", response) + return preFilterCommits, fmt.Errorf("list commits failed: %v", response.Body) + } + + pattern := `^Merge (.*) into (.*)$` + reg := regexp.MustCompile(pattern) + + for _, commit := range commits { + if commit.Commit != nil && commit.Commit.Message != nil { + if reg.MatchString(*commit.Commit.Message) { + preFilterCommits = append(preFilterCommits, commit) + } + } + } + + return preFilterCommits, nil +} + +func listExistedComments(ctx context.Context, agent linters.Agent, org, repo string, number int) ([]*github.IssueComment, error) { + comments, resp, err := agent.GitHubClient().Issues.ListComments(ctx, org, repo, number, &github.IssueListCommentsOptions{}) + if err != nil { + return nil, err + } + + if resp.StatusCode != 200 { + log.Errorf("list comments failed: %v", resp) + return nil, fmt.Errorf("list comments failed: %v", resp.Body) + } + + return comments, nil +} diff --git a/internal/linters/git-flow/rebase-suggestion/rebase_suggestion_test.go b/internal/linters/git-flow/rebase-suggestion/rebase_suggestion_test.go new file mode 100644 index 00000000..296fb73c --- /dev/null +++ b/internal/linters/git-flow/rebase-suggestion/rebase_suggestion_test.go @@ -0,0 +1,22 @@ +package rebase_suggestion + +import ( + "bytes" + "testing" + "text/template" +) + +func TestRebaseSuggestionTmpl(t *testing.T) { + tmpl, err := template.New("rebase_suggestion").Parse(rebaseSuggestionTmpl) + if err != nil { + t.Fatal(err) + } + + var buf bytes.Buffer + err = tmpl.Execute(&buf, []string{"commit1", "commit2"}) + if err != nil { + t.Fatal(err) + } + + t.Log(buf.String()) +}