From 64751ea2c5896765afe98d195ce8c0fe6f150209 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 12 Sep 2023 13:21:29 -0700 Subject: [PATCH] github-automation: Use a single comment for team mentions on pull requests (#66037) This will reduce the number of notifications created when a pull request label is added. Each team will only get a notification when their team's label is added and not when other teams' labels are added. --- .github/workflows/pr-subscriber.yml | 8 +++++ llvm/utils/git/github-automation.py | 47 +++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pr-subscriber.yml b/.github/workflows/pr-subscriber.yml index 3b18c8b35e97..60c884cb172c 100644 --- a/.github/workflows/pr-subscriber.yml +++ b/.github/workflows/pr-subscriber.yml @@ -9,6 +9,14 @@ on: permissions: contents: read +concurrency: + # Ideally, we would use the PR number in the concurrency group, but we don't + # have access to it here. We need to ensure only one job is running for + # each PR at a time, because there is a potential race condition when + # updating the issue comment. + group: "PR Subscriber" + cancel-in-progress: false + jobs: auto-subscribe: runs-on: ubuntu-latest diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index f732b13d97b8..0517cac286a3 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -10,6 +10,7 @@ import argparse from git import Repo # type: ignore +import html import github import os import re @@ -97,6 +98,13 @@ class PRSubscriber: self._team_name = "pr-subscribers-{}".format( label_name.replace("+", "x") ).lower() + self.COMMENT_TAG = "\n" + + def get_summary_comment(self) -> github.IssueComment.IssueComment: + for comment in self.pr.as_issue().get_comments(): + if self.COMMENT_TAG in comment.body: + return comment + return None def run(self) -> bool: patch = None @@ -121,7 +129,7 @@ class PRSubscriber: # Get the diff try: - patch = requests.get(self.pr.diff_url).text + patch = html.escape(requests.get(self.pr.diff_url).text) except: patch = "" diff_stats += "\n
\n" + patch
@@ -131,22 +139,35 @@ class PRSubscriber:
         patch_link = f"Full diff: {self.pr.diff_url}\n"
         if len(patch) > DIFF_LIMIT:
             patch_link = f"\nPatch is {human_readable_size(len(patch))}, truncated to {human_readable_size(DIFF_LIMIT)} below, full version: {self.pr.diff_url}\n"
-            diff_stats = diff_stats[0:DIFF_LIMIT] + "...\n\n"
+            diff_stats = html.escape(diff_stats[0:DIFF_LIMIT]) + "...\n\n"
         diff_stats += "
" + team_mention = "@llvm/{}".format(team.slug) body = self.pr.body - comment = ( - "@llvm/{}".format(team.slug) - + "\n\n
\n" - + f"Changes\n\n" - + f"{body}\n--\n" - + patch_link - + "\n" - + f"{diff_stats}\n\n" - + "
" - ) + comment = f""" +{self.COMMENT_TAG} +{team_mention} + +
+Changes +{body} +-- +{patch_link} +{diff_stats} +
+""" - self.pr.as_issue().create_comment(comment) + summary_comment = self.get_summary_comment() + if not summary_comment: + self.pr.as_issue().create_comment(comment) + elif team_mention + "\n" in summary_comment.body: + print("Team {} already mentioned.".format(team.slug)) + else: + summary_comment.edit( + summary_comment.body.replace( + self.COMMENT_TAG, self.COMMENT_TAG + team_mention + "\n" + ) + ) return True def _get_curent_team(self) -> Optional[github.Team.Team]: