Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/close-stale-ci-prs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Close Stale CI PRs

on:
schedule:
# Run every hour
- cron: "0 * * * *"
workflow_dispatch:

jobs:
close-stale-prs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Close stale PRs
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get all open PRs with patchwork-ci- branches
prs=$(gh pr list --state open --json number,headRefName,createdAt --jq '.[] | select(.headRefName | startswith("patchwork-ci-")) | "\(.number) \(.createdAt)"')

while IFS= read -r line; do
if [ -z "$line" ]; then
continue
fi

pr_number=$(echo "$line" | awk '{print $1}')
created_at=$(echo "$line" | awk '{print $2}')

# Convert to Unix timestamp
created_ts=$(date -d "$created_at" +%s)
current_ts=$(date +%s)
age_hours=$(( (current_ts - created_ts) / 3600 ))

if [ $age_hours -gt 1 ]; then
echo "Closing PR #$pr_number (age: $age_hours hours)"
gh pr comment $pr_number --body "This PR has been automatically closed because it's been open for more than 1 hour. This is a CI-generated PR and should be reviewed and merged promptly if valid."
gh pr close $pr_number
fi
done <<< "$prs"

- name: Delete stale branches
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get all branches with patchwork-ci- prefix
branches=$(gh api repos/${{ github.repository }}/branches --jq '.[] | select(.name | startswith("patchwork-ci-")) | "\(.name) \(.commit.commit.committer.date)"')

while IFS= read -r line; do
if [ -z "$line" ]; then
continue
fi

branch_name=$(echo "$line" | awk '{print $1}')
created_at=$(echo "$line" | awk '{print $2}')

# Convert to Unix timestamp
created_ts=$(date -d "$created_at" +%s)
current_ts=$(date +%s)
age_days=$(( (current_ts - created_ts) / 86400 ))

if [ $age_days -gt 7 ]; then
echo "Deleting branch $branch_name (age: $age_days days)"
gh api -X DELETE repos/${{ github.repository }}/git/refs/heads/$branch_name
fi
done <<< "$branches"
34 changes: 25 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
push:
branches-ignore:
- main
- patchwork-ci-*
- autofix-*
- dependencyupgrade-*
- generatereadme-*
- generatedocstring-*
- generatediagram-*
- generateunittests-*
- generatecodeusageexample-*
- resolveissue-*
Expand Down Expand Up @@ -104,8 +106,10 @@ jobs:
patchwork AutoFix --log debug \
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--branch_prefix=patchwork-ci-autofix- \
--force_pr_creation \
--disable_telemetry
--disable_telemetry \
--plain

- name: Dependency Upgrade
run: |
Expand All @@ -114,9 +118,11 @@ jobs:
--libraries_api_key=${{ secrets.LIBRARIES_KEY }} \
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--branch_prefix=patchwork-ci-dependencyupgrade- \
--language=python \
--force_pr_creation \
--disable_telemetry
--disable_telemetry \
--plain

main-test:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -160,7 +166,8 @@ jobs:
--anthropic_api_key=${{ secrets.ANTHROPIC_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--pr_url=https://github.com/patched-codes/patchwork/pull/${{ steps.findPr.outputs.number }} \
--disable_telemetry
--disable_telemetry \
--plain

- name: Generate Docstring
run: |
Expand All @@ -169,7 +176,9 @@ jobs:
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--base_path=tests/cicd/generate_docstring \
--disable_telemetry
--branch_prefix=patchwork-ci-generatedocstring- \
--disable_telemetry \
--plain

- name: Generate Diagram
run: |
Expand All @@ -178,7 +187,9 @@ jobs:
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--folder_path=patchwork/steps \
--disable_telemetry
--branch_prefix=patchwork-ci-generatediagram- \
--disable_telemetry \
--plain

- name: Generate UnitTests
run: |
Expand All @@ -187,7 +198,9 @@ jobs:
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--folder_path=tests/cicd/generate_docstring \
--disable_telemetry
--branch_prefix=patchwork-ci-generateunittests- \
--disable_telemetry \
--plain

- name: Generate Code Usage Example
run: |
Expand All @@ -196,7 +209,9 @@ jobs:
--patched_api_key=${{ secrets.PATCHED_API_KEY }} \
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--folder_path=tests/cicd/generate_docstring \
--disable_telemetry
--branch_prefix=patchwork-ci-generatecodeusageexample- \
--disable_telemetry \
--plain

- name: Generate README
run: |
Expand All @@ -218,8 +233,9 @@ jobs:
--github_api_key=${{ secrets.SCM_GITHUB_KEY }} \
--filter=*.py \
--folder_path=$dir \
--branch_prefix=generatereadme-$branch_name \
--disable_telemetry
--branch_prefix=patchwork-ci-generatereadme \
--disable_telemetry \
--plain
else
echo "Found README.md in $dir"
fi
Expand Down
7 changes: 5 additions & 2 deletions patchwork/patchflows/AutoFix/AutoFix.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ def __init__(self, inputs: dict):
"compatibility": ["C. Compatibility Risk:", "D. Fixed Code:"],
"patch": ["D. Fixed Code:", "```", "\n", "```"],
}
final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

validate_steps_with_inputs(
set(final_inputs.keys()).union({"prompt_values"}), ScanSemgrep, ExtractCode, LLM, ModifyCode, PR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ def __init__(self, inputs):
if "prompt_template_file" not in final_inputs:
final_inputs["prompt_template_file"] = _DEFAULT_PROMPT_JSON

final_inputs["pr_title"] = f"PatchWork Usage Example generated"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = "PatchWork Usage Example generated"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

validate_steps_with_inputs(
set(final_inputs.keys()).union({"prompt_values", "files_to_patch"}), LLM, CallCode2Prompt, ModifyCode, PR
Expand All @@ -50,7 +53,7 @@ def run(self):
outputs = ModifyCode(self.inputs).run()
self.inputs.update(outputs)
number = len(self.inputs["modified_code_files"])
self.inputs["pr_header"] = f"This pull request adds usage example."
self.inputs["pr_header"] = "This pull request adds usage example."
outputs = PR(self.inputs).run()
self.inputs.update(outputs)

Expand Down
9 changes: 6 additions & 3 deletions patchwork/patchflows/GenerateDiagram/GenerateDiagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ def __init__(self, inputs):
if "prompt_template_file" not in final_inputs:
final_inputs["prompt_template_file"] = _DEFAULT_PROMPT_JSON

final_inputs["pr_title"] = f"PatchWork System Architecture Diagram"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = "PatchWork System Architecture Diagram"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

validate_steps_with_inputs(
set(final_inputs.keys()).union({"prompt_values", "files_to_patch"}), LLM, CallCode2Prompt, ModifyCode, PR
Expand All @@ -44,7 +47,7 @@ def run(self):
self.inputs.update(outputs)
outputs = ModifyCode(self.inputs).run()
self.inputs.update(outputs)
self.inputs["pr_header"] = f"This pull request from patchwork generates system architecture diagram."
self.inputs["pr_header"] = "This pull request from patchwork generates system architecture diagram."
outputs = PR(self.inputs).run()
self.inputs.update(outputs)

Expand Down
14 changes: 9 additions & 5 deletions patchwork/patchflows/GenerateDocstring/GenerateDocstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ def __init__(self, inputs: dict):
if "prompt_template_file" not in final_inputs.keys():
final_inputs["prompt_template_file"] = _DEFAULT_PROMPT_JSON

final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

final_inputs["context_grouping"] = "FUNCTION"
final_inputs["allow_overlap_contexts"] = False
final_inputs["force_code_contexts"] = final_inputs.get("rewrite_existing", False)
Expand All @@ -75,9 +79,9 @@ def run(self) -> dict:
self.inputs.update(outputs)

# Commit changes and create PR
self.inputs[
"pr_header"
] = f'This pull request from patchwork fixes {len(self.inputs["prompt_values"])} docstrings.'
self.inputs["pr_header"] = (
f"This pull request from patchwork fixes {len(self.inputs['prompt_values'])} docstrings."
)
outputs = PR(self.inputs).run()
self.inputs.update(outputs)

Expand Down
3 changes: 2 additions & 1 deletion patchwork/patchflows/GenerateREADME/GenerateREADME.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def __init__(self, inputs: dict):
else:
final_inputs["folder_path"] = Path(final_inputs["folder_path"])

final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"

validate_steps_with_inputs(
set(final_inputs.keys()).union({"prompt_values", "files_to_patch"}), CallCode2Prompt, LLM, ModifyCode, PR
Expand Down
9 changes: 6 additions & 3 deletions patchwork/patchflows/GenerateUnitTests/GenerateUnitTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ def __init__(self, inputs):
if "prompt_template_file" not in final_inputs:
final_inputs["prompt_template_file"] = _DEFAULT_PROMPT_JSON

final_inputs["pr_title"] = f"PatchWork Unit Tests generated"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = "PatchWork Unit Tests generated"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

validate_steps_with_inputs(
set(final_inputs.keys()).union({"prompt_values", "files_to_patch"}), LLM, CallCode2Prompt, ModifyCode, PR
Expand All @@ -50,7 +53,7 @@ def run(self):
outputs = ModifyCode(self.inputs).run()
self.inputs.update(outputs)
number = len(self.inputs["modified_code_files"])
self.inputs["pr_header"] = f"This pull request from patchwork adds tests."
self.inputs["pr_header"] = "This pull request from patchwork adds tests."
outputs = PR(self.inputs).run()
self.inputs.update(outputs)

Expand Down
13 changes: 8 additions & 5 deletions patchwork/patchflows/ResolveIssue/ResolveIssue.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ def __init__(self, inputs: dict):
final_inputs = yaml.safe_load(_DEFAULT_INPUT_FILE.read_text()) or dict()
final_inputs.update(inputs)

final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"
if "pr_title" not in final_inputs.keys():
final_inputs["pr_title"] = f"PatchWork {self.__class__.__name__}"

if "branch_prefix" not in final_inputs.keys():
final_inputs["branch_prefix"] = f"{self.__class__.__name__.lower()}-"

validate_steps_with_inputs(
{"issue_description"}.union(final_inputs.keys()),
Expand All @@ -46,8 +49,8 @@ def run(self) -> dict:
issue=outputs["issue_description"],
),
system_prompt="""\
You are a senior software engineer tasked to analyze a issue.
Your analysis will be used to guide the junior engineer to resolve this issue.
You are a senior software engineer tasked to analyze a issue.
Your analysis will be used to guide the junior engineer to resolve this issue.
""",
user_prompt="""\
<uploaded_files>
Expand Down Expand Up @@ -130,7 +133,7 @@ def run(self) -> dict:
1. Edit the sourcecode of the repo to resolve the issue
2. Think about edge cases and make sure your fix handles them as well

I've already taken care of all changes to any of the test files described in the PR.
I've already taken care of all changes to any of the test files described in the PR.
This means you DON'T have to modify the testing logic or any of the tests in any way!
""",
max_llm_calls=200,
Expand Down
Loading