Преглед изворни кода

Script to list PR comments (#128)

Jon Meow пре 5 година
родитељ
комит
fd4bf92717
2 измењених фајлова са 129 додато и 1 уклоњено
  1. 1 1
      .pre-commit-config.yaml
  2. 128 0
      src/scripts/pr-comments.py

+ 1 - 1
.pre-commit-config.yaml

@@ -19,7 +19,7 @@ repos:
     rev: v1.17.1
     hooks:
       - id: codespell
-        args: ['-L', 'copyable,circularly']
+        args: ['-L', 'circularly,copyable,pullrequest']
         exclude: '^src/jekyll/Gemfile.lock$'
   - repo: local
     hooks:

+ 128 - 0
src/scripts/pr-comments.py

@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+
+"""Figure out comments on a GitHub PR."""
+
+import argparse
+import os
+import sys
+import textwrap
+
+# https://pypi.org/project/gql/
+import gql
+import gql.transport.requests
+
+# Use https://developer.github.com/v4/explorer/ to help with edits.
+_QUERY = """
+{
+  repository(owner: "carbon-language", name: "carbon-lang") {
+    pullRequest(number: %d) {
+      reviewThreads(first: 100) {
+        totalCount
+        nodes {
+          comments(first: 100) {
+            nodes {
+              body
+              author {
+                login
+              }
+              url
+            }
+          }
+          isResolved
+          resolvedBy {
+            login
+          }
+        }
+      }
+      author {
+        login
+      }
+      title
+    }
+  }
+}
+"""
+
+
+def parse_args():
+    """Parses command-line arguments and flags."""
+    parser = argparse.ArgumentParser(description="Lists comments on a PR.")
+    parser.add_argument(
+        "pr_num",
+        metavar="PR#",
+        type=int,
+        nargs=1,
+        help="The pull request to fetch comments from.",
+    )
+    parser.add_argument(
+        "--github-access-token",
+        metavar="ACCESS_TOKEN",
+        help="The access token for use with GitHub. May also be specified in "
+        "the environment as GITHUB_ACCESS_TOKEN.",
+    )
+    parser.add_argument(
+        "--include-resolved",
+        action="store_true",
+        help="Whether to include resolved review threads. By default, only "
+        "unresolved threads will be shown.",
+    )
+    return parser.parse_args()
+
+
+def rewrap(content):
+    indent = "    "
+    lines = []
+    for line in content.split("\n"):
+        for x in textwrap.wrap(
+            line, width=80, initial_indent=indent, subsequent_indent=indent
+        ):
+            lines.append(x)
+    return "\n".join(lines)
+
+
+def main():
+    parsed_args = parse_args()
+    pr_num = parsed_args.pr_num[0]
+    access_token = parsed_args.github_access_token
+    include_resolved = parsed_args.include_resolved
+    if not access_token:
+        if "GITHUB_ACCESS_TOKEN" not in os.environ:
+            sys.exit(
+                "Missing github access token. This must be provided through "
+                "either --github-access-token or GITHUB_ACCESS_TOKEN."
+            )
+        access_token = os.environ["GITHUB_ACCESS_TOKEN"]
+
+    transport = gql.transport.requests.RequestsHTTPTransport(
+        url="https://api.github.com/graphql",
+        headers={"Authorization": "bearer %s" % access_token},
+    )
+    client = gql.Client(transport=transport, fetch_schema_from_transport=True)
+    threads_result = client.execute(gql.gql(_QUERY % pr_num))
+    pull_request = threads_result["repository"]["pullRequest"]
+    print(
+        "'%s' (%d) by %s"
+        % (pull_request["title"], pr_num, pull_request["author"]["login"])
+    )
+
+    for thread in pull_request["reviewThreads"]["nodes"]:
+        resolved = thread["isResolved"]
+        if resolved and not include_resolved:
+            continue
+        # TODO: Print relevant file/line. Possibly LOC.
+        print("\nThread (%s)" % ("resolved" if resolved else "unresolved"))
+        # TODO: Try to link to the review thread with an appropriate diff.
+        # Ideally comment-to-present, worst case original-to-comment (to see
+        # comment). Possibly both.
+        print("    %s" % thread["comments"]["nodes"][0]["url"])
+        # TODO: Add a short comment mode that does comment-per-line.
+        # TODO: Timestamps would be nice.
+        for comment in thread["comments"]["nodes"]:
+            print("  %s:" % comment["author"]["login"])
+            print(rewrap(comment["body"]))
+        if resolved:
+            print("  %s:\n    RESOLVED" % thread["resolvedBy"]["login"])
+
+
+if __name__ == "__main__":
+    main()