Let AI write emails and messages for you 🔥

Using ChatGPT to review Github Pull Request

Gourav Goyal

Gourav Goyal

Sep 28, 2023

You can consider using AI for your initial round of basic code reviews before asking a human for a review. While AI-performed code reviews may not always be 100% accurate, they are still useful for spotting issues that you or the human reviewer might have missed. The approach for using AI in code review is quite simple: extract code changes from a GitHub pull request and ask ChatGPT to review them. Even with limited context, current AI tools are capable of performing initial code reviews. Scroll to the end to see a sample code review result performed by GPT-4.

Which AI tool performs the best code review?

I asked various AI tools to review code, including Bard, GitHub CoPilot, Phind, and Perplexity AI. They did a poor job. Rix performed slightly better, as it runs on Claude 2. GPT-3.5 also showed better performance. However, GPT-4 offered the best code review, catching even subtle bugs.

Getting Started

We'll be using GitHub CLI (gh) to easily obtain PR details so you need to install it first. It's available for all major operating systems.

Note: You can also choose to use git for fetching PR details, but I find GitHub CLI (gh) more straightforward.

Step 1: Copy PR details to clipboard

We will be using these 2 commands:

  1. gh pr view - Displays the title, body, and other information about a pull request for the current branch.

Example output:

title:	Fix paste issue
state:	OPEN
author:	authorX
labels:	
assignees:	
reviewers:	GorvGoyl (Requested)
projects:	
milestone:	
number:	10
url:	https://github.com/GorvGoyl/repo-name/pull/10
additions:	45
deletions:	1
auto-merge:	disabled
--
## PR Description
Fixed an issue where pasting text into command context and generation instructions was not happening. It occured due to onPaste not being handled on textarea and input, so other elements on the page were taking over that event.
  1. gh pr diff - Views code changes in a pull request for the current branch.

Example output:

diff --git a/contents/writer.tsx b/contents/writer.tsx
index 8f79d01..0b77b4e 100644
--- a/contents/writer.tsx
+++ b/contents/writer.tsx
@@ -195,7 +195,7 @@ function renderCGWBtnOnGmailToolbar(e: any) {
   );
   if (!el_gmail_email_boxes) return;
 
-  for (const el_gmail_box of el_gmail_email_boxes) {
+  for (const el_gmail_box of el_gmail_email_boxes as any as Element[]) {
     const el_gmail_toolbar = el_gmail_box.querySelector("tbody > tr.btC");
     if (!el_gmail_toolbar) {
       console.warn(
@@ -431,7 +431,49 @@ function ComposerUI() {
       }
     }
   }
+  // issue was the site's input boxes were capturing the onPaste event, so we need
+  // to manually handle the paste action in our inputs
 
+  function handlePaste(
+    e: React.ClipboardEvent<HTMLTextAreaElement | HTMLInputElement>
+  ) {
+    e.preventDefault();
+
+    const text = e.clipboardData.getData("text/plain") || "";
+    const inputEl = e.target as HTMLTextAreaElement | HTMLInputElement;
+
+    const start_position = inputEl.selectionStart || 0;
+    const end_position = inputEl.selectionEnd || 0;
+
+    if (document.execCommand && typeof document.execCommand === "function") {
+      // Save the current selection
+      const savedSelectionStart = inputEl.selectionStart || 0;
+      const savedSelectionEnd = inputEl.selectionEnd || 0;
+
+      // Insert the text using execCommand
+      document.execCommand("insertText", false, text);
+
+      // Restore the selection
+      inputEl.setSelectionRange(
+        savedSelectionStart + text.length,
+        savedSelectionEnd + text.length
+      );
+    } else {
+      // Fallback for browsers that don't support execCommand
+      const insertText = `${inputEl.value.substring(
+        0,
+        start_position
+      )}${text}${inputEl.value.substring(end_position)}`;
+      inputEl.value = insertText;
+    }
+
+    if (inputEl instanceof HTMLTextAreaElement) {
+      stateComposerSource.messageContext = inputEl.value;
+      resizeTextarea(inputEl);
+    } else {
+      stateComposerSource.responseGenerationInstruction = inputEl.value;
+    }
+  }
   return (
     <div className="w-[700px]">
       <ModalHeaderUI
@@ -452,6 +494,7 @@ function ComposerUI() {
                 e.preventDefault();
                 stateComposerSource.messageContext = e.target.value;
               }}
+              onPaste={handlePaste}
               className={formStyles.input}
               placeholder={stateComposerRender.composerCopy.contextPlaceholder}
               name="email-context"
@@ -549,6 +592,7 @@ function ComposerUI() {
                 onKeyPressCapture={(e) => {
                   e.stopPropagation();
                 }}
+                onPaste={handlePaste}
               />
             </div>
             <div className="mt-1">

Note: If the code changes exceed the allowed input length of the AI model, you can reduce some changes and try again.

You can use the following one-liner code to copy PR details and code diff to the clipboard:

One-Liner to Copy PR Details Including Diff of the Current Branch to Clipboard

For Mac:

{ gh pr view; gh pr diff; } | pbcopy

For Windows:

(gh pr view && gh pr diff) | clip

One-Liner to Copy Details of a Specific PR to Clipboard

Replace PR_NUM with the GitHub pull request number.

For Mac:

PR_NUM=12; { gh pr view $PR_NUM; gh pr diff $PR_NUM; } | pbcopy

For Windows:

set PR_NUM=12 && (gh pr view %PR_NUM% && gh pr diff %PR_NUM%) | clip

Step 2: Ask ChatGPT to Review the PR

Here's the prompt I use:

Perform a code review of the GitHub pull request below.
Include code snippets and examples in your suggestions wherever possible.
Here are the pull request details, including the diff:

{paste_github_pull_request_details_from_clipboard}

Here’s the example response:

Let me know your thoughts on this approach at hey@gourav.io

That's all, folks!

Gourav Goyal

Gourav Goyal