478 lines
14 KiB
Python
Executable File
478 lines
14 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Example: Working on 3 Issues Simultaneously with Allegro-Primus
|
|
|
|
This example demonstrates how to use the AP Git Worktree Automation
|
|
to work on multiple GitHub issues in parallel using isolated worktrees.
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add tools to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
try:
|
|
from git_tools import WorktreeManager, ParallelAgent, ParallelTask, IssueParallelizer, TaskRunner, TaskBatch
|
|
except ImportError:
|
|
# Direct imports for development
|
|
from worktree_manager import WorktreeManager
|
|
from parallel_agent import ParallelAgent, ParallelTask, IssueParallelizer
|
|
from task_runner import TaskRunner, TaskBatch
|
|
|
|
|
|
def example_1_basic_parallel():
|
|
"""
|
|
Example 1: Basic parallel execution on 3 issues
|
|
|
|
Scenario:
|
|
- Issue #101: Fix authentication bug
|
|
- Issue #102: Add user profile endpoint
|
|
- Issue #103: Update API documentation
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 1: Basic Parallel Execution on 3 Issues")
|
|
print("="*70)
|
|
|
|
# Initialize parallel agent
|
|
agent = ParallelAgent(max_workers=3)
|
|
|
|
# Define tasks for each issue
|
|
tasks = [
|
|
ParallelTask(
|
|
task_id="auth-fix-tests",
|
|
issue_number="101",
|
|
task_type="command",
|
|
payload=["echo", "Running authentication tests for issue #101..."],
|
|
dependencies=[],
|
|
priority=1,
|
|
auto_commit=False
|
|
),
|
|
ParallelTask(
|
|
task_id="api-endpoint-build",
|
|
issue_number="102",
|
|
task_type="command",
|
|
payload=["echo", "Building user profile endpoint for issue #102..."],
|
|
dependencies=[],
|
|
priority=1,
|
|
auto_commit=False
|
|
),
|
|
ParallelTask(
|
|
task_id="docs-generate",
|
|
issue_number="103",
|
|
task_type="command",
|
|
payload=["echo", "Generating API docs for issue #103..."],
|
|
dependencies=[],
|
|
priority=2, # Lower priority
|
|
auto_commit=False
|
|
)
|
|
]
|
|
|
|
# Run all tasks in parallel
|
|
print("\nLaunching parallel tasks...")
|
|
results = agent.run_parallel(tasks)
|
|
|
|
print(f"\n✓ Execution complete!")
|
|
print(f" Total tasks: {results['stats']['total_tasks']}")
|
|
print(f" Successful: {results['stats']['successful']}")
|
|
print(f" Failed: {results['stats']['failed']}")
|
|
print(f" Worktrees used: {results['stats']['worktrees_used']}")
|
|
|
|
return results
|
|
|
|
|
|
def example_2_issue_parallelizer():
|
|
"""
|
|
Example 2: Using IssueParallelizer for cleaner workflow
|
|
|
|
Same 3 issues, but using the higher-level interface
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 2: Using IssueParallelizer")
|
|
print("="*70)
|
|
|
|
# Create parallelizer
|
|
parallelizer = IssueParallelizer()
|
|
|
|
# Register issues
|
|
print("\nRegistering issues...")
|
|
parallelizer.register_issue("101", "Fix authentication bug")
|
|
parallelizer.register_issue("102", "Add user profile endpoint")
|
|
parallelizer.register_issue("103", "Update API documentation")
|
|
|
|
# Add tasks to each issue
|
|
print("Adding tasks...")
|
|
parallelizer.add_task_to_issue(
|
|
"101",
|
|
["bash", "-c", "echo 'Issue 101: Fixing auth...' && sleep 1 && echo 'Fixed!'"],
|
|
task_id="auth-fix",
|
|
timeout=60
|
|
)
|
|
|
|
parallelizer.add_task_to_issue(
|
|
"102",
|
|
["bash", "-c", "echo 'Issue 102: Building API...' && sleep 1 && echo 'Built!'"],
|
|
task_id="api-build",
|
|
timeout=60
|
|
)
|
|
|
|
parallelizer.add_task_to_issue(
|
|
"103",
|
|
["bash", "-c", "echo 'Issue 103: Updating docs...' && sleep 1 && echo 'Updated!'"],
|
|
task_id="docs-update",
|
|
timeout=60
|
|
)
|
|
|
|
# Run in parallel
|
|
print("\nRunning all tasks in parallel...")
|
|
results = parallelizer.run()
|
|
|
|
print(f"\n✓ Complete!")
|
|
for r in results['results']:
|
|
status = "✓" if r['success'] else "✗"
|
|
print(f" {status} {r['task_id']}: {r['stdout'].strip()}")
|
|
|
|
return results
|
|
|
|
|
|
def example_3_task_dependencies():
|
|
"""
|
|
Example 3: Tasks with dependencies
|
|
|
|
Issue #201: Database migration
|
|
- Step 1: Create migration script
|
|
- Step 2: Run migration (depends on step 1)
|
|
- Step 3: Verify migration (depends on step 2)
|
|
|
|
Issue #202: Add feature
|
|
- Step 1: Implement feature (parallel with #201)
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 3: Task Dependencies")
|
|
print("="*70)
|
|
|
|
agent = ParallelAgent(max_workers=3)
|
|
|
|
tasks = [
|
|
# Issue 201 - Sequential tasks with dependencies
|
|
ParallelTask(
|
|
task_id="db-create-migration",
|
|
issue_number="201",
|
|
task_type="command",
|
|
payload=["echo", "Creating migration script..."],
|
|
dependencies=[],
|
|
priority=1
|
|
),
|
|
ParallelTask(
|
|
task_id="db-run-migration",
|
|
issue_number="201",
|
|
task_type="command",
|
|
payload=["echo", "Running database migration..."],
|
|
dependencies=["db-create-migration"], # Wait for creation
|
|
priority=1
|
|
),
|
|
ParallelTask(
|
|
task_id="db-verify",
|
|
issue_number="201",
|
|
task_type="command",
|
|
payload=["echo", "Verifying migration..."],
|
|
dependencies=["db-run-migration"], # Wait for migration
|
|
priority=1
|
|
),
|
|
|
|
# Issue 202 - Parallel independent task
|
|
ParallelTask(
|
|
task_id="feature-implement",
|
|
issue_number="202",
|
|
task_type="command",
|
|
payload=["echo", "Implementing new feature..."],
|
|
dependencies=[],
|
|
priority=1
|
|
)
|
|
]
|
|
|
|
print("\nTask dependency graph:")
|
|
print(" db-create-migration → db-run-migration → db-verify")
|
|
print(" feature-implement (parallel)")
|
|
|
|
print("\nRunning tasks...")
|
|
results = agent.run_parallel(tasks)
|
|
|
|
print(f"\n✓ Execution complete!")
|
|
print(f" Total: {results['stats']['total_tasks']}")
|
|
print(f" Successful: {results['stats']['successful']}")
|
|
|
|
return results
|
|
|
|
|
|
def example_4_script_execution():
|
|
"""
|
|
Example 4: Running Python scripts in parallel worktrees
|
|
|
|
Execute different analysis scripts on 3 issues simultaneously
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 4: Python Script Execution in Parallel")
|
|
print("="*70)
|
|
|
|
agent = ParallelAgent(max_workers=3)
|
|
|
|
# Python script for code analysis
|
|
analysis_script = '''
|
|
import os
|
|
import json
|
|
|
|
print(f"Running in worktree: {os.environ.get('AP_WORKTREE', 'unknown')}")
|
|
print(f"Processing issue: {os.environ.get('AP_ISSUE', 'unknown')}")
|
|
print(f"Task ID: {os.environ.get('AP_TASK_ID', 'unknown')}")
|
|
|
|
# Simulate analysis
|
|
results = {
|
|
"files_analyzed": 42,
|
|
"issues_found": 3,
|
|
"suggestions": ["Refactor module X", "Add tests for Y"]
|
|
}
|
|
|
|
print(json.dumps(results, indent=2))
|
|
'''
|
|
|
|
# Python script for testing
|
|
test_script = '''
|
|
import os
|
|
import time
|
|
|
|
print(f"Running tests for issue {os.environ.get('AP_ISSUE')}")
|
|
|
|
# Simulate test run
|
|
tests = ["test_auth.py", "test_api.py", "test_models.py"]
|
|
for test in tests:
|
|
print(f" ✓ {test} passed")
|
|
time.sleep(0.1)
|
|
|
|
print("\\nAll tests passed!")
|
|
'''
|
|
|
|
# Python script for documentation
|
|
docs_script = '''
|
|
import os
|
|
|
|
print(f"Generating documentation for issue {os.environ.get('AP_ISSUE')}")
|
|
print(" - Processing docstrings...")
|
|
print(" - Building HTML...")
|
|
print(" - Done!")
|
|
'''
|
|
|
|
tasks = [
|
|
ParallelTask(
|
|
task_id="analyze-issue-301",
|
|
issue_number="301",
|
|
task_type="script",
|
|
payload=analysis_script,
|
|
dependencies=[]
|
|
),
|
|
ParallelTask(
|
|
task_id="test-issue-302",
|
|
issue_number="302",
|
|
task_type="script",
|
|
payload=test_script,
|
|
dependencies=[]
|
|
),
|
|
ParallelTask(
|
|
task_id="docs-issue-303",
|
|
issue_number="303",
|
|
task_type="script",
|
|
payload=docs_script,
|
|
dependencies=[]
|
|
)
|
|
]
|
|
|
|
print("\nExecuting Python scripts in parallel worktrees...")
|
|
results = agent.run_parallel(tasks)
|
|
|
|
print(f"\n✓ Complete!")
|
|
for r in results['results']:
|
|
print(f"\n--- {r['task_id']} ---")
|
|
print(r['stdout'])
|
|
|
|
return results
|
|
|
|
|
|
def example_5_worktree_management():
|
|
"""
|
|
Example 5: Worktree management workflow
|
|
|
|
Demonstrate creating, listing, syncing, and cleaning worktrees
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 5: Worktree Management Workflow")
|
|
print("="*70)
|
|
|
|
wm = WorktreeManager()
|
|
|
|
# Step 1: Create worktrees for 3 issues
|
|
print("\n1. Creating worktrees...")
|
|
issues = [
|
|
("401", "Bug fix for login"),
|
|
("402", "Feature: dark mode"),
|
|
("403", "Refactor auth module")
|
|
]
|
|
|
|
paths = {}
|
|
for num, desc in issues:
|
|
try:
|
|
path = wm.create_worktree(num, desc)
|
|
paths[num] = path
|
|
print(f" ✓ Issue #{num}: {path}")
|
|
except Exception as e:
|
|
print(f" ✗ Issue #{num}: {e}")
|
|
|
|
# Step 2: List all worktrees
|
|
print("\n2. Active worktrees:")
|
|
for wt in wm.list_worktrees():
|
|
if not wt.is_main:
|
|
print(f" - {wt.branch} at {wt.path}")
|
|
|
|
# Step 3: Get status of each
|
|
print("\n3. Worktree status:")
|
|
for num, _ in issues:
|
|
status = wm.get_worktree_status(num)
|
|
print(f" Issue #{num}: branch={status.get('branch', 'N/A')}, "
|
|
f"changes={status.get('has_uncommitted_changes', False)}")
|
|
|
|
# Step 4: Clean up
|
|
print("\n4. Cleaning up worktrees...")
|
|
for num, _ in issues:
|
|
if wm.remove_worktree(num):
|
|
print(f" ✓ Removed issue #{num}")
|
|
|
|
return paths
|
|
|
|
|
|
def example_6_conflict_detection():
|
|
"""
|
|
Example 6: Conflict detection between parallel worktrees
|
|
|
|
Shows how the system detects when multiple issues modify the same files
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("EXAMPLE 6: Conflict Detection")
|
|
print("="*70)
|
|
|
|
print("""
|
|
This example shows conflict detection capabilities:
|
|
|
|
Scenario:
|
|
Issue #501 - Modifies src/auth.py and src/login.py
|
|
Issue #502 - Modifies src/auth.py and src/api.py
|
|
Issue #503 - Modifies src/utils.py only
|
|
|
|
The system will detect that Issues #501 and #502 both modify src/auth.py
|
|
and flag this as a potential conflict.
|
|
""")
|
|
|
|
from parallel_agent import ConflictDetector
|
|
|
|
wm = WorktreeManager()
|
|
detector = ConflictDetector(wm)
|
|
|
|
# Simulate file ownership registration
|
|
print("\nRegistering file modifications...")
|
|
detector.register_files("task-501", ["src/auth.py", "src/login.py"])
|
|
print(" Task 501: src/auth.py, src/login.py")
|
|
|
|
conflict = detector.register_files("task-502", ["src/auth.py", "src/api.py"])
|
|
print(" Task 502: src/auth.py, src/api.py")
|
|
if conflict:
|
|
print(f" ⚠ CONFLICT DETECTED: src/auth.py already owned by {conflict}")
|
|
|
|
detector.register_files("task-503", ["src/utils.py"])
|
|
print(" Task 503: src/utils.py (no conflict)")
|
|
|
|
print("\n✓ Conflict detection active")
|
|
|
|
|
|
def save_example_tasks_json():
|
|
"""
|
|
Create an example JSON file with tasks for CLI usage
|
|
"""
|
|
tasks = [
|
|
{
|
|
"task_id": "fix-auth-101",
|
|
"issue_number": "101",
|
|
"task_type": "command",
|
|
"payload": ["echo", "Fixing authentication..."],
|
|
"dependencies": [],
|
|
"priority": 1,
|
|
"auto_commit": False,
|
|
"timeout": 300
|
|
},
|
|
{
|
|
"task_id": "add-api-102",
|
|
"issue_number": "102",
|
|
"task_type": "command",
|
|
"payload": ["echo", "Adding API endpoint..."],
|
|
"dependencies": [],
|
|
"priority": 1,
|
|
"auto_commit": False,
|
|
"timeout": 300
|
|
},
|
|
{
|
|
"task_id": "update-docs-103",
|
|
"issue_number": "103",
|
|
"task_type": "command",
|
|
"payload": ["echo", "Updating documentation..."],
|
|
"dependencies": [],
|
|
"priority": 2,
|
|
"auto_commit": False,
|
|
"timeout": 300
|
|
}
|
|
]
|
|
|
|
output_path = Path(__file__).parent / "example_tasks.json"
|
|
with open(output_path, 'w') as f:
|
|
json.dump(tasks, f, indent=2)
|
|
|
|
print(f"\n✓ Saved example tasks to {output_path}")
|
|
print(f"\nUsage: python cli.py parallel run -f {output_path}")
|
|
|
|
|
|
def main():
|
|
"""Run all examples"""
|
|
print("\n" + "="*70)
|
|
print("ALLEGRO-PRIMUS GIT WORKTREE AUTOMATION")
|
|
print("Example: Working on 3 Issues Simultaneously")
|
|
print("="*70)
|
|
|
|
try:
|
|
# Run examples
|
|
example_1_basic_parallel()
|
|
example_2_issue_parallelizer()
|
|
example_3_task_dependencies()
|
|
example_4_script_execution()
|
|
example_5_worktree_management()
|
|
example_6_conflict_detection()
|
|
|
|
# Save example JSON
|
|
save_example_tasks_json()
|
|
|
|
print("\n" + "="*70)
|
|
print("All examples completed successfully!")
|
|
print("="*70)
|
|
print("""
|
|
CLI Usage:
|
|
python cli.py worktree list # List worktrees
|
|
python cli.py worktree create 101 # Create worktree for issue 101
|
|
python cli.py parallel run -f example_tasks.json
|
|
python cli.py demo # Run full demo
|
|
""")
|
|
|
|
except Exception as e:
|
|
print(f"\n✗ Error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|