Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🤖 Feature Request: AI-Assisted Coder for Automated Issue-to-PR Workflow #3312

Open
DonnieBLT opened this issue Feb 1, 2025 · 23 comments
Open

Comments

@DonnieBLT
Copy link
Collaborator

We propose an enhancement to our development workflow by integrating an AI-assisted coder. This system will automatically:
1. Accept an issue link that describes the required changes.
2. Pull the repository into a working environment (using CodeSpaces, Copilot Workspace, Cursor AI, or its own local workspace).
3. Set up the project, install dependencies, and run the existing tests.
4. Generate all required file changes (including new files, modifications, tests, and documentation updates) to implement the issue.
5. Run and verify that all tests pass.
6. Submit a fully functional pull request (PR) with all changes committed, ensuring that the branch follows our contribution guidelines.

The AI-assisted coder will leverage the latest o3-mini-high model to generate code and documentation, ensuring the output is of high quality and meets our coding standards.

Feature Details:
• Triggering the Process:
• The process is initiated by providing the AI-assisted coder with an issue link (e.g., the URL of this issue).
• The AI agent will fetch the full issue description and any referenced details.
• Repository Setup:
• The agent will clone the repository into an isolated workspace.
• It will configure the environment (install dependencies, set environment variables, etc.) and run the test suite to ensure the baseline is correct.
• Implementation:
• The AI agent uses the o3-mini-high model to interpret the issue, generate all necessary code changes, and create or update files as required.
• The implementation must include:
• Modifications to existing files.
• New files if necessary (e.g., tests, configuration updates, documentation).
• Inline comments and documentation to explain the changes.
• The AI must ensure that all code adheres to our project’s coding guidelines and is thoroughly tested.
• Testing & Validation:
• After applying the changes, the AI agent runs the full test suite.
• If tests fail, the agent is expected to iterate on the changes until a green build is achieved.
• Pull Request Submission:
• Once the changes are verified, the AI agent automatically creates a new branch, commits the changes with clear commit messages, and submits a pull request.
• The PR should reference the original issue and include a summary of changes and instructions for manual testing (if needed).

AI Agent Coding Instructions:

You are an AI-assisted coder responsible for automating the workflow from issue to pull request. Your tasks are:

  1. Initialization:

    • Receive an issue URL (passed as a parameter) which contains all details of the required changes.
    • Clone the repository into a secure working environment (e.g., CodeSpaces, Copilot Workspace, Cursor AI, or a local workspace).
  2. Setup:

    • Set up the project environment by installing dependencies and configuring environment variables as per the project documentation.
    • Run the current test suite to verify the baseline environment is correct.
  3. Implementation:

    • Parse the issue details and generate all required file changes using the latest o3-mini-high model.
    • Ensure that code modifications, new tests, and documentation updates follow the project's coding standards.
    • The changes must fully address the issue requirements and include:
      • A detailed code implementation.
      • Inline comments and documentation.
      • Necessary configuration and environment changes.
  4. Validation:

    • Run the full test suite after implementing the changes.
    • If any tests fail, debug and adjust the code until all tests pass.
  5. Submission:

    • Create a new branch named according to the issue (e.g., ai/issue-<id>-feature-name).
    • Commit all changes with descriptive commit messages.
    • Automatically create a pull request referencing the original issue URL.
    • The pull request should include:
      • A summary of changes.
      • AI agent instructions used.
      • Any additional notes or instructions for reviewers.
  6. Error Handling:

    • Ensure that any errors during cloning, environment setup, or testing are logged and reported.
    • The process should abort gracefully if a critical error occurs.

Make sure that the final pull request is clean, all tests pass, and the code is production-ready.

Acceptance Criteria:
1. Automation:
• Given an issue URL, the AI-assisted coder clones the repo, sets up the environment, and runs tests without manual intervention.
• The AI agent generates all necessary file changes that fully implement the issue.
2. Testing:
• All tests pass after the modifications are applied.
• The AI agent handles any errors gracefully and iterates until a successful build is achieved.
3. Pull Request:
• A new branch is created, and a pull request is submitted automatically.
• The PR contains a detailed summary, references the original issue, and includes all required file changes.
4. Quality:
• The generated code adheres to the project’s coding standards, includes proper inline documentation, and is maintainable.
• The solution is verified by a green test suite and meets all acceptance criteria outlined in the issue.

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 1, 2025

/assign

Copy link
Contributor

github-actions bot commented Feb 1, 2025

You cannot be assigned to this issue because you are already assigned to the following issues without an open pull request: #1874. Please submit a pull request for these issues before getting assigned to a new one.

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 1, 2025

/assign

Copy link
Contributor

github-actions bot commented Feb 1, 2025

Hello @tsu-ki! You've been assigned to OWASP-BLT/BLT issue #3312. You have 24 hours to complete a pull request.

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 2, 2025

@DonnieBLT sir, do I need to integrate it in BLT repository or create it as a separate model?

@DonnieBLT
Copy link
Collaborator Author

In BLT

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 2, 2025

In BLT

@DonnieBLT sir, is it okay if I create a new subdirectory as implementing this feature would require different model, setup and initialisation files?

@DonnieBLT
Copy link
Collaborator Author

Can you do separate files instead of directories so it matches our structure?

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 2, 2025

Can you do separate files instead of directories so it matches our structure?

umm, I'm currently trying to figure out an efficient way to implement this without having to subscribe to expensive agentic services such as Devin.
So far, I've come up with this approach:

  1. Create an agent and incorporate it using github actions.
  2. So that when author of the issue, adds the agent's label to issue, the agent is invoked through github actions and it fetches the issue.
  3. A hurdle i'm currently tackling is security issues, because for the agent to create new branches in main repository. It would require access and would have to be a collaborator.

@DonnieBLT sir, can you please review this approach, I've come up with so far? thank you

@DonnieBLT
Copy link
Collaborator Author

I was thinking it will create a fork to work on. I like the idea of a GitHub action as one way in addition to giving it a url to any GitHub issue. We want this to work on all repos so we couldn’t rely on the label method. I would avoid Devin and instead use the models directly like Claude sonet or o3-mini-high

@DonnieBLT
Copy link
Collaborator Author

POC

Automated Workflow from Issue to Pull Request

Below is an example implementation in Python that automates the workflow from receiving an issue URL to creating a production-ready pull request. This script demonstrates:

  1. Initialization:
    • Receives an issue URL and clones the repository.
  2. Setup:
    • Sets up the project environment by installing dependencies and verifying the baseline via tests.
  3. Implementation:
    • Parses the issue details (placeholder AI integration) and generates all required file changes.
  4. Validation:
    • Runs the full test suite to ensure that modifications pass.
  5. Submission:
    • Creates a new branch, commits the changes with descriptive messages, and submits a pull request.
  6. Error Handling:
    • Logs any errors and aborts gracefully if a critical error occurs.

import subprocess
import os
import sys
import logging

# Set up logging for error handling and status messages.
logging.basicConfig(level=logging.INFO)

def clone_repo(repo_url, clone_dir):
    """Clone the repository to a secure working directory."""
    try:
        subprocess.run(["git", "clone", repo_url, clone_dir], check=True)
        logging.info("Repository cloned successfully.")
    except subprocess.CalledProcessError as e:
        logging.error("Failed to clone repository: %s", e)
        sys.exit(1)

def setup_environment(clone_dir):
    """Install dependencies and prepare the environment."""
    os.chdir(clone_dir)
    try:
        # Example for a Python project; adjust for your project's package manager.
        subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True)
        logging.info("Dependencies installed successfully.")
    except subprocess.CalledProcessError as e:
        logging.error("Failed to install dependencies: %s", e)
        sys.exit(1)

def run_tests():
    """Run the project’s test suite to ensure a correct baseline."""
    try:
        # Replace with your test command (e.g., pytest, npm test, etc.)
        subprocess.run(["pytest"], check=True)
        logging.info("Initial test suite passed.")
    except subprocess.CalledProcessError as e:
        logging.error("Initial test suite failed: %s", e)
        sys.exit(1)

def generate_changes_from_issue(issue_url):
    """
    Placeholder for AI model integration (using the latest o3-mini-high model)
    to parse the issue details and generate file changes.
    In a real implementation, this function would call your AI service.
    """
    # For demonstration, we return a dummy file change.
    return {
        "example.py": (
            "# Updated according to issue requirements\n"
            "# This implementation uses inline comments and adheres to coding standards.\n"
            "def greet():\n"
            "    print('Hello, World!')\n\n"
            "if __name__ == '__main__':\n"
            "    greet()\n"
        )
    }

def implement_changes(issue_url):
    """Generate and apply code changes based on the issue."""
    logging.info("Parsing issue details from %s", issue_url)
    file_changes = generate_changes_from_issue(issue_url)
    
    # Apply changes: iterate through files and write modifications.
    for filepath, content in file_changes.items():
        with open(filepath, "w") as f:
            f.write(content)
        logging.info("Updated file: %s", filepath)
    
    # Return a summary of the changes for commit messages and PR description.
    return "Implemented new greeting function in example.py based on issue requirements."

def validate_changes():
    """Run the test suite again to verify that changes did not break existing functionality."""
    try:
        subprocess.run(["pytest"], check=True)
        logging.info("Validation tests passed after changes.")
    except subprocess.CalledProcessError as e:
        logging.error("Validation tests failed: %s", e)
        # Additional debugging and iterative fixes can be added here.
        sys.exit(1)

def create_branch_and_commit(branch_name, commit_message):
    """Create a new branch, add changes, and commit them."""
    try:
        subprocess.run(["git", "checkout", "-b", branch_name], check=True)
        subprocess.run(["git", "add", "."], check=True)
        subprocess.run(["git", "commit", "-m", commit_message], check=True)
        logging.info("Changes committed on branch %s", branch_name)
    except subprocess.CalledProcessError as e:
        logging.error("Error during branch creation or commit: %s", e)
        sys.exit(1)

def create_pull_request(issue_url, branch_name, pr_title, pr_body):
    """
    Create a pull request referencing the original issue.
    This example uses the GitHub CLI (gh); adapt as needed for your repository hosting service.
    """
    try:
        subprocess.run([
            "gh", "pr", "create",
            "--title", pr_title,
            "--body", pr_body,
            "--base", "main"  # Adjust the base branch if needed.
        ], check=True)
        logging.info("Pull request created referencing issue: %s", issue_url)
    except subprocess.CalledProcessError as e:
        logging.error("Failed to create pull request: %s", e)
        sys.exit(1)

def main(issue_url, repo_url):
    working_dir = "working_repo"
    # Step 1: Initialization
    clone_repo(repo_url, working_dir)
    
    # Step 2: Setup
    setup_environment(working_dir)
    run_tests()
    
    # Step 3: Implementation
    changes_summary = implement_changes(issue_url)
    
    # Step 4: Validation
    validate_changes()
    
    # Step 5: Submission
    # Derive branch name from issue details; here we use a dummy issue ID and feature name.
    branch_name = "ai/issue-123-feature-name"
    commit_message = f"Implement changes for issue: {changes_summary}"
    create_branch_and_commit(branch_name, commit_message)
    
    pr_title = "AI: Issue #123 - Feature Implementation"
    pr_body = (
        f"### Summary of changes\n{changes_summary}\n\n"
        "### AI Agent Instructions\n"
        "- Parsed issue details using the latest o3-mini-high model.\n"
        "- Generated necessary file changes, tests, and documentation updates.\n\n"
        f"References issue: {issue_url}"
    )
    create_pull_request(issue_url, branch_name, pr_title, pr_body)
    
    logging.info("Automation workflow completed successfully.")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python automation.py <issue_url> <repo_url>")
        sys.exit(1)
    issue_url = sys.argv[1]
    repo_url = sys.argv[2]
    main(issue_url, repo_url)

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 2, 2025

POC

Automated Workflow from Issue to Pull Request

Below is an example implementation in Python that automates the workflow from receiving an issue URL to creating a production-ready pull request. This script demonstrates:

  1. Initialization:

    • Receives an issue URL and clones the repository.
  2. Setup:

    • Sets up the project environment by installing dependencies and verifying the baseline via tests.
  3. Implementation:

    • Parses the issue details (placeholder AI integration) and generates all required file changes.
  4. Validation:

    • Runs the full test suite to ensure that modifications pass.
  5. Submission:

    • Creates a new branch, commits the changes with descriptive messages, and submits a pull request.
  6. Error Handling:

    • Logs any errors and aborts gracefully if a critical error occurs.

import subprocess
import os
import sys
import logging

Set up logging for error handling and status messages.

logging.basicConfig(level=logging.INFO)

def clone_repo(repo_url, clone_dir):
"""Clone the repository to a secure working directory."""
try:
subprocess.run(["git", "clone", repo_url, clone_dir], check=True)
logging.info("Repository cloned successfully.")
except subprocess.CalledProcessError as e:
logging.error("Failed to clone repository: %s", e)
sys.exit(1)

def setup_environment(clone_dir):
"""Install dependencies and prepare the environment."""
os.chdir(clone_dir)
try:
# Example for a Python project; adjust for your project's package manager.
subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True)
logging.info("Dependencies installed successfully.")
except subprocess.CalledProcessError as e:
logging.error("Failed to install dependencies: %s", e)
sys.exit(1)

def run_tests():
"""Run the project’s test suite to ensure a correct baseline."""
try:
# Replace with your test command (e.g., pytest, npm test, etc.)
subprocess.run(["pytest"], check=True)
logging.info("Initial test suite passed.")
except subprocess.CalledProcessError as e:
logging.error("Initial test suite failed: %s", e)
sys.exit(1)

def generate_changes_from_issue(issue_url):
"""
Placeholder for AI model integration (using the latest o3-mini-high model)
to parse the issue details and generate file changes.
In a real implementation, this function would call your AI service.
"""
# For demonstration, we return a dummy file change.
return {
"example.py": (
"# Updated according to issue requirements\n"
"# This implementation uses inline comments and adheres to coding standards.\n"
"def greet():\n"
" print('Hello, World!')\n\n"
"if name == 'main':\n"
" greet()\n"
)
}

def implement_changes(issue_url):
"""Generate and apply code changes based on the issue."""
logging.info("Parsing issue details from %s", issue_url)
file_changes = generate_changes_from_issue(issue_url)

# Apply changes: iterate through files and write modifications.
for filepath, content in file_changes.items():
    with open(filepath, "w") as f:
        f.write(content)
    logging.info("Updated file: %s", filepath)

# Return a summary of the changes for commit messages and PR description.
return "Implemented new greeting function in example.py based on issue requirements."

def validate_changes():
"""Run the test suite again to verify that changes did not break existing functionality."""
try:
subprocess.run(["pytest"], check=True)
logging.info("Validation tests passed after changes.")
except subprocess.CalledProcessError as e:
logging.error("Validation tests failed: %s", e)
# Additional debugging and iterative fixes can be added here.
sys.exit(1)

def create_branch_and_commit(branch_name, commit_message):
"""Create a new branch, add changes, and commit them."""
try:
subprocess.run(["git", "checkout", "-b", branch_name], check=True)
subprocess.run(["git", "add", "."], check=True)
subprocess.run(["git", "commit", "-m", commit_message], check=True)
logging.info("Changes committed on branch %s", branch_name)
except subprocess.CalledProcessError as e:
logging.error("Error during branch creation or commit: %s", e)
sys.exit(1)

def create_pull_request(issue_url, branch_name, pr_title, pr_body):
"""
Create a pull request referencing the original issue.
This example uses the GitHub CLI (gh); adapt as needed for your repository hosting service.
"""
try:
subprocess.run([
"gh", "pr", "create",
"--title", pr_title,
"--body", pr_body,
"--base", "main" # Adjust the base branch if needed.
], check=True)
logging.info("Pull request created referencing issue: %s", issue_url)
except subprocess.CalledProcessError as e:
logging.error("Failed to create pull request: %s", e)
sys.exit(1)

def main(issue_url, repo_url):
working_dir = "working_repo"
# Step 1: Initialization
clone_repo(repo_url, working_dir)

# Step 2: Setup
setup_environment(working_dir)
run_tests()

# Step 3: Implementation
changes_summary = implement_changes(issue_url)

# Step 4: Validation
validate_changes()

# Step 5: Submission
# Derive branch name from issue details; here we use a dummy issue ID and feature name.
branch_name = "ai/issue-123-feature-name"
commit_message = f"Implement changes for issue: {changes_summary}"
create_branch_and_commit(branch_name, commit_message)

pr_title = "AI: Issue #123 - Feature Implementation"
pr_body = (
    f"### Summary of changes\n{changes_summary}\n\n"
    "### AI Agent Instructions\n"
    "- Parsed issue details using the latest o3-mini-high model.\n"
    "- Generated necessary file changes, tests, and documentation updates.\n\n"
    f"References issue: {issue_url}"
)
create_pull_request(issue_url, branch_name, pr_title, pr_body)

logging.info("Automation workflow completed successfully.")

if name == "main":
if len(sys.argv) != 3:
print("Usage: python automation.py <issue_url> <repo_url>")
sys.exit(1)
issue_url = sys.argv[1]
repo_url = sys.argv[2]
main(issue_url, repo_url)

thank you providing me with a foundation to work on, this helps a lot. I'll further implement this correctly and use the fork creation approach, thanks!

@DonnieBLT
Copy link
Collaborator Author

Here is the function:

import re
import os
import requests
import logging

def generate_changes_from_issue(issue_url):
    """
    Fetches issue details from the provided GitHub issue URL and calls the AI service
    (o3-mini-high model) to generate the necessary file changes to address the issue.

    Steps performed:
      1. Parse the GitHub issue URL to extract repository information.
      2. Retrieve issue details (title and description) via the GitHub API.
      3. Construct a prompt incorporating the issue details for the AI service.
      4. Call the AI service to generate the file changes.
      5. Validate and return the generated file changes as a dictionary mapping filenames to new content.

    The AI service is expected to return a JSON object in the following format:
      {
        "filename1": "updated file content",
        "filename2": "updated file content"
      }

    Environment Variables:
      - AI_API_KEY: API key for authenticating with the AI service.

    Args:
        issue_url (str): The URL of the GitHub issue (e.g., "https://github.com/owner/repo/issues/123").

    Returns:
        dict: A dictionary where keys are file names and values are the corresponding file content changes.

    Raises:
        ValueError: If the issue URL format is invalid or if the AI response format is unexpected.
        EnvironmentError: If the AI_API_KEY is not set.
        requests.HTTPError: If any API request (GitHub or AI service) fails.
        Exception: For any other errors during the process.
    """
    try:
        # Extract repository owner, repo name, and issue number from the GitHub issue URL.
        match = re.search(r"github\.com/([^/]+)/([^/]+)/issues/(\d+)", issue_url)
        if not match:
            raise ValueError(
                "Invalid GitHub issue URL format. Expected format: 'https://github.com/owner/repo/issues/123'"
            )
        owner, repo, issue_number = match.groups()
        logging.info("Parsed issue URL. Owner: %s, Repo: %s, Issue Number: %s", owner, repo, issue_number)
        
        # Retrieve issue details from the GitHub API.
        github_api_url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}"
        github_response = requests.get(github_api_url)
        github_response.raise_for_status()
        issue_data = github_response.json()
        issue_title = issue_data.get("title", "No Title Provided")
        issue_body = issue_data.get("body", "No Description Provided")
        logging.info("Fetched GitHub issue details: %s", issue_title)
        
        # Construct the prompt for the AI service.
        prompt = (
            "You are an AI coding assistant. Based on the following GitHub issue details, "
            "generate the required file changes with detailed inline comments, tests, and configuration "
            "updates as needed. Ensure the code adheres to best practices and is production-ready.\n\n"
            f"Issue Title: {issue_title}\n"
            f"Issue Description: {issue_body}\n\n"
            "Return the changes in the following JSON format:\n"
            "{\n"
            '  "filename1": "file content",\n'
            '  "filename2": "file content"\n'
            "}\n"
        )
        logging.info("Constructed prompt for AI service.")
        
        # Retrieve the API key for the AI service from environment variables.
        ai_api_key = os.environ.get("AI_API_KEY")
        if not ai_api_key:
            raise EnvironmentError("AI_API_KEY not set in environment variables.")
        
        # Define the AI service endpoint (replace with the actual endpoint as needed).
        ai_endpoint = "https://api.o3mini-high.example.com/generate"
        
        # Prepare headers and payload for the AI service request.
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {ai_api_key}"
        }
        payload = {
            "prompt": prompt,
            "max_tokens": 1500,   # Adjust token count as needed.
            "temperature": 0.7    # Adjust the randomness as needed.
        }
        
        # Call the AI service.
        ai_response = requests.post(ai_endpoint, json=payload, headers=headers)
        ai_response.raise_for_status()
        response_data = ai_response.json()
        
        # Validate the response from the AI service.
        if not isinstance(response_data, dict):
            raise ValueError("Unexpected response format from AI service. Expected a JSON object mapping filenames to changes.")
        
        logging.info("Successfully generated file changes from the AI service.")
        return response_data

    except Exception as e:
        logging.error("Error in generate_changes_from_issue: %s", e)
        raise

Copy link
Contributor

github-actions bot commented Feb 4, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 4, 2025

/assign

Copy link
Contributor

github-actions bot commented Feb 4, 2025

Hello @tsu-ki! You've been assigned to OWASP-BLT/BLT issue #3312. You have 24 hours to complete a pull request.

Copy link
Contributor

github-actions bot commented Feb 5, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

1 similar comment
Copy link
Contributor

github-actions bot commented Feb 5, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

@tsu-ki
Copy link
Contributor

tsu-ki commented Feb 5, 2025

/assign

Copy link
Contributor

github-actions bot commented Feb 5, 2025

Hello @tsu-ki! You've been assigned to OWASP-BLT/BLT issue #3312. You have 24 hours to complete a pull request.

@github-actions github-actions bot assigned tsu-ki and unassigned tsu-ki Feb 5, 2025
Copy link
Contributor

github-actions bot commented Feb 6, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

1 similar comment
Copy link
Contributor

github-actions bot commented Feb 6, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

Copy link
Contributor

github-actions bot commented Feb 6, 2025

⏰ This issue has been automatically unassigned due to 24 hours of inactivity.
The issue is now available for anyone to work on again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Backlog
Development

No branches or pull requests

2 participants