Integrate GitHub functionality: add GitHub integration class and implement branch/PR management; update dependencies and add initial README documentation.

This commit is contained in:
2026-01-09 13:09:43 +00:00
parent 163c918d56
commit ad4d4234eb
4 changed files with 157 additions and 3 deletions

View File

@@ -0,0 +1,24 @@
# AutoMetabuilder
AutoMetabuilder is an AI-powered tool designed to integrate with the metabuilder SDLC workflow.
## Features
- **GitHub Integration**: Automatically fetches context from GitHub Issues and Pull Requests.
- **SDLC Automation**: Can create branches and pull requests based on the AI's decisions.
- **Customizable Prompts**: Loads workflow instructions from a remote YAML prompt.
## Configuration
The following environment variables are required:
- `GITHUB_TOKEN`: A GitHub Personal Access Token with repository permissions.
- `GITHUB_REPOSITORY`: The full name of the repository (e.g., `owner/repo`).
## Usage
Run the tool using poetry:
```bash
poetry run autometabuilder
```

View File

@@ -12,6 +12,7 @@ requests = "^2.31.0"
pyyaml = "^6.0.1"
python-dotenv = "^1.0.0"
openai = "^1.0.0"
PyGithub = "^2.1.1"
[build-system]
requires = ["poetry-core"]

View File

@@ -0,0 +1,34 @@
import os
from github import Github
from github.Repository import Repository
from github.Issue import Issue
from github.PullRequest import PullRequest
class GitHubIntegration:
def __init__(self, token: str, repo_name: str):
self.github = Github(token)
self.repo = self.github.get_repo(repo_name)
def get_open_issues(self):
return self.repo.get_issues(state='open')
def get_issue(self, issue_number: int) -> Issue:
return self.repo.get_issue(number=issue_number)
def create_branch(self, branch_name: str, base_branch: str = "main"):
base_ref = self.repo.get_git_ref(f"heads/{base_branch}")
self.repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base_ref.object.sha)
def create_pull_request(self, title: str, body: str, head_branch: str, base_branch: str = "main") -> PullRequest:
return self.repo.create_pull(title=title, body=body, head=head_branch, base=base_branch)
def get_pull_requests(self, state: str = 'open'):
return self.repo.get_pulls(state=state)
def get_repo_name_from_env() -> str:
# Try to get from environment variable, or fallback to some detection if possible
repo_name = os.environ.get("GITHUB_REPOSITORY")
if not repo_name:
# Fallback or error
raise ValueError("GITHUB_REPOSITORY environment variable not set")
return repo_name

View File

@@ -1,8 +1,16 @@
import os
import requests
import yaml
import json
from dotenv import load_dotenv
from openai import OpenAI
try:
from autometabuilder.github_integration import GitHubIntegration, get_repo_name_from_env
except ImportError:
# Fallback for running as a script without proper package installation
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from autometabuilder.github_integration import GitHubIntegration, get_repo_name_from_env
load_dotenv()
@@ -20,6 +28,15 @@ def main():
print("Error: GITHUB_TOKEN environment variable not set.")
return
# Initialize GitHub Integration
try:
repo_name = get_repo_name_from_env()
gh = GitHubIntegration(token, repo_name)
print(f"Integrated with repository: {repo_name}")
except Exception as e:
print(f"Warning: GitHub integration failed: {e}")
gh = None
endpoint = "https://models.github.ai/inference"
client = OpenAI(
@@ -32,17 +49,95 @@ def main():
messages = prompt["messages"]
model = prompt.get("model", "openai/gpt-4.1")
# Add runtime request (optional)
messages = messages + [{"role": "user", "content": "What should I do next?"}]
# Define tools for SDLC operations
tools = [
{
"type": "function",
"function": {
"name": "create_branch",
"description": "Create a new git branch in the repository",
"parameters": {
"type": "object",
"properties": {
"branch_name": {"type": "string", "description": "The name of the new branch"},
"base_branch": {"type": "string", "description": "The name of the base branch", "default": "main"},
},
"required": ["branch_name"],
},
},
},
{
"type": "function",
"function": {
"name": "create_pull_request",
"description": "Create a new pull request",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string", "description": "The title of the PR"},
"body": {"type": "string", "description": "The body content of the PR"},
"head_branch": {"type": "string", "description": "The branch where changes are implemented"},
"base_branch": {"type": "string", "description": "The branch to merge into", "default": "main"},
},
"required": ["title", "body", "head_branch"],
},
},
}
]
# Add SDLC Context if available
sdlc_context = ""
if gh:
try:
issues = gh.get_open_issues()
issue_list = "\n".join([f"- #{i.number}: {i.title}" for i in issues[:5]])
if issue_list:
sdlc_context += f"\nOpen Issues:\n{issue_list}"
prs = gh.get_pull_requests()
pr_list = "\n".join([f"- #{p.number}: {p.title}" for p in prs[:5]])
if pr_list:
sdlc_context += f"\nOpen Pull Requests:\n{pr_list}"
except Exception as e:
print(f"Error fetching SDLC context: {e}")
if sdlc_context:
messages.append({"role": "system", "content": f"SDLC Context:{sdlc_context}"})
# Add runtime request
messages.append({"role": "user", "content": "What should I do next?"})
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tools,
tool_choice="auto",
temperature=1.0,
top_p=1.0,
)
print(response.choices[0].message.content)
response_message = response.choices[0].message
print(response_message.content if response_message.content else "Tool call requested...")
# Handle tool calls
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
if function_name == "create_branch":
if gh:
print(f"Executing: create_branch({args})")
gh.create_branch(**args)
else:
print("Error: GitHub integration not available for tool call.")
elif function_name == "create_pull_request":
if gh:
print(f"Executing: create_pull_request({args})")
gh.create_pull_request(**args)
else:
print("Error: GitHub integration not available for tool call.")
if __name__ == "__main__":
main()