Skip to content

MM-68829 Improving UX for DMs sent on PR comments#1010

Open
avasconcelos114 wants to merge 3 commits into
masterfrom
fixing_edit_dm_spam
Open

MM-68829 Improving UX for DMs sent on PR comments#1010
avasconcelos114 wants to merge 3 commits into
masterfrom
fixing_edit_dm_spam

Conversation

@avasconcelos114
Copy link
Copy Markdown
Contributor

@avasconcelos114 avasconcelos114 commented May 15, 2026

Summary

This PR mainly does two things to improve the general experience of receiving DM notifications from the GitHub bot

  • Preventing edit or delete PR message events from sending a "new comment" DM notification
  • Improving logic that cleans body to prevent issues with html comments in the message from interfering with visibility of message

Ticket Link

Fixes: https://mattermost.atlassian.net/browse/MM-68829

QA Notes

The main webhook event affected by this is the PR commenting, which mainly consists of:

  • Notification received by someone who was mentioned in a PR comment (that is neither the author nor the user posting the comment)
  • Notification received by the author of the PR

We'll want to make sure that editing a PR comment does not send a new notification to the users as a DM

We might also want to run some regression tests on the following DM notifications to confirm they still append a quote with the body of the comment as well:

  • commentMentionNotification — DMs users @mentioned in an issue
  • commentAuthorIssueNotification — DMs the issue author when someone comments on their issue
  • commentAssigneePullRequestNotification — DMs PR assignees when someone comments on the PR conversation
  • commentAssigneeIssueNotification — DMs issue assignees when someone comments on the issue
  • commentAssigneeSelfMentionPullRequestNotification — DMs PR assignees who were also @mentioned in the comment
  • commentAssigneeSelfMentionIssueNotification — DMs issue assignees who were also @mentioned in the comment

Change Impact: 🟡 Medium

Reasoning: The PR adds new DM notification handlers for PR review comments and updates message-body cleaning logic used across multiple DM templates; these are user-facing changes spanning several files (webhook handling, templates, and tests) but remain focused on notification behavior.

Regression Risk: Moderate. Early-return guards reduce unwanted DMs, but new code paths (user mapping, permission checks, muted-user filtering, and DM posting) introduce failure points that could silently suppress or misroute notifications. The new cleanBody helper changes message rendering for many templates; while templates were updated, dedicated tests for all template output permutations appear limited.

** QA Recommendation:** Perform targeted manual QA on PR comment workflows: verify that editing or deleting PR comments no longer sends "new comment" DMs, and confirm quoted comment bodies are correctly cleaned/omitted for the affected notification types (commentMentionNotification, commentAuthorIssueNotification, commentAssigneePullRequestNotification, commentAssigneeIssueNotification, commentAssigneeSelfMentionPullRequestNotification, commentAssigneeSelfMentionIssueNotification). Automated tests cover many scenarios but manual verification is recommended for edge cases (HTML comments, GitHub footer removal, and permission/mapping failures).

Generated by CodeRabbitAI

Review Change Stack

- Preventing edit or delete PR message events from sending a "new comment" DM notification
- Improving logic that cleans body to prevent issues with html comments in the message from interfering with visibility of message
@avasconcelos114 avasconcelos114 self-assigned this May 15, 2026
@avasconcelos114 avasconcelos114 requested a review from a team as a code owner May 15, 2026 14:31
@avasconcelos114 avasconcelos114 added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels May 15, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4589d1a2-609d-4369-b163-11af6465fe51

📥 Commits

Reviewing files that changed from the base of the PR and between 42b3f35 and ea29a91.

📒 Files selected for processing (1)
  • server/plugin/template.go
💤 Files with no reviewable changes (1)
  • server/plugin/template.go

📝 Walkthrough

Walkthrough

Adds mention and author notification flows for PR review comments. Introduces cleanBody template function, invokes mention/author handlers on created review comments, parses mentioned users, enforces permission and mute checks, sends direct posts or DMs, and updates tests and mocks.

Changes

Review Comment Mention and Author Notifications

Layer / File(s) Summary
Body cleanup template utility
server/plugin/template.go
cleanBody removes GitHub notification footers and HTML comments from bodies; review comment notification templates now use this for quoted bodies.
Test mock builder parameterization
server/plugin/test_utils.go
GetMockPullRequestReviewCommentEvent now accepts action, body, and sender and sets PullRequest.User.Login to MockIssueAuthor.
Webhook dispatcher wiring
server/plugin/webhook.go
PullRequestReviewCommentEvent handler calls new mention and author notification handlers in addition to the base post handler.
PR review comment post handler refactor
server/plugin/webhook.go, server/plugin/webhook_test.go
postPullRequestReviewCommentEvent now only runs for created actions and uses the updated message template variable; tests updated for non-created actions and CreatePost error/success paths.
Mention and author notification handlers
server/plugin/webhook.go, server/plugin/webhook_test.go
Adds handleReviewCommentMentionNotification and handleReviewCommentAuthorNotification to clean and parse comment bodies, resolve usernames/author, enforce private-repo permissions and mute filtering, create direct mention posts or author DMs, and trigger refresh; tests cover suppression, mapping misses, and successful notifications.
Issue comment assignee notification action filtering
server/plugin/webhook.go, server/plugin/webhook_test.go
handleCommentAssigneeNotification returns early for edited and deleted actions; tests assert these actions are ignored.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit hops through mentions and DMs with glee,
Cleaning tails of footers so messages are free,
Authors and mentions now get a polite ping,
Tests hum along as the notification bells ring,
🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately captures the primary objective of improving UX for direct messages sent on PR comments, which is the main focus of the changes across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fixing_edit_dm_spam

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/plugin/webhook.go`:
- Around line 1106-1111: The comparisons that suppress self/author mentions are
using case-sensitive equality against event.GetSender().GetLogin() and
event.GetPullRequest().GetUser().GetLogin(), so usernames with different casing
can bypass suppression; update those checks to perform case-insensitive
comparisons (e.g., use strings.EqualFold or compare lowercased strings) for the
expressions that reference username, event.GetSender().GetLogin(), and
event.GetPullRequest().GetUser().GetLogin(); make the same change at the other
occurrence around lines 1143-1145 so both sender and PR author checks are
case-insensitive.
- Around line 1091-1097: The code reads the comment body into body and only
strips the email footer before calling parseGitHubUsernamesFromText, but HTML
comment blocks (<!-- ... -->) can still contain mentions and trigger DMs; before
calling parseGitHubUsernamesFromText, remove or sanitize any HTML comments from
the comment text (the variable body produced from event.GetComment().GetBody())
so mentions inside <!-- --> are ignored, then pass the cleaned body to
parseGitHubUsernamesFromText (update the body variable or use a new cleanedBody)
to ensure hidden-comment mentions are not parsed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 03b5dc71-be81-4372-b8f0-96ade155671a

📥 Commits

Reviewing files that changed from the base of the PR and between 5e32dfe and c49b18c.

📒 Files selected for processing (4)
  • server/plugin/template.go
  • server/plugin/test_utils.go
  • server/plugin/webhook.go
  • server/plugin/webhook_test.go

Comment thread server/plugin/webhook.go
Comment thread server/plugin/webhook.go Outdated
@avasconcelos114 avasconcelos114 changed the title Improving UX for DMs sent on PR comments MM-68829 Improving UX for DMs sent on PR comments May 15, 2026
Comment thread server/plugin/webhook.go
}
}

func (p *Plugin) handleReviewCommentMentionNotification(event *github.PullRequestReviewCommentEvent) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleCommentMentionNotification filters out mentioned users who are also assignees. Maybe worth mirroring the skip logic for consistency and to avoid double DM?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the PullRequestReviewCommentEvent events there isn't an assignee handler like we do for IssueCommentEvent, only one handler for the author which this function is skipping inhandleReviewCommentMentionNotification:1112 to avoid duplication, so I think in here we're safe from the risk of double DMing here

Comment thread server/plugin/webhook.go

func (p *Plugin) handleCommentAssigneeNotification(event *github.IssueCommentEvent) {
action := event.GetAction()
if action == actionEdited || action == actionDeleted {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can check if handleCommentAssigneeNotification caller already filters out edit and delete actions. If yes this guard is dead code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caller (handleWebhook) doesn't filter out by action, this has been done for each individual handler previously but this handler in particular was missing it

I'm wondering if we want to move the guard up to handleWebhook but not entirely certain as this would deviate from how every other webhook event is processed (specific action-related guards happening at the handler function-level), what do you think works best here?

Comment thread server/plugin/template.go Outdated
}
cleaned = mdCommentRegex.ReplaceAllString(cleaned, "")
cleaned = strings.TrimSpace(cleaned)
if cleaned == "" {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this if cleaned == "" { return "" } block returns "" either way. Just return cleaned

Copy link
Copy Markdown
Contributor

@nang2049 nang2049 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM otherwise :)

@avasconcelos114 avasconcelos114 requested a review from nang2049 May 26, 2026 18:31
@dryrunsecurity
Copy link
Copy Markdown

DryRun Security

This pull request may allow notification and refresh-event spam in server/plugin/webhook.go because handleReviewCommentMentionNotification processes an unlimited number of mentioned users in a single PR comment, potentially letting an attacker create significant load on the Mattermost server and clients.

🟡 Notification and Refresh Event Spam in server/plugin/webhook.go (drs_48a3b2e2)
Vulnerability Notification and Refresh Event Spam
Description The handleReviewCommentMentionNotification function processes mentions in GitHub pull request review comments and, for each mentioned user, sends a direct message via Mattermost and triggers a client refresh event. While the parseGitHubUsernamesFromText function iterates through the comment text, the function does not implement a maximum limit on the number of mentions processed per comment. An attacker could potentially mention a large number of users in a single comment to cause significant load on the Mattermost server and client.

for _, username := range mentionedUsernames {
if strings.EqualFold(username, event.GetSender().GetLogin()) {
continue
}


Comment to provide feedback on these findings.

Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]

Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing

All finding details can be found in the DryRun Security Dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants