-
Notifications
You must be signed in to change notification settings - Fork 3
Implement GitHub API integration with real authentication and testing #16
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
f5372e5
f06c99d
92c0ccb
d8e1e18
5e462bb
1ba63c9
93a04a1
d5fa6c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
<<<<<<< HEAD | ||
.env | ||
======= | ||
# Python | ||
*.pyc | ||
__pycache__/ | ||
.coverage | ||
|
||
# Environment variables | ||
.env | ||
>>>>>>> feature/ai-engine-core | ||
.env.* | ||
!.env.example | ||
*.env.example | ||
# Coverage | ||
.coverage | ||
htmlcov/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import pkg_resources | ||
import sys | ||
|
||
try: | ||
version = pkg_resources.get_distribution("PyGithub").version | ||
print(f"PyGithub version: {version}") | ||
except pkg_resources.DistributionNotFound: | ||
print("PyGithub is not installed") | ||
|
||
print(f"Python version: {sys.version}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import os | ||
import sys | ||
import json | ||
from unittest.mock import MagicMock, patch | ||
|
||
# Add the project root directory to the Python path | ||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) | ||
|
||
# Import the GitHub integration class and exceptions | ||
from src.backend.github_integration import GitHubIntegration | ||
from src.backend.exceptions import GitHubAuthError, WebhookError | ||
|
||
print("Starting GitHub integration implementation check...") | ||
|
||
# Test the GitHub integration with mocks | ||
with patch('src.backend.github_integration.Github') as mock_github_class, \ | ||
patch('src.backend.github_integration.Auth.AppAuth') as mock_auth, \ | ||
patch('src.backend.github_integration.requests.post') as mock_requests_post: | ||
|
||
# Create mock objects | ||
mock_github = MagicMock() | ||
mock_repo = MagicMock() | ||
mock_pr = MagicMock() | ||
mock_issue = MagicMock() | ||
mock_commit = MagicMock() | ||
mock_comment = MagicMock() | ||
mock_status = MagicMock() | ||
mock_collaborator = MagicMock() | ||
|
||
# Configure the mocks | ||
mock_github_class.return_value = mock_github | ||
mock_github.get_repo.return_value = mock_repo | ||
mock_repo.get_pull.return_value = mock_pr | ||
mock_repo.get_issue.return_value = mock_issue | ||
mock_pr.create_issue_comment.return_value = mock_comment | ||
mock_issue.create_comment.return_value = mock_comment | ||
mock_repo.get_commit.return_value = mock_commit | ||
mock_commit.create_status.return_value = mock_status | ||
|
||
# Mock the requests.post method | ||
mock_response = MagicMock() | ||
mock_response.status_code = 201 | ||
mock_response.json.return_value = {"id": 12345, "body": "Test comment"} | ||
mock_response.text = json.dumps({"id": 12345, "body": "Test comment"}) | ||
mock_requests_post.return_value = mock_response | ||
|
||
# Mock the token attribute | ||
mock_github._Github__requester = MagicMock() | ||
mock_github._Github__requester._Requester__auth = MagicMock() | ||
mock_github._Github__requester._Requester__auth.token = "mock-token" | ||
|
||
# Set up PR and issue properties | ||
mock_pr.head = MagicMock() | ||
mock_pr.head.ref = "feature-branch" | ||
mock_pr.head.sha = "abc123" | ||
mock_pr.merged = True | ||
mock_pr.user = MagicMock() | ||
mock_pr.user.login = "test-user" | ||
|
||
mock_issue.user = MagicMock() | ||
mock_issue.user.login = "test-user" | ||
mock_issue.state = "closed" | ||
|
||
# Set up collaborators | ||
mock_collaborator.login = "reviewer-user" | ||
mock_repo.get_collaborators.return_value = [mock_collaborator] | ||
|
||
# Create an instance of GitHubIntegration | ||
print("Creating GitHubIntegration instance...") | ||
github = GitHubIntegration(app_id="test_id", private_key="test_key") | ||
|
||
# Test repository cloning | ||
print("\nTesting repository cloning...") | ||
with patch('os.path.exists', return_value=False), patch('os.system') as mock_system: | ||
local_path = github.clone_repository("owner/repo", "main") | ||
print(f"Repository cloning: {'✅ Passed' if mock_system.called else '❌ Failed'}") | ||
print(f" - Local path: {local_path}") | ||
|
||
# Test creating a comment | ||
print("\nTesting comment creation...") | ||
try: | ||
github.create_comment("owner/repo", 123, "Test comment") | ||
print(f"Comment creation: ✅ Passed") | ||
print(f" - get_issue called: {mock_repo.get_issue.called}") | ||
print(f" - create_comment called: {mock_issue.create_comment.called if hasattr(mock_issue, 'create_comment') else False}") | ||
except Exception as e: | ||
print(f"Comment creation: ❌ Failed - {str(e)}") | ||
|
||
# Test updating status | ||
print("\nTesting status update...") | ||
try: | ||
github.update_status("owner/repo", "abc123", "success", "Tests passed") | ||
print(f"Status update: ✅ Passed") | ||
print(f" - get_commit called: {mock_repo.get_commit.called}") | ||
print(f" - create_status called: {mock_commit.create_status.called if hasattr(mock_commit, 'create_status') else False}") | ||
except Exception as e: | ||
print(f"Status update: ❌ Failed - {str(e)}") | ||
|
||
# Test tracking a pull request | ||
print("\nTesting PR tracking...") | ||
try: | ||
github.track_pull_request("owner/repo", 123) | ||
print(f"PR tracking: ✅ Passed") | ||
print(f" - get_pull called: {mock_repo.get_pull.called}") | ||
except Exception as e: | ||
print(f"PR tracking: ❌ Failed - {str(e)}") | ||
|
||
# Test tracking a merge | ||
print("\nTesting merge tracking...") | ||
try: | ||
github.track_merge("owner/repo", 123) | ||
print(f"Merge tracking: ✅ Passed") | ||
print(f" - get_pull call count: {mock_repo.get_pull.call_count}") | ||
except Exception as e: | ||
print(f"Merge tracking: ❌ Failed - {str(e)}") | ||
|
||
# Test assigning a reviewer | ||
print("\nTesting reviewer assignment...") | ||
try: | ||
github.assign_reviewer("owner/repo", 123) | ||
print(f"Reviewer assignment: ✅ Passed") | ||
print(f" - get_issue call count: {mock_repo.get_issue.call_count}") | ||
print(f" - get_collaborators called: {mock_repo.get_collaborators.called}") | ||
except Exception as e: | ||
print(f"Reviewer assignment: ❌ Failed - {str(e)}") | ||
|
||
# Test tracking issue resolution | ||
print("\nTesting issue resolution tracking...") | ||
try: | ||
github.track_issue_resolution("owner/repo", 123) | ||
print(f"Issue resolution tracking: ✅ Passed") | ||
print(f" - get_issue call count: {mock_repo.get_issue.call_count}") | ||
except Exception as e: | ||
print(f"Issue resolution tracking: ❌ Failed - {str(e)}") | ||
|
||
print("\nImplementation verification complete!") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
# Logging Configuration | ||
LOG_LEVEL=INFOLOG_DIR=logs | ||
LOG_MAX_BYTES=10485760LOG_BACKUP_COUNT=5 | ||
|
||
|
||
# GitHub App Configuration | ||
GITHUB_APP_ID=your_app_id_here | ||
GITHUB_PRIVATE_KEY=your_private_key_here | ||
WEBHOOK_SECRET=your_webhook_secret_here | ||
|
||
|
||
|
||
# Logging Configuration | ||
LOG_LEVEL=INFO | ||
LOG_DIR=logs | ||
LOG_MAX_BYTES=10485760 | ||
LOG_BACKUP_COUNT=5 |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,44 @@ | ||||||||||||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||||||||||
import sys | ||||||||||||||||||||||||||||||||||||||||||
from dotenv import load_dotenv | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
# Load environment variables | ||||||||||||||||||||||||||||||||||||||||||
env_path = os.path.join('config', '.env') | ||||||||||||||||||||||||||||||||||||||||||
load_dotenv(env_path) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
# Get GitHub App credentials | ||||||||||||||||||||||||||||||||||||||||||
app_id = os.getenv("GITHUB_APP_ID") | ||||||||||||||||||||||||||||||||||||||||||
private_key = os.getenv("GITHUB_PRIVATE_KEY") | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
print(f"App ID: {app_id}") | ||||||||||||||||||||||||||||||||||||||||||
print(f"Original private key length: {len(private_key) if private_key else 0}") | ||||||||||||||||||||||||||||||||||||||||||
print(f"Original private key: {private_key}") | ||||||||||||||||||||||||||||||||||||||||||
saksham-jain177 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
# Fix the private key format | ||||||||||||||||||||||||||||||||||||||||||
if private_key: | ||||||||||||||||||||||||||||||||||||||||||
# Check if the key is already in the correct format | ||||||||||||||||||||||||||||||||||||||||||
if "-----BEGIN RSA PRIVATE KEY-----" not in private_key: | ||||||||||||||||||||||||||||||||||||||||||
# Format the key properly | ||||||||||||||||||||||||||||||||||||||||||
formatted_key = "-----BEGIN RSA PRIVATE KEY-----\n" | ||||||||||||||||||||||||||||||||||||||||||
formatted_key += private_key | ||||||||||||||||||||||||||||||||||||||||||
formatted_key += "\n-----END RSA PRIVATE KEY-----" | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
# Update the .env file | ||||||||||||||||||||||||||||||||||||||||||
with open(env_path, 'r') as file: | ||||||||||||||||||||||||||||||||||||||||||
env_content = file.read() | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
# Replace the private key | ||||||||||||||||||||||||||||||||||||||||||
new_env_content = env_content.replace( | ||||||||||||||||||||||||||||||||||||||||||
f"GITHUB_PRIVATE_KEY={private_key}", | ||||||||||||||||||||||||||||||||||||||||||
f"GITHUB_PRIVATE_KEY={formatted_key}" | ||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
with open(env_path, 'w') as file: | ||||||||||||||||||||||||||||||||||||||||||
file.write(new_env_content) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
saksham-jain177 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||
print(f"\nPrivate key has been formatted and saved to {env_path}") | ||||||||||||||||||||||||||||||||||||||||||
print(f"New private key length: {len(formatted_key)}") | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+45
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate print statements. These print statements duplicate lines 40-41 and will execute even if the file update operation failed. Remove these duplicate print statements as they're already included within the try block: except IOError as e:
print(f"\nError updating .env file: {str(e)}")
sys.exit(1)
- print(f"\nPrivate key has been formatted and saved to {env_path}")
- print(f"New private key length: {len(formatted_key)}") 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||
print("\nPrivate key is already in the correct format") | ||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||
print("\nNo private key found in .env file") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import os | ||
import subprocess | ||
import webbrowser | ||
|
||
def generate_coverage_report(): | ||
"""Generate HTML coverage report for backend code.""" | ||
print("Generating coverage report...") | ||
|
||
# Run pytest with coverage | ||
cmd = [ | ||
"python", "-m", "pytest", | ||
"tests/", | ||
"--cov=src", | ||
"--cov-report=html" | ||
] | ||
|
||
result = subprocess.run(cmd, capture_output=True, text=True) | ||
|
||
# Print the output | ||
print(result.stdout) | ||
|
||
if result.stderr: | ||
print("Errors:") | ||
print(result.stderr) | ||
|
||
# Check if the report was generated | ||
report_path = os.path.join(os.getcwd(), "htmlcov", "index.html") | ||
if os.path.exists(report_path): | ||
print(f"Coverage report generated at: {report_path}") | ||
|
||
# Open the report in the default browser | ||
try: | ||
print("Opening report in browser...") | ||
webbrowser.open(f"file:///{os.path.abspath(report_path)}") | ||
print("Report opened in browser.") | ||
except Exception as e: | ||
print(f"Failed to open report in browser: {str(e)}") | ||
print(f"Please open the report manually at: {report_path}") | ||
else: | ||
print("Coverage report was not generated.") | ||
|
||
return result.returncode | ||
|
||
if __name__ == "__main__": | ||
generate_coverage_report() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove unused imports from the exception module.
The GitHubAuthError and WebhookError imports are not used in this script.
📝 Committable suggestion
🧰 Tools
🪛 Ruff (0.8.2)
11-11:
src.backend.exceptions.GitHubAuthError
imported but unusedRemove unused import
(F401)
11-11:
src.backend.exceptions.WebhookError
imported but unusedRemove unused import
(F401)