From 83419710f93e6cb8e087ba40c5ab8e1c5cb64725 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 17:30:12 -0500
Subject: [PATCH 01/11] chore: refactor rigging pr decorator
---
.github/scripts/rigging_pr_decorator.py | 201 ++++++++----------------
1 file changed, 68 insertions(+), 133 deletions(-)
diff --git a/.github/scripts/rigging_pr_decorator.py b/.github/scripts/rigging_pr_decorator.py
index feb4bd6..11a7f85 100644
--- a/.github/scripts/rigging_pr_decorator.py
+++ b/.github/scripts/rigging_pr_decorator.py
@@ -1,142 +1,77 @@
+# /// script
+# requires-python = ">=3.10"
+# dependencies = [
+# "rigging",
+# "typer",
+# ]
+# ///
+
import asyncio
-import base64
-import os
+import subprocess
import typing as t
-from pydantic import ConfigDict, StringConstraints
+import typer
import rigging as rg
-from rigging import logger
-from rigging.generator import GenerateParams, Generator, register_generator
-
-logger.enable("rigging")
-
-MAX_TOKENS = 8000
-TRUNCATION_WARNING = "\n\n**Note**: Due to the large size of this diff, some content has been truncated."
-str_strip = t.Annotated[str, StringConstraints(strip_whitespace=True)]
-
-
-class PRDiffData(rg.Model):
- """XML model for PR diff data"""
-
- content: str_strip = rg.element()
-
- @classmethod
- def xml_example(cls) -> str:
- return """example diff content"""
-
-
-class PRDecorator(Generator):
- """Generator for creating PR descriptions"""
-
- model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)
-
- api_key: str = ""
- max_tokens: int = MAX_TOKENS
-
- def __init__(self, model: str, params: rg.GenerateParams) -> None:
- api_key = params.extra.get("api_key")
- if not api_key:
- raise ValueError("api_key is required in params.extra")
-
- super().__init__(model=model, params=params, api_key=api_key)
- self.api_key = api_key
- self.max_tokens = params.max_tokens or MAX_TOKENS
-
- async def generate_messages(
- self,
- messages: t.Sequence[t.Sequence[rg.Message]],
- params: t.Sequence[GenerateParams],
- ) -> t.Sequence[rg.GeneratedMessage]:
- responses = []
- for message_seq, p in zip(messages, params):
- base_generator = rg.get_generator(self.model, params=p)
- llm_response = await base_generator.generate_messages([message_seq], [p])
- responses.extend(llm_response)
- return responses
-
-
-register_generator("pr_decorator", PRDecorator)
-
-
-async def generate_pr_description(diff_text: str) -> str:
- """Generate a PR description from the diff text"""
- diff_tokens = len(diff_text) // 4
- if diff_tokens >= MAX_TOKENS:
- char_limit = (MAX_TOKENS * 4) - len(TRUNCATION_WARNING)
- diff_text = diff_text[:char_limit] + TRUNCATION_WARNING
-
- diff_data = PRDiffData(content=diff_text)
- params = rg.GenerateParams(
- extra={
- "api_key": os.environ["OPENAI_API_KEY"],
- "diff_text": diff_text,
- },
- temperature=0.1,
- max_tokens=500,
- )
-
- generator = rg.get_generator("pr_decorator!gpt-4-turbo-preview", params=params)
- prompt = f"""You are a helpful AI that generates clear and concise PR descriptions with some pirate tongue.
- Analyze the provided git diff and create a summary, specifically focusing on the elements of the code that
- has changed, high severity functions etc using exactly this format:
-
- ### PR Summary
-
- #### Overview of Changes
-
-
- #### Key Modifications
- 1. ****:
- (continue as needed)
-
- #### Potential Impact
- -
- (continue as needed)
-
- Here is the PR diff to analyze:
- {diff_data.to_xml()}"""
-
- chat = await generator.chat(prompt).run()
- return chat.last.content.strip()
-
-
-async def main():
- """Main function for CI environment"""
- if not os.environ.get("OPENAI_API_KEY"):
- raise ValueError("OPENAI_API_KEY environment variable must be set")
-
- try:
- diff_text = os.environ.get("GIT_DIFF", "")
- if not diff_text:
- raise ValueError("No diff found in GIT_DIFF environment variable")
-
- try:
- diff_text = base64.b64decode(diff_text).decode("utf-8")
- except Exception:
- padding = 4 - (len(diff_text) % 4)
- if padding != 4:
- diff_text += "=" * padding
- diff_text = base64.b64decode(diff_text).decode("utf-8")
- logger.debug(f"Processing diff of length: {len(diff_text)}")
- description = await generate_pr_description(diff_text)
-
- with open(os.environ["GITHUB_OUTPUT"], "a") as f:
- f.write("content< t.Annotated[str, rg.Ctx("markdown")]: # type: ignore[empty-body]
+ """
+ Analyze the provided git diff and create a PR description in markdown format.
+
+
+ - Keep the summary concise and informative.
+ - Use bullet points to structure important statements.
+ - Focus on key modifications and potential impact - if any.
+ - Do not add in general advice or best-practice information.
+ - Write like a developer who authored the changes.
+ - Prefer flat bullet lists over nested.
+ - Do not include any title structure.
+
+ """
+
+
+def get_diff(target_ref: str, source_ref: str) -> str:
+ """
+ Get the git diff between two branches.
+ """
+
+ merge_base = subprocess.run(
+ ["git", "merge-base", source_ref, target_ref],
+ capture_output=True,
+ text=True,
+ check=True,
+ ).stdout.strip()
+ diff_text = subprocess.run(
+ ["git", "diff", merge_base],
+ capture_output=True,
+ text=True,
+ check=True,
+ ).stdout
+ return diff_text
+
+
+def main(
+ target_ref: str,
+ source_ref: str = "HEAD",
+ generator_id: str = "openai/gpt-4o-mini",
+ max_diff_lines: int = 1000,
+) -> None:
+ """
+ Use rigging to generate a PR description from a git diff.
+ """
+
+ diff = get_diff(target_ref, source_ref)
+ diff_lines = diff.split("\n")
+ if len(diff_lines) > max_diff_lines:
+ diff = "\n".join(diff_lines[:max_diff_lines]) + TRUNCATION_WARNING
+
+ description = asyncio.run(generate_pr_description.bind(generator_id)(diff))
+ print(description)
if __name__ == "__main__":
- asyncio.run(main())
\ No newline at end of file
+ typer.run(main)
From f303cbfe1c0906630aa6f1ae49326e9fd1390ff7 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 20:08:03 -0500
Subject: [PATCH 02/11] fix: refactor workflow
---
.github/workflows/rigging_pr_description.yml | 46 ++++++++------------
1 file changed, 19 insertions(+), 27 deletions(-)
diff --git a/.github/workflows/rigging_pr_description.yml b/.github/workflows/rigging_pr_description.yml
index 5bb8b8f..1be4efa 100644
--- a/.github/workflows/rigging_pr_description.yml
+++ b/.github/workflows/rigging_pr_description.yml
@@ -2,7 +2,7 @@ name: Update PR Description with Rigging
on:
pull_request:
- types: [opened]
+ types: [opened, synchronize]
jobs:
update-description:
@@ -12,48 +12,40 @@ jobs:
contents: read
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
- fetch-depth: 0
+ fetch-depth: 0 # full history for proper diffing
- # Get the diff first
- - name: Get Diff
- id: diff
- # shellcheck disable=SC2102
- run: |
- git fetch origin "${{ github.base_ref }}"
- MERGE_BASE=$(git merge-base HEAD "origin/${{ github.base_ref }}")
- # Use separate diff arguments instead of range notation
- DIFF=$(git diff "$MERGE_BASE" HEAD | base64 --wrap=0)
- echo "diff=${DIFF}" >> "$GITHUB_OUTPUT"
- - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b #v5.0.3
+ - name: Set up Python
+ uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.0.3
with:
- python-version: "3.11"
+ python-version: "3.10"
- - name: Install dependencies
+ - name: Install uv
run: |
python -m pip install --upgrade pip
- pip cache purge
- pip install pydantic
- pip install rigging[all]
- # Generate the description using the diff
+ pip install uv
+
- name: Generate PR Description
id: description
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- PR_NUMBER: ${{ github.event.pull_request.number }}
- GIT_DIFF: ${{ steps.diff.outputs.diff }}
run: |
- python .github/scripts/rigging_pr_decorator.py
- # Update the PR description
+ DESCRIPTION=$(uv run --no-project .github/scripts/rigging_pr_decorator.py origin/${{ github.base_ref }})
+ echo "description<> $GITHUB_OUTPUT
+ echo "$DESCRIPTION" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
- name: Update PR Description
- uses: nefrob/pr-description@4dcc9f3ad5ec06b2a197c5f8f93db5e69d2fdca7 #v1.2.0
+ uses: nefrob/pr-description@4dcc9f3ad5ec06b2a197c5f8f93db5e69d2fdca7 # v1.2.0
with:
content: |
## AI-Generated Summary
- ${{ steps.description.outputs.content }}
+
+ ${{ steps.description.outputs.description }}
+
---
+
This summary was generated with ❤️ by [rigging](https://rigging.dreadnode.io/)
regex: ".*"
regexFlags: s
From 9c908330e8e0d87476315773d0c15189ffe7a813 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 20:10:08 -0500
Subject: [PATCH 03/11] chore: tmp exclusion
---
.pre-commit-config.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e2e0634..720dbe3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -35,3 +35,4 @@ repos:
entry: python .scripts/check_pinned_hash_dependencies.py
language: python
files: \.github/.*\.yml$
+ exclude: ^\.github/workflows/.*\.yml$
From 1862b9482d9ebd5ca8b2466f28ba1be9d7a1485d Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:27:14 -0500
Subject: [PATCH 04/11] fix: excludes in wrong block
---
.pre-commit-config.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 720dbe3..3304d43 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -18,6 +18,7 @@ repos:
- id: actionlint
name: Check Github Actions
args: ["--ignore", "SC2102"]
+ exclude: ^rigging_pr_decorator\.py$
# Python code security
- repo: https://github.com/PyCQA/bandit
@@ -26,6 +27,7 @@ repos:
- id: bandit
name: Code security checks
args: ["-r", "--level", "2", "./"]
+ exclude: ^rigging_pr_decorator\.py$
- repo: local
hooks:
@@ -35,4 +37,3 @@ repos:
entry: python .scripts/check_pinned_hash_dependencies.py
language: python
files: \.github/.*\.yml$
- exclude: ^\.github/workflows/.*\.yml$
From 0009344f576df196cd3f9e15856e53391c6cc376 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:30:42 -0500
Subject: [PATCH 05/11] chore: tmp remove bandit for now
---
.pre-commit-config.yaml | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3304d43..9a3c80f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -18,16 +18,7 @@ repos:
- id: actionlint
name: Check Github Actions
args: ["--ignore", "SC2102"]
- exclude: ^rigging_pr_decorator\.py$
-
- # Python code security
- - repo: https://github.com/PyCQA/bandit
- rev: 8fd258abbac759d62863779f946d6a88e8eabb0f #1.8.0
- hooks:
- - id: bandit
- name: Code security checks
- args: ["-r", "--level", "2", "./"]
- exclude: ^rigging_pr_decorator\.py$
+ exclude: ^rigging_pr_description\.yml$
- repo: local
hooks:
From 3241f94a1c221188adff77f5cbe26df953bf9dfe Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:31:53 -0500
Subject: [PATCH 06/11] chore: test with x flag
---
.pre-commit-config.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9a3c80f..f7edfa9 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -20,6 +20,14 @@ repos:
args: ["--ignore", "SC2102"]
exclude: ^rigging_pr_description\.yml$
+ # Python code security
+ - repo: https://github.com/PyCQA/bandit
+ rev: 8fd258abbac759d62863779f946d6a88e8eabb0f #1.8.0
+ hooks:
+ - id: bandit
+ name: Code security checks
+ args: ["-r", "--level", "2", "./", --exclude, "rigging_pr_decorator.py"]
+
- repo: local
hooks:
# Ensure our GH actions are pinned to a specific hash
From e1d9301e5fdc8e28d8f546f39300af4d33d38620 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:36:56 -0500
Subject: [PATCH 07/11] fix: missing dir
---
.pre-commit-config.yaml | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f7edfa9..c92156b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,7 +26,15 @@ repos:
hooks:
- id: bandit
name: Code security checks
- args: ["-r", "--level", "2", "./", --exclude, "rigging_pr_decorator.py"]
+ args:
+ [
+ "-r",
+ "--level",
+ "2",
+ "./",
+ --exclude,
+ ".github/scripts/rigging_pr_decorator.py",
+ ]
- repo: local
hooks:
From 23237f157e548814a3712fccb93ddade09bd66d2 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:39:37 -0500
Subject: [PATCH 08/11] fix: missing dir path
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index c92156b..0b0fdc4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,7 +17,7 @@ repos:
hooks:
- id: actionlint
name: Check Github Actions
- args: ["--ignore", "SC2102"]
+ args: ["--ignore", "SC2102", "SC2129", "SC2086"]
exclude: ^rigging_pr_description\.yml$
# Python code security
From cc2806bd77fcc8d8bc3459409c29665df73ee3af Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:43:05 -0500
Subject: [PATCH 09/11] fix: ignore regex
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0b0fdc4..f4f837e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,7 +17,7 @@ repos:
hooks:
- id: actionlint
name: Check Github Actions
- args: ["--ignore", "SC2102", "SC2129", "SC2086"]
+ args: ["--ignore", "SC2102,SC2129,SC2086"]
exclude: ^rigging_pr_description\.yml$
# Python code security
From 43cb7f25510aa096669a55e42b7608c966ec1ac0 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:44:42 -0500
Subject: [PATCH 10/11] fix: parsing syntax
---
.pre-commit-config.yaml | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f4f837e..85ba9e5 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,15 +26,7 @@ repos:
hooks:
- id: bandit
name: Code security checks
- args:
- [
- "-r",
- "--level",
- "2",
- "./",
- --exclude,
- ".github/scripts/rigging_pr_decorator.py",
- ]
+ args: ["-r", "./", --exclude, ".github/scripts/rigging_pr_decorator.py"]
- repo: local
hooks:
From 2aa2d91bc8033235bb2ba7658c4201c2a734cb13 Mon Sep 17 00:00:00 2001
From: Ads Dawson <104169244+GangGreenTemperTatum@users.noreply.github.com>
Date: Fri, 24 Jan 2025 21:54:39 -0500
Subject: [PATCH 11/11] chore: args no quotes
---
.pre-commit-config.yaml | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 85ba9e5..0b362ce 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,7 +26,15 @@ repos:
hooks:
- id: bandit
name: Code security checks
- args: ["-r", "./", --exclude, ".github/scripts/rigging_pr_decorator.py"]
+ args:
+ [
+ -r,
+ .,
+ --severity-level,
+ high,
+ -x,
+ .github/scripts/rigging_pr_decorator.py,
+ ]
- repo: local
hooks: