Skip to content

Commit 90d5bb6

Browse files
committed
ping author of a failing test's pr
1 parent 8b18ba3 commit 90d5bb6

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. crosslink)
5+
component: issuegenerator
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: issuegenerator now pings the author of a failing test's PR
9+
10+
# One or more tracking issues related to the change
11+
issues: [1182]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

issuegenerator/internal/github/client.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ Link to latest failed build: ${linkToBuild}
6969
Commit: ${commit}
7070
7171
${failedTests}
72+
`
73+
prCommentTemplate = `@${prAuthor} some tests are failing on main after these changes.
74+
Details: ${issueLink}
75+
Please take a look when you get a chance. Thanks!
7276
`
7377
)
7478

@@ -227,6 +231,13 @@ func (c *Client) CommentOnIssue(ctx context.Context, r report.Report, issue *git
227231
c.handleBadResponses(response)
228232
}
229233

234+
// Also comment on the PR with a link to this comment
235+
if prNumber > 0 && issueComment != nil && issueComment.HTMLURL != nil {
236+
if prAuthor := c.GetPRAuthor(ctx, prNumber); prAuthor != "" {
237+
_ = c.CommentOnPR(ctx, prNumber, prAuthor, *issueComment.HTMLURL)
238+
}
239+
}
240+
230241
return issueComment
231242
}
232243

@@ -315,6 +326,83 @@ func (c *Client) getCommitMessage(ctx context.Context) string {
315326
return ""
316327
}
317328

329+
// GetPRAuthor fetches the author of a pull request
330+
func (c *Client) GetPRAuthor(ctx context.Context, prNumber int) string {
331+
if prNumber <= 0 {
332+
return ""
333+
}
334+
335+
pr, response, err := c.client.PullRequests.Get(
336+
ctx,
337+
c.envVariables[githubOwner],
338+
c.envVariables[githubRepository],
339+
prNumber,
340+
)
341+
if err != nil {
342+
c.logger.Warn("Failed to get PR details from GitHub API",
343+
zap.Int("pr_number", prNumber),
344+
zap.Error(err),
345+
)
346+
return ""
347+
}
348+
349+
if response.StatusCode != http.StatusOK {
350+
c.logger.Warn("Unexpected response when fetching PR",
351+
zap.Int("status_code", response.StatusCode),
352+
zap.Int("pr_number", prNumber),
353+
)
354+
return ""
355+
}
356+
357+
if pr.User != nil && pr.User.Login != nil {
358+
return *pr.User.Login
359+
}
360+
361+
return ""
362+
}
363+
364+
// CommentOnPR adds a comment to a pull request to notify the author about failing tests
365+
func (c *Client) CommentOnPR(ctx context.Context, prNumber int, prAuthor string, issueURL string) *github.IssueComment {
366+
if prNumber <= 0 || prAuthor == "" {
367+
c.logger.Warn("Cannot comment on PR: missing PR number or author",
368+
zap.Int("pr_number", prNumber),
369+
zap.String("pr_author", prAuthor),
370+
)
371+
return nil
372+
}
373+
374+
body := os.Expand(prCommentTemplate, func(param string) string {
375+
return prTemplateHelper(param, prAuthor, issueURL)
376+
})
377+
378+
prComment, response, err := c.client.Issues.CreateComment(
379+
ctx,
380+
c.envVariables[githubOwner],
381+
c.envVariables[githubRepository],
382+
prNumber,
383+
&github.IssueComment{
384+
Body: &body,
385+
},
386+
)
387+
if err != nil {
388+
c.logger.Warn("Failed to comment on PR",
389+
zap.Int("pr_number", prNumber),
390+
zap.Error(err),
391+
)
392+
return nil
393+
}
394+
395+
if response.StatusCode != http.StatusCreated {
396+
c.logger.Warn("Unexpected response when commenting on PR",
397+
zap.Int("status_code", response.StatusCode),
398+
zap.Int("pr_number", prNumber),
399+
)
400+
return nil
401+
}
402+
403+
return prComment
404+
}
405+
318406
func (c *Client) extractPRNumberFromCommitMessage(commitMsg string) int {
319407
// Only consider the first line of the commit message.
320408
firstLine := strings.SplitN(commitMsg, "\n", 2)[0]
@@ -377,9 +465,27 @@ func (c *Client) CreateIssue(ctx context.Context, r report.Report) *github.Issue
377465
c.handleBadResponses(response)
378466
}
379467

468+
// After creating the issue, also comment on the PR with a link to the created issue
469+
if prNumber > 0 && issue != nil && issue.HTMLURL != nil {
470+
if prAuthor := c.GetPRAuthor(ctx, prNumber); prAuthor != "" {
471+
_ = c.CommentOnPR(ctx, prNumber, prAuthor, *issue.HTMLURL)
472+
}
473+
}
474+
380475
return issue
381476
}
382477

478+
func prTemplateHelper(param string, prAuthor string, issueURL string) string {
479+
switch param {
480+
case "prAuthor":
481+
return prAuthor
482+
case "issueLink":
483+
return issueURL
484+
default:
485+
return ""
486+
}
487+
}
488+
383489
func (c *Client) handleBadResponses(response *github.Response) {
384490
body, _ := io.ReadAll(response.Body)
385491
c.logger.Fatal(

issuegenerator/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func main() {
6666
)
6767

6868
existingIssue := ghClient.GetExistingIssue(ctx, report.Module)
69+
// CreateIssue/CommentOnIssue will also comment on the related PR.
6970
if existingIssue == nil {
7071
// If none exists, create a new GitHub Issue for the failure.
7172
logger.Info("No existing Issues found, creating a new one.")
@@ -80,5 +81,6 @@ func main() {
8081
createdIssueComment := ghClient.CommentOnIssue(ctx, report, existingIssue)
8182
logger.Info("GitHub Issue updated", zap.String("html_url", *createdIssueComment.HTMLURL))
8283
}
84+
8385
}
8486
}

0 commit comments

Comments
 (0)