From cc07ee02150815023ab6992a70c1395c1b74e1c9 Mon Sep 17 00:00:00 2001 From: sumire88 <151038614+sumire88@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:07:35 -0400 Subject: [PATCH 1/3] feat(pkg/github): add support to issue_comment reply --- pkg/github/github.go | 2 +- pkg/github/issue.go | 41 +++++++++++++++++++++++++++++++++++++--- pkg/github/issue_test.go | 15 ++++++++++++++- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/pkg/github/github.go b/pkg/github/github.go index 15f7a13..327c2d6 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -18,7 +18,7 @@ type GitHubRepo interface { Owner() string Repository() string GetInfo() (*Repository, error) - AddIssueComment(issueNum int, comment string) error + AddIssueComment(issueNum int, commentID int64, comment string) error } func NewGitHubRepo(s *Session, f *RepositoryQueryFilter) (GitHubRepo, error) { diff --git a/pkg/github/issue.go b/pkg/github/issue.go index 7a11d3b..f696ec9 100644 --- a/pkg/github/issue.go +++ b/pkg/github/issue.go @@ -1,11 +1,46 @@ package github -import "github.com/google/go-github/v73/github" +import ( + "strings" + + "github.com/google/go-github/v73/github" +) + +// quoteText turns each line into a Markdown quote ("> ...") +func quoteText(body string) string { + lines := strings.Split(body, "\n") + for i, line := range lines { + lines[i] = "> " + line + } + return strings.Join(lines, "\n") +} // AddIssueComment adds a comment to an issue in the repository // https://pkg.go.dev/github.com/google/go-github/v73/github#IssuesService.CreateComment -func (g *gitHubRepo) AddIssueComment(issueNum int, comment string) error { - _, _, err := g.session.Client.Issues.CreateComment(g.session.Context, g.owner, g.repostiory, issueNum, &github.IssueComment{Body: &comment}) +func (g *gitHubRepo) AddIssueComment(issueNum int, commentID int64, comment string) error { + var newComment string + // If commentID is provided, we assume it's a reply to an existing comment + if commentID > 0 { + // Fetch the original comment + origComment, _, err := g.session.Client.Issues.GetComment(g.session.Context, g.owner, g.repostiory, commentID) + if err != nil { + return err + } + + // Build the quoted comment block + quoted := quoteText(origComment.GetBody()) + + // Combine quoted text with the reply + newComment = quoted + "\n\n" + comment + } else { + // If no commentID is provided, just use the comment as is + newComment = comment + } + + // Create a new comment on the issue + _, _, err := g.session.Client.Issues.CreateComment(g.session.Context, g.owner, g.repostiory, issueNum, &github.IssueComment{ + Body: &newComment, + }) if err != nil { return err } diff --git a/pkg/github/issue_test.go b/pkg/github/issue_test.go index 542277c..66c8213 100644 --- a/pkg/github/issue_test.go +++ b/pkg/github/issue_test.go @@ -29,7 +29,20 @@ func TestGithub_AddIssueComment(t *testing.T) { } comment := "This is a test comment from the GitHub API client." - err = repo.AddIssueComment(10, comment) + err = repo.AddIssueComment(10, 0, comment) + if err != nil { + t.Fatal(err) + } +} + +func TestGithub_AddIssueCommentReply(t *testing.T) { + repo, err := initIssueTest() + if err != nil { + t.Fatal(err) + } + + comment := "This is a test comment from the GitHub API client." + err = repo.AddIssueComment(27, 3050731768, comment) if err != nil { t.Fatal(err) } From ef04fd8b649360edacb930e08f8828c02dd02e4f Mon Sep 17 00:00:00 2001 From: sumire88 <151038614+sumire88@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:08:25 -0400 Subject: [PATCH 2/3] patch(pkg/handler): pass commentID as arg --- pkg/handler/issue_comment_events.go | 2 +- pkg/handler/issue_events.go | 2 +- pkg/handler/pull_request_events.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/handler/issue_comment_events.go b/pkg/handler/issue_comment_events.go index 862ad61..bdcb331 100644 --- a/pkg/handler/issue_comment_events.go +++ b/pkg/handler/issue_comment_events.go @@ -34,7 +34,7 @@ func (h *handler) ProcessIssueCommentCreatedEvent(ctx context.Context, deliveryI } // Process translation request - if err := svc.SendCloudEventRequest(*event.Issue.Number, *event.Comment.Body); err != nil { + if err := svc.SendCloudEventRequest(*event.Issue.Number, *event.Comment.ID, *event.Comment.Body); err != nil { h.logger.Errorw("Failed to process translation request", "error", err) return err } diff --git a/pkg/handler/issue_events.go b/pkg/handler/issue_events.go index e8582f0..51bafe3 100644 --- a/pkg/handler/issue_events.go +++ b/pkg/handler/issue_events.go @@ -37,7 +37,7 @@ func (h *handler) ProcessIssuesOpenedEvent(ctx context.Context, deliveryID strin } // Process translation request - if err := svc.SendCloudEventRequest(*event.Issue.Number, *event.Issue.Body); err != nil { + if err := svc.SendCloudEventRequest(*event.Issue.Number, 0, *event.Issue.Body); err != nil { h.logger.Errorw("Failed to process translation request", "error", err) return err } diff --git a/pkg/handler/pull_request_events.go b/pkg/handler/pull_request_events.go index 95febdd..19d91b8 100644 --- a/pkg/handler/pull_request_events.go +++ b/pkg/handler/pull_request_events.go @@ -44,7 +44,7 @@ func (h *handler) ProcessPullRequestsOpenedEvent(ctx context.Context, deliveryID } // Process translation request - if err := svc.SendCloudEventRequest(*event.PullRequest.Number, *event.PullRequest.Body); err != nil { + if err := svc.SendCloudEventRequest(*event.PullRequest.Number, 0, *event.PullRequest.Body); err != nil { h.logger.Errorw("Failed to process translation request", "error", err) return err } From 6e36ac4168b8ceb095d1949b09cde56029946a23 Mon Sep 17 00:00:00 2001 From: sumire88 <151038614+sumire88@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:08:54 -0400 Subject: [PATCH 3/3] feat(svc/action): take commentID from event payload --- service/action.go | 19 ++++++------------- service/cloudevent.go | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/service/action.go b/service/action.go index 0f6f59c..eef4d6a 100644 --- a/service/action.go +++ b/service/action.go @@ -17,16 +17,6 @@ func (s *AppService) GetRepoInfo() (*github.Repository, error) { return result, nil } -// AddIssueComment adds a comment to an issue in the repository -func (s *AppService) AddIssueComment(issueNumber int, comment string) error { - err := s.repo.AddIssueComment(issueNumber, comment) - if err != nil { - return errors.New("failed to add issue comment: " + err.Error()) - } - - return nil -} - // MultilineTranslate translates a multiline text using the translation engine func (s *AppService) MultilineTranslate(text string) (string, error) { if s.translateEngine == nil { @@ -42,9 +32,12 @@ func (s *AppService) MultilineTranslate(text string) (string, error) { } // ProcessTranslationRequest processes a translation request for an issue comment -func (s *AppService) ProcessTranslationRequest(issueNumber int, text string) error { +func (s *AppService) ProcessTranslationRequest(issueNumber int, commentID int64, text string) error { // Log the incoming translation request - s.logger.Infow("Processing translation request", "issueNumber", issueNumber) + s.logger.Infow("Processing translation request", + "issueNumber", issueNumber, + "commentID", commentID, + ) // Check if the text needs to be translated langResult, err := translate.DetectLanguage(text) @@ -79,7 +72,7 @@ func (s *AppService) ProcessTranslationRequest(issueNumber int, text string) err result = "> [!NOTE]\n> The following content has been translated from its original language using an automated process powered by a proprietary API. Segments originally written in English have been preserved, while non-English portions have been machine-translated for readability. Please be aware that minor inaccuracies may exist due to the automated nature of the translation.\n\n" + result // Add the translated text as a comment on the issue - if err := s.AddIssueComment(issueNumber, result); err != nil { + if err := s.repo.AddIssueComment(issueNumber, commentID, result); err != nil { return errors.New("failed to add translated comment: " + err.Error()) } diff --git a/service/cloudevent.go b/service/cloudevent.go index 2a3d824..6119332 100644 --- a/service/cloudevent.go +++ b/service/cloudevent.go @@ -10,7 +10,7 @@ import ( ) // SendCloudEventRequest sends a translation request as a CloudEvent -func (s *AppService) SendCloudEventRequest(issueNumber int, text string) error { +func (s *AppService) SendCloudEventRequest(issueNumber int, commentID int64, text string) error { // Log the incoming translation request s.logger.Infof("Sending translation request for issue #%d", issueNumber) @@ -21,6 +21,7 @@ func (s *AppService) SendCloudEventRequest(issueNumber int, text string) error { // Construct the data to be sent in the event data := map[string]string{ "issue_number": strconv.Itoa(issueNumber), + "comment_id": strconv.FormatInt(commentID, 10), "text": text, "repo_owner": s.repo.Owner(), "repo_name": s.repo.Repository(), @@ -85,11 +86,15 @@ func (s *AppService) ProcessCloudEventRequest(event cloudevent.Event) error { // Instantiate the translation engine s.translateEngine = translate.NewLocalAIClient() - // Extract issue number and text from the event data + // Extract issue number, issue comment number, and text from the event data issueNumberStr, ok := data["issue_number"] if !ok { s.logger.Error("missing issue_number in event data") } + commentIDStr, ok := data["comment_id"] + if !ok { + s.logger.Error("missing issue_comment_number in event data") + } text, ok := data["text"] if !ok { s.logger.Error("missing text in event data") @@ -100,9 +105,14 @@ func (s *AppService) ProcessCloudEventRequest(event cloudevent.Event) error { if err != nil { s.logger.Errorf("invalid issue_number format: %v", err) } + // Convert issue comment number to integer + commentID, err := strconv.Atoi(commentIDStr) + if err != nil { + s.logger.Errorf("invalid issue_comment_number format: %v", err) + } // Process the translation request - err = s.ProcessTranslationRequest(issueNumber, text) + err = s.ProcessTranslationRequest(issueNumber, int64(commentID), text) if err != nil { s.logger.Errorf("failed to process translation request: %v", err) }