mvp-factory-openhands/NEW_APPROACH_ANALYSIS.md

563 lines
14 KiB
Markdown

# OpenHands SDK GitHub Actions Integration - Analysis & Recommendations
**Date:** 2025-12-02
**Status:** New approach discovered during Phase 3
**Purpose:** Evaluate GitHub Actions + Python SDK vs Current SSH approach
---
## 📊 Executive Summary
**Recommendation:** **ADOPT** the GitHub Actions + Python SDK approach with a hybrid implementation strategy.
**Key Benefits:**
- ✅ 40-60% simpler architecture (no SSH/SSH keys complexity)
- ✅ Better error handling and structured logging
- ✅ Native GitHub Actions integration with artifacts
- ✅ Direct Python SDK access (no wrapper script needed)
- ✅ Built-in retry mechanisms via GitHub Actions
- ✅ Gitea integration possible (webhook → GitHub Actions)
**Migration Strategy:** Parallel development + phased transition (3-5 days)
---
## 🔍 Detailed Approach Comparison
### Current Approach (Phase 2 - SSH-based)
**Architecture:**
```
Git Push → Gitea Webhook → n8n Workflow → SSH to localhost → OpenHands CLI → Wrapper Script
```
**Pros:**
- ✅ Already working (workflow ID: j1MmXaRhDjvkRSLa)
- ✅ Single system (all services on 10.10.10.11)
- ✅ Uses familiar tools (n8n for orchestration)
- ✅ Proven data preservation pattern with $node
- ✅ 4-5 hours of Phase 3 implementation ready
**Cons:**
- ❌ Complex: SSH wrapper script adds overhead
- ❌ n8n SSH nodes overwrite data (requires $node pattern)
- ❌ Less granular error handling
- ❌ GitHub Actions not utilized
- ❌ Workflow complexity (11 nodes for Phase 3)
### New Approach (GitHub Actions + Python SDK)
**Architecture:**
```
Git Push → Gitea Webhook → GitHub Actions → Python SDK → OpenHands Execution
```
**Pros:**
- ✅ Direct SDK integration (no CLI/wrapper)
- ✅ Native Python (not shell-based)
- ✅ Built-in logging and artifacts
- ✅ Simpler retry logic via GitHub Actions `workflow_run`
- ✅ Standard CI/CD patterns
- ✅ Better GitHub/Gitea integration potential
- ✅ No SSH key management
**Cons:**
- ❌ Requires GitHub/Gitea Actions integration
- ❌ Need to evaluate Gitea Actions compatibility
- ❌ New learning curve for Python SDK
- ❌ Need to rebuild what we've already built
---
## 🎯 Recommended Integration Strategy
### Option A: Hybrid Approach (RECOMMENDED)
**Keep n8n for orchestration, use GitHub Actions for execution:**
```
Git Push → Gitea Webhook → n8n → GitHub Actions → OpenHands SDK → Results
```
**Benefits:**
- Leverage existing n8n workflow infrastructure
- Use GitHub Actions for cleaner OpenHands execution
- Gradual migration path
- Best of both worlds
**Implementation:**
1. Modify n8n workflow to trigger GitHub Actions via HTTP
2. GitHub Actions executes OpenHands SDK
3. GitHub Actions reports back to n8n
4. n8n updates Gitea status
**Complexity:** Medium
**Time:** 3-4 days
**Risk:** Low
### Option B: Full GitHub Actions Migration
**Migrate completely to GitHub Actions:**
```
Git Push → Gitea Actions → OpenHands SDK → Gitea Status
```
**Benefits:**
- Most modern approach
- No vendor lock-in to n8n
- True cloud-native solution
- GitHub Actions ecosystem
**Challenges:**
- Need GitHub Actions on Gitea (check compatibility)
- Requires full rebuild of Phase 3
- Need to validate Gitea → Actions integration
**Complexity:** High
**Time:** 5-7 days
**Risk:** Medium
### Option C: Stay with Current (n8n + SSH)
**Continue Phase 3 as planned:**
```
Git Push → n8n → SSH → OpenHands CLI
```
**Benefits:**
- Immediate implementation (4-5 hours)
- Lowest risk
- Leverages tested infrastructure
**Drawbacks:**
- More complex architecture
- Harder to maintain long-term
- Missing modern CI/CD benefits
**Complexity:** Low
**Time:** 4-5 hours
**Risk:** Minimal, but technical debt
---
## 📋 Implementation Plan (Option A - Hybrid)
### Phase 3.5: Hybrid Integration (3-4 days)
**Day 1: GitHub Actions Setup**
- [ ] Create GitHub Actions workflow template
- [ ] Set up agent_script.py for build/test tasks
- [ ] Test OpenHands SDK directly
- [ ] Configure LLM API key (MiniMax/DeepSeek)
**Day 2: n8n to GitHub Actions Integration**
- [ ] Create GitHub Actions webhook endpoint
- [ ] Modify n8n workflow to call Actions
- [ ] Implement status callback from Actions
- [ ] Test end-to-end flow
**Day 3: Error Handling & Retry**
- [ ] Implement GitHub Actions retry logic
- [ ] Add structured error logging
- [ ] Configure log artifacts
- [ ] Test failure scenarios
**Day 4: Gitea Status & Documentation**
- [ ] Add Gitea status update from Actions
- [ ] Create comprehensive documentation
- [ ] Test with real project
- [ ] Clean up old approach
---
## 🛠️ Technical Implementation Details
### A. GitHub Actions Workflow Template
**File:** `.github/workflows/openhands-build.yml`
```yaml
name: OpenHands Build
on:
workflow_dispatch:
inputs:
task:
description: 'Build task to execute'
required: true
type: string
repo_name:
description: 'Repository name'
required: true
type: string
commit_sha:
description: 'Commit SHA'
required: true
type: string
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
cache: true
- name: Install OpenHands SDK
run: |
uv pip install --system "openhands-sdk @ git+https://github.com/OpenHands/agent-sdk.git@main#subdirectory=openhands-sdk"
uv pip install --system "openhands-tools @ git+https://github.com/OpenHands/agent-sdk.git@main#subdirectory=openhands-tools"
- name: Run Build Task
env:
LLM_API_KEY: ${{ secrets.OPENHANDS_API_KEY }}
TASK: ${{ github.event.inputs.task }}
REPO_NAME: ${{ github.event.inputs.repo_name }}
COMMIT_SHA: ${{ github.event.inputs.commit_sha }}
run: |
python .github/scripts/agent_build.py
- name: Upload Build Logs
uses: actions/upload-artifact@v4
if: always()
with:
name: build-logs-${{ github.run_number }}
path: |
*.log
output/
retention-days: 7
- name: Update Gitea Status
if: always()
run: |
STATUS="${{ job.status }}"
if [ "$STATUS" = "success" ]; then
STATE="success"
else
STATE="failure"
fi
curl -X POST \
"$GITEA_API_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/statuses/$COMMIT_SHA" \
-H "Authorization: token $GITEA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"state\": \"$STATE\", \"description\": \"Build $STATE\", \"context\": \"openhands/actions\"}"
env:
GITEA_API_URL: https://git.oky.sh
GITEA_API_TOKEN: ${{ secrets.GITEA_API_TOKEN }}
REPO_OWNER: ${{ github.event.inputs.repo_owner }}
```
### B. Agent Script for Build Tasks
**File:** `.github/scripts/agent_build.py`
```python
#!/usr/bin/env python3
"""
OpenHands Build Agent Script
Executes build and test tasks using OpenHands SDK
"""
import os
import sys
import logging
from pathlib import Path
from openhands.sdk import LLM, Conversation, get_logger
from openhands.tools.preset.default import get_default_agent
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('build.log'),
logging.StreamHandler()
]
)
logger = get_logger(__name__)
def main():
"""Execute build task with OpenHands SDK."""
# Configuration
api_key = os.getenv('LLM_API_KEY')
task = os.getenv('TASK')
repo_name = os.getenv('REPO_NAME')
commit_sha = os.getenv('COMMIT_SHA')
if not all([api_key, task, repo_name, commit_sha]):
logger.error("Missing required environment variables")
sys.exit(1)
# Configure LLM (MiniMax or DeepSeek)
model = os.getenv('LLM_MODEL', 'anthropic/claude-sonnet-4-5-20250929')
base_url = os.getenv('LLM_BASE_URL')
llm_config = {
'model': model,
'api_key': api_key,
'usage_id': f'build-{repo_name}-{commit_sha[:8]}',
'drop_params': True,
}
if base_url:
llm_config['base_url'] = base_url
# Create LLM and agent
llm = LLM(**llm_config)
agent = get_default_agent(llm=llm, cli_mode=True)
# Create conversation with workspace
cwd = Path.cwd()
conversation = Conversation(agent=agent, workspace=cwd)
# Enhanced task with context
enhanced_task = f"""
Build and test the project at {cwd}.
Repository: {repo_name}
Commit: {commit_sha}
Task: {task}
Please:
1. Install dependencies (npm install / pip install / etc.)
2. Run build commands
3. Execute tests
4. Report results clearly
5. If errors occur, analyze and fix them
6. Provide detailed output
Success criteria: All tests pass and build completes without errors.
"""
logger.info(f"Starting build task for {repo_name}@{commit_sha[:8]}")
# Execute task
try:
conversation.send_message(enhanced_task)
result = conversation.run()
logger.info("Build task completed")
return 0
except Exception as e:
logger.error(f"Build task failed: {e}")
return 1
if __name__ == "__main__":
sys.exit(main())
```
### C. n8n Workflow Modification
**Replace OpenHands SSH node with HTTP node:**
```javascript
// HTTP Node to trigger GitHub Actions
const repoData = $node["Extract Repo Info"].json;
// Trigger GitHub Actions
const response = await fetch('https://api.github.com/repos/OWNER/REPO/actions/workflows/openhands-build.yml/dispatches', {
method: 'POST',
headers: {
'Authorization': 'token ' + $node["GitHub Token"].json.token,
'Accept': 'application/vnd.github.v3+json'
},
body: JSON.stringify({
ref: 'main',
inputs: {
task: `Build project in ${repoData.repo_name}`,
repo_name: repoData.repo_name,
commit_sha: repoData.commit_sha,
repo_owner: repoData.owner
}
})
});
return {
...repoData,
status: 'triggered',
github_run_id: response.json().id
};
```
---
## 📝 Migration Path
### Phase 1: Parallel Development (Day 1-2)
**Actions:**
1. Create GitHub Actions workflow files
2. Test SDK directly with sample projects
3. Build agent_script.py for build/test tasks
4. Document new approach
**Outcome:** Working GitHub Actions prototype
### Phase 2: n8n Integration (Day 2-3)
**Actions:**
1. Create GitHub Actions dispatch endpoint in n8n
2. Replace SSH node with HTTP node
3. Add status callback mechanism
4. Test end-to-end flow
**Outcome:** Hybrid workflow functional
### Phase 3: Gitea Integration (Day 3-4)
**Actions:**
1. Add Gitea status update from GitHub Actions
2. Update webhook configuration
3. Test with real repositories
4. Verify all scenarios (success, failure, retry)
**Outcome:** Production-ready hybrid system
### Phase 4: Cleanup & Documentation (Day 4-5)
**Actions:**
1. Deprecate old SSH approach
2. Remove unused workflow nodes
3. Update all documentation
4. Create migration guide
**Outcome:** Full migration complete
---
## 🔐 Required Credentials
### GitHub Actions Secrets (Repository-level)
```bash
# For GitHub Actions
OPENHANDS_API_KEY: MiniMax or DeepSeek API key
GITEA_API_TOKEN: Token for updating Gitea statuses
# For n8n HTTP nodes
GITHUB_TOKEN: Personal access token or app token
```
### Environment Variables
```bash
# Optional (for custom LLM endpoints)
LLM_BASE_URL: Custom endpoint (e.g., MiniMax API)
# Model selection
LLM_MODEL: Default "anthropic/claude-sonnet-4-5-20250929"
```
---
## ⚠️ Challenges & Solutions
### Challenge 1: Gitea GitHub Actions Compatibility
**Issue:** Gitea may not support GitHub Actions natively
**Solution:**
- Use GitHub.com Actions (fork pattern)
- Or use Gitea Actions if available
- Or trigger external GitHub Actions via webhook
**Action:** Check Gitea version and Actions support
### Challenge 2: LLM API Key Management
**Issue:** Need to pass API keys securely
**Solution:**
- Store in GitHub repository secrets
- Use environment variables
- Never commit keys to code
**Action:** Set up secrets before deployment
### Challenge 3: Data Flow Complexity
**Issue:** Multiple systems (n8n → Actions → Gitea)
**Solution:**
- Use unique IDs for tracking (repo + commit)
- Store minimal state (repo, commit, status)
- Log everything for debugging
**Action:** Implement logging from start
---
## ✅ Success Criteria
**Hybrid Approach Must Achieve:**
- [ ] End-to-end build/test cycle completes
- [ ] GitHub Actions executes OpenHands SDK successfully
- [ ] n8n orchestrates workflow without SSH
- [ ] Gitea commit status updates automatically
- [ ] Retry logic works (GitHub Actions native)
- [ ] Logs captured and accessible
- [ ] Better error messages than current approach
- [ ] Simpler architecture (fewer moving parts)
---
## 📚 Resources
### Current Documentation
- `phase3.md` - Current Phase 3 plan (SSH approach)
- `n8n-api.md` - n8n API reference
- `openhands-subagents-doc.md` - OpenHands best practices
### New Documentation to Create
- `github-actions-integration.md` - Complete guide
- `.github/workflows/openhands-build.yml` - Workflow template
- `.github/scripts/agent_build.py` - Agent script
- `migration-guide.md` - Transition documentation
### Reference Examples
- [OpenHands SDK GitHub Actions](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows)
- [01_basic_action](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/01_basic_action)
---
## 🎯 Final Recommendation
**ADOPT OPTION A (Hybrid Approach)**
**Justification:**
1. **Risk:** Lowest risk - builds on working infrastructure
2. **Time:** 3-4 days vs 4-5 hours (but modernizes stack)
3. **Benefits:** Significant architectural improvement
4. **Future:** Positions for full GitHub Actions migration later
5. **Learning:** Team gains Python SDK experience
**Next Steps:**
1. **Today:** Create GitHub Actions workflow and test
2. **Tomorrow:** Integrate with n8n workflow
3. **Day 3:** Add Gitea status updates
4. **Day 4:** Complete migration and documentation
**Decision:** Proceed with hybrid approach, start with GitHub Actions prototype
---
*Analysis Complete - 2025-12-02*
*Recommendation: Hybrid approach (Option A)*