From c0a6caec2a89b9fca59986691432ccc3d18e4e0f Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:14:24 -0500 Subject: [PATCH 01/16] feat: Add Gemini Summarize PR --- .github/workflows/gemini_summarizer.yml | 34 ++++++++ gemini_summarize_pr.py | 110 ++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 .github/workflows/gemini_summarizer.yml create mode 100644 gemini_summarize_pr.py diff --git a/.github/workflows/gemini_summarizer.yml b/.github/workflows/gemini_summarizer.yml new file mode 100644 index 000000000..e8ffa324f --- /dev/null +++ b/.github/workflows/gemini_summarizer.yml @@ -0,0 +1,34 @@ +name: Gemini Pull Request Summarizer + +on: + pull_request: + types: [opened, edited, synchronize] + +permissions: + pull-requests: write + +jobs: + comment: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Dependencies + run: pip install google-cloud-aiplatform PyGithub + + - name: Set up Google Cloud credentials + uses: google-github-actions/setup-gcloud@v0 + with: + project_id: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} + service_account_key: ${{ secrets.GOOGLE_CREDENTIALS }} + + - name: Run Script + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: python gemini_summarize_pr.py diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py new file mode 100644 index 000000000..b7ae6ebea --- /dev/null +++ b/gemini_summarize_pr.py @@ -0,0 +1,110 @@ +import os +import json +import requests + +from github import Github + +import vertexai +from vertexai.generative_models import GenerationConfig, GenerativeModel + + +def get_pr_number() -> str: + event_path = os.getenv("GITHUB_EVENT_PATH", "") + + # Load event data + with open(event_path, "r", encoding="utf-8") as f: + event_data = json.load(f) + + # Determine the PR number based on the event + if "pull_request" in event_data: + return event_data["pull_request"]["number"] + + if ( + "issue" in event_data and "pull_request" in event_data["issue"] + ): # For comment events on PRs + return event_data["issue"]["number"] + + raise ValueError("Unable to determine pull request number from event data.") + + +def call_gemini( + pull_request_content: str, model_id: str = "gemini-1.5-flash-001" +) -> str: + vertexai.init() + + model = GenerativeModel( + model_id, + system_instruction=[ + "You are an expert software engineer.", + ], + generation_config=GenerationConfig(temperature=0.0), + ) + + prompt = [ + "The following is the content of a GitHub Pull Request for a repository focused on Generative AI with Google Cloud. This content includes the Pull Request title, Pull Request description, a list of all of the files changed with the file name, the code diff and the raw file content. Your task is to output a summary of the Pull Request in Markdown format.", + "Content:", + pull_request_content, + "Summary:", + ] + + print("---Prompt---\n", prompt) + response = model.generate_content(prompt) + print("---Gemini Response---\n", response) + return response.text + + +def summarize_pr(token: str, repo_name: str, pr_number: str): + # Create a GitHub client and access the repository + g = Github(token) + repo = g.get_repo(repo_name) + pr = repo.get_pull(pr_number) + + pull_request_content = "" + + # Extract and print title and description + pull_request_content += f"Title: {pr.title}\n" + pull_request_content += f"Pull Request Description: {pr.body}\n" + + # Fetch and print code diff + pull_request_content += "\n--- Files Changed ---\n" + for file in pr.get_files(): + pull_request_content += f"File name: {file.filename}\n\n" + + # Attempt to fetch raw content if patch is not available + if file.patch is None: + try: + raw_content = requests.get(file.raw_url).text + pull_request_content += f"Raw File Content:\n`\n{raw_content}\n`\n\n" + except requests.exceptions.RequestException: + pull_request_content += "Unable to fetch raw file content.\n\n" + else: # Use patch if available + pull_request_content += f"Code Diff:\n{file.patch}\n\n" + + gemini_response = call_gemini(pull_request_content) + + comment_body = f"## Pull Request Summary from Gemini ✨\n {gemini_response}" + + # Check for existing comments by the bot + bot_username = os.getenv("GITHUB_ACTOR") + + for comment in pr.get_issue_comments(): + if comment.user.login == bot_username: + # Update the existing comment + comment.edit(comment_body) + return + + # If no existing comment is found, create a new one + pr.create_issue_comment(comment_body) + + +def main(): + # Get GitHub token and repository details + repo_name = os.getenv("GITHUB_REPOSITORY") + token = os.getenv("GITHUB_TOKEN") + pr_number = get_pr_number() + + summarize_pr(token, repo_name=repo_name, pr_number=pr_number) + + +if __name__ == "__main__": + main() From 2a219e314f3ea43ae9791a36cee0255a140b2b15 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Tue, 11 Jun 2024 16:17:03 +0000 Subject: [PATCH 02/16] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- gemini_summarize_pr.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py index b7ae6ebea..be051857b 100644 --- a/gemini_summarize_pr.py +++ b/gemini_summarize_pr.py @@ -1,9 +1,8 @@ -import os import json -import requests +import os from github import Github - +import requests import vertexai from vertexai.generative_models import GenerationConfig, GenerativeModel From 54a4c02bf9df2a4497d3801b556fcfd00a3a032f Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:25:16 -0500 Subject: [PATCH 03/16] Add Google cloud project env variable --- .github/workflows/gemini_summarizer.yml | 1 + gemini_summarize_pr.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gemini_summarizer.yml b/.github/workflows/gemini_summarizer.yml index e8ffa324f..b0ab35157 100644 --- a/.github/workflows/gemini_summarizer.yml +++ b/.github/workflows/gemini_summarizer.yml @@ -31,4 +31,5 @@ jobs: - name: Run Script env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GOOGLE_CLOUD_PROJECT_ID: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} run: python gemini_summarize_pr.py diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py index be051857b..8860e8d36 100644 --- a/gemini_summarize_pr.py +++ b/gemini_summarize_pr.py @@ -29,7 +29,8 @@ def get_pr_number() -> str: def call_gemini( pull_request_content: str, model_id: str = "gemini-1.5-flash-001" ) -> str: - vertexai.init() + project_id = os.getenv("GOOGLE_CLOUD_PROJECT_ID") + vertexai.init(project=project_id, location="us-central1") model = GenerativeModel( model_id, From b207cae9a586c8c8e587ca97163f3f3941e897de Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:32:25 -0500 Subject: [PATCH 04/16] Update authentication --- .github/workflows/gemini_summarizer.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gemini_summarizer.yml b/.github/workflows/gemini_summarizer.yml index b0ab35157..7c3522ca4 100644 --- a/.github/workflows/gemini_summarizer.yml +++ b/.github/workflows/gemini_summarizer.yml @@ -22,11 +22,16 @@ jobs: - name: Install Dependencies run: pip install google-cloud-aiplatform PyGithub - - name: Set up Google Cloud credentials - uses: google-github-actions/setup-gcloud@v0 + - id: 'auth' + uses: 'google-github-actions/auth@v0' with: - project_id: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} - service_account_key: ${{ secrets.GOOGLE_CREDENTIALS }} + credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' + + - name: 'Set up Cloud SDK' + uses: 'google-github-actions/setup-gcloud@v0' + + - name: 'Use gcloud CLI' + run: 'gcloud info' - name: Run Script env: From b14138bb387ab6a0fac45d4e2eef0ce568352278 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:34:50 -0500 Subject: [PATCH 05/16] Udpate auth to v2 --- .github/workflows/gemini_summarizer.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gemini_summarizer.yml b/.github/workflows/gemini_summarizer.yml index 7c3522ca4..d3c50d918 100644 --- a/.github/workflows/gemini_summarizer.yml +++ b/.github/workflows/gemini_summarizer.yml @@ -23,13 +23,13 @@ jobs: run: pip install google-cloud-aiplatform PyGithub - id: 'auth' - uses: 'google-github-actions/auth@v0' + uses: 'google-github-actions/auth@v2' with: credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}' - + - name: 'Set up Cloud SDK' - uses: 'google-github-actions/setup-gcloud@v0' - + uses: 'google-github-actions/setup-gcloud@v2' + - name: 'Use gcloud CLI' run: 'gcloud info' From b1c3b2fa647940abfa0cd0f587b21bd3591bb2bf Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:36:06 -0500 Subject: [PATCH 06/16] Remove Gemini-created header --- gemini_summarize_pr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py index 8860e8d36..34b7e1248 100644 --- a/gemini_summarize_pr.py +++ b/gemini_summarize_pr.py @@ -50,7 +50,8 @@ def call_gemini( print("---Prompt---\n", prompt) response = model.generate_content(prompt) print("---Gemini Response---\n", response) - return response.text + + return response.text.replace(" ## Pull Request Summary", "") def summarize_pr(token: str, repo_name: str, pr_number: str): From 969d3f4bfc37722c119dd64118645768f6e45eae Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:46:59 -0500 Subject: [PATCH 07/16] Add latest commit and debugging for comments --- gemini_summarize_pr.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py index 34b7e1248..040e1a96c 100644 --- a/gemini_summarize_pr.py +++ b/gemini_summarize_pr.py @@ -83,13 +83,17 @@ def summarize_pr(token: str, repo_name: str, pr_number: str): gemini_response = call_gemini(pull_request_content) - comment_body = f"## Pull Request Summary from Gemini ✨\n {gemini_response}" + latest_commit = pr.get_commits()[0].sha + comment_header = "## Pull Request Summary from Gemini ✨" + comment_body = ( + f"{comment_header}\n {gemini_response} --- \n Generated at `{latest_commit}`\n" + ) # Check for existing comments by the bot bot_username = os.getenv("GITHUB_ACTOR") - + print(bot_username) for comment in pr.get_issue_comments(): - if comment.user.login == bot_username: + if comment.user.login == bot_username and comment_header in comment.body: # Update the existing comment comment.edit(comment_body) return From 472660a48d5d3ffd434ce97b52967712a8a76426 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 11:53:52 -0500 Subject: [PATCH 08/16] Update GITHUB_ACTOR to github-actions --- gemini_summarize_pr.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gemini_summarize_pr.py b/gemini_summarize_pr.py index 040e1a96c..a167eebb1 100644 --- a/gemini_summarize_pr.py +++ b/gemini_summarize_pr.py @@ -51,7 +51,7 @@ def call_gemini( response = model.generate_content(prompt) print("---Gemini Response---\n", response) - return response.text.replace(" ## Pull Request Summary", "") + return response.text.replace("## Pull Request Summary", "") def summarize_pr(token: str, repo_name: str, pr_number: str): @@ -85,20 +85,19 @@ def summarize_pr(token: str, repo_name: str, pr_number: str): latest_commit = pr.get_commits()[0].sha comment_header = "## Pull Request Summary from Gemini ✨" - comment_body = ( - f"{comment_header}\n {gemini_response} --- \n Generated at `{latest_commit}`\n" - ) + comment_body = f"{comment_header}\n {gemini_response} \n---\n " # Check for existing comments by the bot - bot_username = os.getenv("GITHUB_ACTOR") - print(bot_username) + bot_username = "github-actions[bot]" for comment in pr.get_issue_comments(): if comment.user.login == bot_username and comment_header in comment.body: # Update the existing comment + comment_body += f"Updated at `{latest_commit}`\n" comment.edit(comment_body) return # If no existing comment is found, create a new one + comment_body += f"Generated at `{latest_commit}`\n" pr.create_issue_comment(comment_body) From c88cfc74ac211ae38a4ed50ad03fff65be080110 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:25:07 -0500 Subject: [PATCH 09/16] Moved/Refactored Summarize file and updated excludes.txt --- .github/actions/spelling/excludes.txt | 1 + .../actions/summarizer/gemini_summarize_pr.py | 45 +++++++++---------- .github/workflows/gemini_summarizer.yml | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) rename gemini_summarize_pr.py => .github/actions/summarizer/gemini_summarize_pr.py (68%) diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 1c98a8cd0..3b0c8d634 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -100,3 +100,4 @@ ^\Qvision/getting-started/visual_captioning.ipynb\E$ ^\Qvision/use-cases/creating_high_quality_visual_assets_with_gemini_and_imagen.ipynb\E$ ignore$ +^\Q.github/actions/summarizer/gemini_summarize_pr.py\E$ diff --git a/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py similarity index 68% rename from gemini_summarize_pr.py rename to .github/actions/summarizer/gemini_summarize_pr.py index a167eebb1..5fd8a3e14 100644 --- a/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -54,50 +54,47 @@ def call_gemini( return response.text.replace("## Pull Request Summary", "") -def summarize_pr(token: str, repo_name: str, pr_number: str): - # Create a GitHub client and access the repository +def summarize_pr(token, repo_name, pr_number): + """Summarizes the pull request using the Gemini model and updates/creates a comment.""" g = Github(token) repo = g.get_repo(repo_name) pr = repo.get_pull(pr_number) - pull_request_content = "" + pr_content = f""" + Title: {pr.title} + Pull Request Description: {pr.body} + + --- Files Changed --- + """ - # Extract and print title and description - pull_request_content += f"Title: {pr.title}\n" - pull_request_content += f"Pull Request Description: {pr.body}\n" - - # Fetch and print code diff - pull_request_content += "\n--- Files Changed ---\n" for file in pr.get_files(): - pull_request_content += f"File name: {file.filename}\n\n" + pr_content += f"File name: {file.filename}\n\n" # Attempt to fetch raw content if patch is not available if file.patch is None: try: raw_content = requests.get(file.raw_url).text - pull_request_content += f"Raw File Content:\n`\n{raw_content}\n`\n\n" + pr_content += f"Raw File Content:\n`\n{raw_content}\n`\n\n" except requests.exceptions.RequestException: - pull_request_content += "Unable to fetch raw file content.\n\n" + pr_content += "Unable to fetch raw file content.\n\n" else: # Use patch if available - pull_request_content += f"Code Diff:\n{file.patch}\n\n" - - gemini_response = call_gemini(pull_request_content) + pr_content += f"Code Diff:\n{file.patch}\n\n" - latest_commit = pr.get_commits()[0].sha - comment_header = "## Pull Request Summary from Gemini ✨" - comment_body = f"{comment_header}\n {gemini_response} \n---\n " + summary = call_gemini(pr_content) - # Check for existing comments by the bot + comment_header = "## Pull Request Summary from [Gemini ✨](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)" + comment_body = ( + f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits()[0].sha}`" + ) bot_username = "github-actions[bot]" + + # Find and update existing bot comment if any for comment in pr.get_issue_comments(): if comment.user.login == bot_username and comment_header in comment.body: - # Update the existing comment - comment_body += f"Updated at `{latest_commit}`\n" comment.edit(comment_body) return - # If no existing comment is found, create a new one - comment_body += f"Generated at `{latest_commit}`\n" + # Create a new comment if none exists pr.create_issue_comment(comment_body) @@ -107,7 +104,7 @@ def main(): token = os.getenv("GITHUB_TOKEN") pr_number = get_pr_number() - summarize_pr(token, repo_name=repo_name, pr_number=pr_number) + summarize_pr(token, repo_name, pr_number) if __name__ == "__main__": diff --git a/.github/workflows/gemini_summarizer.yml b/.github/workflows/gemini_summarizer.yml index d3c50d918..87b2bad21 100644 --- a/.github/workflows/gemini_summarizer.yml +++ b/.github/workflows/gemini_summarizer.yml @@ -37,4 +37,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CLOUD_PROJECT_ID: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} - run: python gemini_summarize_pr.py + run: python .github/actions/summarizer/gemini_summarize_pr.py From 4a1c3868ee2eaa32b4f95006ecfd13a42b7d914a Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:28:54 -0500 Subject: [PATCH 10/16] Change commit number to be last commit. Updated system prompt --- .github/actions/summarizer/gemini_summarize_pr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index 5fd8a3e14..8ce09129d 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -35,7 +35,7 @@ def call_gemini( model = GenerativeModel( model_id, system_instruction=[ - "You are an expert software engineer.", + "You are an expert software engineer, proficient in Generative AI, Git and GitHub.", ], generation_config=GenerationConfig(temperature=0.0), ) @@ -84,7 +84,7 @@ def summarize_pr(token, repo_name, pr_number): comment_header = "## Pull Request Summary from [Gemini ✨](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)" comment_body = ( - f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits()[0].sha}`" + f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits()[-1].sha}`" ) bot_username = "github-actions[bot]" From 60187a64657b9aea072e53c267274c544738e824 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:43:23 -0500 Subject: [PATCH 11/16] Fix lint errors --- .../actions/summarizer/gemini_summarize_pr.py | 96 +++++++++++-------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index 8ce09129d..2585fc1f5 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -1,15 +1,18 @@ +"""Summarizes the pull request using the Gemini model and adds summary to a PR comment.""" + import json import os +import requests from github import Github -import requests import vertexai from vertexai.generative_models import GenerationConfig, GenerativeModel +GEMINI_MODEL = "gemini-1.5-flash-001" -def get_pr_number() -> str: - event_path = os.getenv("GITHUB_EVENT_PATH", "") +def get_pr_number(event_path: str) -> str: + """Retrieves the pull request number from GitHub event data.""" # Load event data with open(event_path, "r", encoding="utf-8") as f: event_data = json.load(f) @@ -26,22 +29,53 @@ def get_pr_number() -> str: raise ValueError("Unable to determine pull request number from event data.") -def call_gemini( - pull_request_content: str, model_id: str = "gemini-1.5-flash-001" +def get_pr_content(pr: Github.PullRequest) -> str: + """Returns the content of the pull request as a string.""" + pr_content = f""" + Title: {pr.title} + Pull Request Description: {pr.body} + + --- Files Changed --- + """ + + for file in pr.get_files(): + pr_content += f"File name: {file.filename}\n\n" + + # Attempt to fetch raw content if patch is not available + if file.patch is None: + try: + raw_content = requests.get(file.raw_url, timeout=10).text + pr_content += f"Raw File Content:\n`\n{raw_content}\n`\n\n" + except requests.exceptions.RequestException: + pr_content += "Unable to fetch raw file content.\n\n" + else: # Use patch if available + pr_content += f"Code Diff:\n{file.patch}\n\n" + + return pr_content + + +def summarize_pr_gemini( + pull_request_content: str, + project_id: str, + location: str = "us-central1", + model_id: str = GEMINI_MODEL, ) -> str: - project_id = os.getenv("GOOGLE_CLOUD_PROJECT_ID") - vertexai.init(project=project_id, location="us-central1") + """Calls the Gemini model to summarize the pull request content.""" + vertexai.init(project=project_id, location=location) model = GenerativeModel( model_id, system_instruction=[ "You are an expert software engineer, proficient in Generative AI, Git and GitHub.", ], - generation_config=GenerationConfig(temperature=0.0), + generation_config=GenerationConfig(temperature=0.0, max_output_tokens=8192), ) prompt = [ - "The following is the content of a GitHub Pull Request for a repository focused on Generative AI with Google Cloud. This content includes the Pull Request title, Pull Request description, a list of all of the files changed with the file name, the code diff and the raw file content. Your task is to output a summary of the Pull Request in Markdown format.", + "The following is the content of a GitHub Pull Request for a repository focused on Generative AI with Google Cloud." + "This content includes the Pull Request title, Pull Request description, " + "a list of all of the files changed with the file name, the code diff and the raw file content." + "Your task is to output a summary of the Pull Request in Markdown format.", "Content:", pull_request_content, "Summary:", @@ -54,34 +88,8 @@ def call_gemini( return response.text.replace("## Pull Request Summary", "") -def summarize_pr(token, repo_name, pr_number): - """Summarizes the pull request using the Gemini model and updates/creates a comment.""" - g = Github(token) - repo = g.get_repo(repo_name) - pr = repo.get_pull(pr_number) - - pr_content = f""" - Title: {pr.title} - Pull Request Description: {pr.body} - - --- Files Changed --- - """ - - for file in pr.get_files(): - pr_content += f"File name: {file.filename}\n\n" - - # Attempt to fetch raw content if patch is not available - if file.patch is None: - try: - raw_content = requests.get(file.raw_url).text - pr_content += f"Raw File Content:\n`\n{raw_content}\n`\n\n" - except requests.exceptions.RequestException: - pr_content += "Unable to fetch raw file content.\n\n" - else: # Use patch if available - pr_content += f"Code Diff:\n{file.patch}\n\n" - - summary = call_gemini(pr_content) - +def add_pr_comment(pr: Github.PullRequest, summary: str) -> None: + """Comments on the pull request with the provided summary.""" comment_header = "## Pull Request Summary from [Gemini ✨](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)" comment_body = ( f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits()[-1].sha}`" @@ -98,13 +106,21 @@ def summarize_pr(token, repo_name, pr_number): pr.create_issue_comment(comment_body) -def main(): +def main() -> None: + """Summarizes the pull request using the Gemini model and adds summary to a PR comment.""" + # Get GitHub token and repository details repo_name = os.getenv("GITHUB_REPOSITORY") token = os.getenv("GITHUB_TOKEN") - pr_number = get_pr_number() + pr_number = get_pr_number(os.getenv("GITHUB_EVENT_PATH", "")) + + g = Github(token) + repo = g.get_repo(repo_name) + pr = repo.get_pull(pr_number) - summarize_pr(token, repo_name, pr_number) + pr_content = get_pr_content(pr) + summary = summarize_pr_gemini(pr_content, os.getenv("GOOGLE_CLOUD_PROJECT_ID", "")) + add_pr_comment(pr, summary) if __name__ == "__main__": From 0f2d64982586bf97ed96de47a7ce3bd44a7cbe72 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Tue, 11 Jun 2024 17:45:42 +0000 Subject: [PATCH 12/16] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .github/actions/summarizer/gemini_summarize_pr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index 2585fc1f5..410ec4c77 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -2,9 +2,9 @@ import json import os -import requests from github import Github +import requests import vertexai from vertexai.generative_models import GenerationConfig, GenerativeModel From 66ea2fb211ab477384b29e887b12a4a7b8d899cb Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:49:12 -0500 Subject: [PATCH 13/16] Fix typing --- .github/actions/summarizer/gemini_summarize_pr.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index 2585fc1f5..0755ae26a 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -4,14 +4,14 @@ import os import requests -from github import Github +from github import Github, PullRequest import vertexai from vertexai.generative_models import GenerationConfig, GenerativeModel GEMINI_MODEL = "gemini-1.5-flash-001" -def get_pr_number(event_path: str) -> str: +def get_pr_number(event_path: str) -> int: """Retrieves the pull request number from GitHub event data.""" # Load event data with open(event_path, "r", encoding="utf-8") as f: @@ -19,17 +19,17 @@ def get_pr_number(event_path: str) -> str: # Determine the PR number based on the event if "pull_request" in event_data: - return event_data["pull_request"]["number"] + return int(event_data["pull_request"]["number"]) if ( "issue" in event_data and "pull_request" in event_data["issue"] ): # For comment events on PRs - return event_data["issue"]["number"] + return int(event_data["issue"]["number"]) raise ValueError("Unable to determine pull request number from event data.") -def get_pr_content(pr: Github.PullRequest) -> str: +def get_pr_content(pr: PullRequest.PullRequest) -> str: """Returns the content of the pull request as a string.""" pr_content = f""" Title: {pr.title} @@ -88,7 +88,7 @@ def summarize_pr_gemini( return response.text.replace("## Pull Request Summary", "") -def add_pr_comment(pr: Github.PullRequest, summary: str) -> None: +def add_pr_comment(pr: PullRequest.PullRequest, summary: str) -> None: """Comments on the pull request with the provided summary.""" comment_header = "## Pull Request Summary from [Gemini ✨](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)" comment_body = ( @@ -110,7 +110,7 @@ def main() -> None: """Summarizes the pull request using the Gemini model and adds summary to a PR comment.""" # Get GitHub token and repository details - repo_name = os.getenv("GITHUB_REPOSITORY") + repo_name = os.getenv("GITHUB_REPOSITORY", "") token = os.getenv("GITHUB_TOKEN") pr_number = get_pr_number(os.getenv("GITHUB_EVENT_PATH", "")) From ace0c0448de09ec9ed0560bff60f7f62e8e2b82d Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:55:27 -0500 Subject: [PATCH 14/16] Update most recent commit --- .github/actions/summarizer/gemini_summarize_pr.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index dc355df26..89c1c9e56 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -91,9 +91,7 @@ def summarize_pr_gemini( def add_pr_comment(pr: PullRequest.PullRequest, summary: str) -> None: """Comments on the pull request with the provided summary.""" comment_header = "## Pull Request Summary from [Gemini ✨](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)" - comment_body = ( - f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits()[-1].sha}`" - ) + comment_body = f"{comment_header}\n{summary}\n---\nGenerated at `{pr.get_commits().reversed[0].sha}`" bot_username = "github-actions[bot]" # Find and update existing bot comment if any From 21384ecc3dbbfc6b248f3aad5631428ea484d4a4 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 12:59:17 -0500 Subject: [PATCH 15/16] Add lint ignore --- .github/actions/summarizer/gemini_summarize_pr.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index 89c1c9e56..b80ab183f 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -72,10 +72,12 @@ def summarize_pr_gemini( ) prompt = [ + # pylint: disable=line-too-long "The following is the content of a GitHub Pull Request for a repository focused on Generative AI with Google Cloud." "This content includes the Pull Request title, Pull Request description, " "a list of all of the files changed with the file name, the code diff and the raw file content." "Your task is to output a summary of the Pull Request in Markdown format.", + # pylint: enable=line-too-long "Content:", pull_request_content, "Summary:", From 71af137d524b769fa83a86a09279c39e1728b85e Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 11 Jun 2024 13:02:05 -0500 Subject: [PATCH 16/16] Add line-too-long ignore throughout --- .github/actions/summarizer/gemini_summarize_pr.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/actions/summarizer/gemini_summarize_pr.py b/.github/actions/summarizer/gemini_summarize_pr.py index b80ab183f..3fec33c90 100644 --- a/.github/actions/summarizer/gemini_summarize_pr.py +++ b/.github/actions/summarizer/gemini_summarize_pr.py @@ -1,5 +1,6 @@ """Summarizes the pull request using the Gemini model and adds summary to a PR comment.""" +# pylint: disable=line-too-long import json import os @@ -72,12 +73,10 @@ def summarize_pr_gemini( ) prompt = [ - # pylint: disable=line-too-long "The following is the content of a GitHub Pull Request for a repository focused on Generative AI with Google Cloud." "This content includes the Pull Request title, Pull Request description, " "a list of all of the files changed with the file name, the code diff and the raw file content." "Your task is to output a summary of the Pull Request in Markdown format.", - # pylint: enable=line-too-long "Content:", pull_request_content, "Summary:",