Add ephemeral merging label (#98543)

Addresses https://github.com/pytorch/test-infra/issues/3950

Test Plan: Ran a dry run on this pr. The label showed up while trying to merge
<img width="354" alt="Screenshot 2023-04-06 at 4 57 48 PM" src="https://user-images.githubusercontent.com/13758638/230514276-1ac70b58-d2d1-4e4b-892b-a957bf156063.png">

And then disappeared after failing
<img width="373" alt="Screenshot 2023-04-06 at 5 00 11 PM" src="https://user-images.githubusercontent.com/13758638/230514470-38b15ec7-cfd9-4efe-b6e8-0f9af5577c62.png">

There's also the trail of adding and removing the "merging" label at the bottom

Notes: This is slightly buggy sometimes. For example when the merge failed when I was editing this textbox, the label did not disappear.
Pull Request resolved: https://github.com/pytorch/pytorch/pull/98543
Approved by: https://github.com/malfet
diff --git a/.github/scripts/github_utils.py b/.github/scripts/github_utils.py
index 591ec1a..3a830cb 100644
--- a/.github/scripts/github_utils.py
+++ b/.github/scripts/github_utils.py
@@ -55,6 +55,7 @@
     url: str,
     params: Optional[Dict[str, Any]] = None,
     data: Optional[Dict[str, Any]] = None,
+    method: Optional[str] = None,
 ) -> List[Dict[str, Any]]:
     headers = {"Accept": "application/vnd.github.v3+json"}
     if params is not None and len(params) > 0:
@@ -63,7 +64,7 @@
         )
     return cast(
         List[Dict[str, Any]],
-        gh_fetch_url(url, headers=headers, data=data, reader=json.load),
+        gh_fetch_url(url, headers=headers, data=data, reader=json.load, method=method),
     )
 
 
diff --git a/.github/scripts/label_utils.py b/.github/scripts/label_utils.py
index 93edeca..d3c19f5 100644
--- a/.github/scripts/label_utils.py
+++ b/.github/scripts/label_utils.py
@@ -6,7 +6,7 @@
 from typing import Any, List, Tuple, TYPE_CHECKING, Union
 from urllib.request import Request, urlopen
 
-from github_utils import gh_fetch_json, GitHubComment
+from github_utils import gh_fetch_url, GitHubComment
 
 # TODO: this is a temp workaround to avoid circular dependencies,
 #       and should be removed once GitHubPR is refactored out of trymerge script.
@@ -77,12 +77,19 @@
 def gh_add_labels(
     org: str, repo: str, pr_num: int, labels: Union[str, List[str]]
 ) -> None:
-    gh_fetch_json(
-        f"https://api.github.com/repos/{org}/{repo}/issues/{pr_num}/labels",
+    gh_fetch_url(
+        url=f"https://api.github.com/repos/{org}/{repo}/issues/{pr_num}/labels",
         data={"labels": labels},
     )
 
 
+def gh_remove_label(org: str, repo: str, pr_num: int, label: str) -> None:
+    gh_fetch_url(
+        url=f"https://api.github.com/repos/{org}/{repo}/issues/{pr_num}/labels/{label}",
+        method="DELETE",
+    )
+
+
 def get_release_notes_labels(org: str, repo: str) -> List[str]:
     return [
         label
diff --git a/.github/scripts/trymerge.py b/.github/scripts/trymerge.py
index b6966c7..2b10dc7 100755
--- a/.github/scripts/trymerge.py
+++ b/.github/scripts/trymerge.py
@@ -39,9 +39,18 @@
     GitRepo,
     patterns_to_regex,
 )
-from label_utils import gh_add_labels, has_required_labels, LABEL_ERR_MSG
+from label_utils import (
+    gh_add_labels,
+    gh_remove_label,
+    has_required_labels,
+    LABEL_ERR_MSG,
+)
 from trymerge_explainer import get_revert_message, TryMergeExplainer
 
+# labels
+MERGE_IN_PROGRESS_LABEL = "merging"
+MERGE_COMPLETE_LABEL = "merged"
+
 
 class JobCheckState(NamedTuple):
     name: str
@@ -1038,6 +1047,10 @@
                 label = f"{label_base}X{i+2}"
         gh_add_labels(self.org, self.project, self.pr_num, [label])
 
+    def remove_label(self, label: str) -> None:
+        if self.get_labels() is not None and label in self.get_labels():
+            gh_remove_label(self.org, self.project, self.pr_num, label)
+
     def merge_into(
         self,
         repo: GitRepo,
@@ -1061,9 +1074,9 @@
 
         repo.push(self.default_branch(), dry_run)
         if not dry_run:
-            self.add_numbered_label("merged")
+            self.add_numbered_label(MERGE_COMPLETE_LABEL)
             for pr in additional_merged_prs:
-                pr.add_numbered_label("merged")
+                pr.add_numbered_label(MERGE_COMPLETE_LABEL)
 
         if comment_id and self.pr_num:
             # When the merge process reaches this part, we can assume that the commit
@@ -1751,6 +1764,9 @@
     initial_commit_sha = pr.last_commit()["oid"]
     print(f"Attempting merge of {initial_commit_sha}")
 
+    if MERGE_IN_PROGRESS_LABEL not in pr.get_labels():
+        gh_add_labels(org, project, pr_num, [MERGE_IN_PROGRESS_LABEL])
+
     explainer = TryMergeExplainer(
         skip_mandatory_checks, pr.get_labels(), pr.pr_num, org, project, ignore_current
     )
@@ -1983,7 +1999,6 @@
         message += '\nIf those updates are intentional, please add "submodule" keyword to PR title/description.'
         gh_post_pr_comment(org, project, args.pr_num, message, dry_run=args.dry_run)
         return
-
     try:
         merge(
             args.pr_num,
@@ -2020,6 +2035,7 @@
             )
         else:
             print("Missing comment ID or PR number, couldn't upload to Rockset")
+    pr.remove_label(MERGE_IN_PROGRESS_LABEL)
 
 
 if __name__ == "__main__":