13 KiB
GitHub Actions Integration Guide - Hybrid Approach
Date: 2025-12-02 Approach: Hybrid (n8n → GitHub Actions → OpenHands SDK) Status: Ready for implementation
🎯 Overview
This guide shows how to integrate OpenHands SDK via GitHub Actions while keeping n8n for orchestration. This hybrid approach leverages the best of both worlds:
- n8n: Workflow orchestration, webhook handling, data preservation
- GitHub Actions: Clean OpenHands execution, logging, artifacts
- OpenHands SDK: Direct Python integration (no SSH/wrapper)
🏗️ Architecture
┌──────────────┐
│ Git Push │
│ (Gitea) │
└──────┬───────┘
│
▼
┌──────────────────────┐
│ Gitea Webhook │
│ (push to main) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ n8n Workflow │
│ ┌────────────────┐ │
│ │ Extract Info │ │
│ │ Trigger Actions│ │ ← HTTP call to GitHub
│ │ Wait/Callback │ │
│ │ Update Gitea │ │
│ └────────────────┘ │
└──────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ GitHub Actions Workflow │
│ ┌────────────────────────┐ │
│ │ 1. Checkout │ │
│ │ 2. Setup Python │ │
│ │ 3. Install SDK │ │
│ │ 4. Run agent_build.py │ │ ← OpenHands SDK
│ │ 5. Upload Logs │ │
│ │ 6. Update Gitea Status │ │
│ └────────────────────────┘ │
└──────┬───────────────────────┘
│
▼
┌──────────────────────┐
│ Gitea Commit │
│ Status Updated │
└──────────────────────┘
📝 Implementation Steps
Step 1: Set Up GitHub Repository (10 min)
Option A: Use GitHub.com
# Push to GitHub (if you have a GitHub account)
git remote add github https://github.com/username/repo.git
git push github main
Option B: Mirror from Gitea to GitHub
# Create GitHub repo, then mirror
git clone https://git.oky.sh/gitadmin/project.git
cd project
git remote add github https://github.com/username/project.git
git push github --all
Step 2: Configure GitHub Secrets (5 min)
In GitHub Repository → Settings → Secrets and variables → Actions:
-
OPENHANDS_API_KEY
- Value: MiniMax API key from
/home/bam/openhands/.env
- Value: MiniMax API key from
-
GITEA_API_TOKEN
- Value: Gitea API token (generate in Gitea settings)
Repository Variables:
-
LLM_MODEL
- Value:
anthropic/claude-sonnet-4-5-20250929
- Value:
-
LLM_BASE_URL (optional)
- Value: MiniMax API base URL if using custom endpoint
-
GITEA_API_URL
- Value:
https://git.oky.sh
- Value:
Step 3: Create GitHub Actions Workflow (5 min)
The workflow file is already created at:
.github/workflows/openhands-build.yml
Make sure it's in your repository root.
Step 4: Create Build Agent Script (5 min)
The agent script is already created at:
.github/scripts/agent_build.py
Make sure it's executable:
chmod +x .github/scripts/agent_build.py
Step 5: Test GitHub Actions Manually (15 min)
Trigger via GitHub UI:
- Go to GitHub → Actions tab
- Select "OpenHands Build & Test" workflow
- Click "Run workflow"
- Fill in parameters:
- Task: "Build and test this project"
- Repo Name: your-repo
- Commit SHA: current commit SHA
- Retry Count: 0
Expected Result:
- Workflow runs successfully
- Logs uploaded as artifacts
- Gitea status updated (if configured)
Step 6: Modify n8n Workflow (30 min)
Replace the OpenHands SSH node with GitHub Actions HTTP node:
Node 1: Trigger GitHub Actions (HTTP Request)
Configuration:
- Method: POST
- URL:
https://api.github.com/repos/{owner}/{repo}/actions/workflows/openhands-build.yml/dispatches - Headers:
{ "Authorization": "token {{ $node['GitHub Token'].json.token }}", "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json" } - Body:
{ "ref": "main", "inputs": { "task": "Build and test the project", "repo_name": "{{ $node['Extract Repo Info'].json.repo_name }}", "commit_sha": "{{ $node['Extract Repo Info'].json.commit_sha }}", "retry_count": "{{ $workflow.staticData.retry_count || 0 }}", "previous_errors": "{{ $json.error_message || '' }}" } }
Node 2: Wait for Completion (Wait)
- Amount: 5 (minutes)
Node 3: Check Build Status (HTTP Request)
Configuration:
- Method: GET
- URL:
https://api.github.com/repos/{owner}/{repo}/actions/runs/{{ $json.id }} - Headers:
{ "Authorization": "token {{ $node['GitHub Token'].json.token }}", "Accept": "application/vnd.github.v3+json" }
Node 4: Process Results (Code)
const runData = $json;
const repoData = $node["Extract Repo Info"].json;
const status = runData.status; // completed
const conclusion = runData.conclusion; // success or failure
let result;
if (conclusion === 'success') {
result = {
status: 'SUCCESS',
...repoData,
message: 'Build completed successfully',
github_run_id: runData.id,
github_url: runData.html_url
};
} else {
// Check if we should retry
const currentRetry = $workflow.staticData.retry_count || 0;
if (currentRetry < 3) {
// Retry with error feedback
result = {
status: 'RETRY',
...repoData,
retry_count: currentRetry + 1,
error_message: `Build failed. Check logs: ${runData.html_url}`,
github_run_id: runData.id,
github_url: runData.html_url
};
} else {
// Max retries reached
result = {
status: 'FAILED',
...repoData,
retry_count: currentRetry,
error_message: `Build failed after 3 attempts. Check logs: ${runData.html_url}`,
github_run_id: runData.id,
github_url: runData.html_url
};
}
}
return result;
Step 7: Test End-to-End Flow (30 min)
Push Test Repository:
# Make a small change and push
git add .
git commit -m "Test build"
git push origin main
Expected Flow:
- Gitea webhook triggers n8n
- n8n extracts repo info
- n8n triggers GitHub Actions
- GitHub Actions runs OpenHands SDK
- GitHub Actions updates Gitea status
- n8n receives result and notifies
Check:
- ✅ GitHub Actions runs successfully
- ✅ Build logs uploaded
- ✅ Gitea commit status updated
- ✅ n8n workflow completes
🔧 Configuration Details
GitHub Token Requirements
Create Personal Access Token:
- GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token (classic)
- Scopes:
repo(Full control of private repositories)workflow(Update GitHub Actions workflows)write:packages(Upload packages)
Use token in n8n:
- Store as credential: "GitHub Token"
- Use in HTTP nodes:
{{ $node['GitHub Token'].json.token }}
Gitea API Token
Generate Token:
- Gitea → Settings → Applications
- Generate Access Token
- Copy token (save immediately - only shown once)
Use in n8n:
- Store as credential: "Gitea API Token"
- Reference in HTTP nodes
OpenHands API Key
Sources:
- MiniMax:
/home/bam/openhands/.env→MINIMAX_API_KEY - DeepSeek:
/home/bam/openhands/.env→DEEPSEEK_API_KEY
Use in GitHub:
- Store as repository secret:
OPENHANDS_API_KEY
📊 Complete n8n Workflow Structure
Hybrid Workflow Nodes
[1] Gitea Webhook
↓
[2] Extract Repo Info (Code)
↓
[3] Initialize Retry (Code)
→ Set $workflow.staticData.retry_count
↓
[4] Trigger GitHub Actions (HTTP)
→ POST to GitHub Actions API
↓
[5] Wait for Completion (Wait)
→ 5 minutes
↓
[6] Check Build Status (HTTP)
→ GET GitHub Actions status
↓
[7] Process Results (Code)
→ Parse success/failure
→ Increment retry counter
↓
[8] Decision: Continue?
├─ YES (retry_count < 3) → [4]
└─ NO (retry_count >= 3) → [9]
↓
[9] Update Gitea Status (HTTP)
→ Success or failure
↓
[10] Format Response (Code)
↓
[11] HTTP Response
🎯 Testing Checklist
Unit Tests
- GitHub Actions workflow runs manually
- Agent script executes successfully
- OpenHands SDK initializes
- Build task completes
- Logs uploaded as artifacts
Integration Tests
- n8n triggers GitHub Actions
- GitHub Actions receives parameters
- Build executes in Actions
- n8n receives completion status
- Gitea status updated
End-to-End Tests
- Git push triggers webhook
- Workflow completes successfully
- Gitea status shows "success"
- All retries tested (success path)
- All retries tested (failure path, max 3)
- Error messages properly formatted
🐛 Troubleshooting
Issue: GitHub Actions Not Triggered
Symptoms:
- n8n HTTP request returns 404 or 403
Solutions:
- Check token has
workflowscope - Verify workflow file exists:
.github/workflows/openhands-build.yml - Check workflow file has
workflow_dispatchtrigger - Verify correct repository owner/name in URL
Issue: OpenHands API Key Error
Symptoms:
- Actions log: "LLM_API_KEY environment variable is not set"
Solutions:
- Check secret exists:
OPENHANDS_API_KEY - Verify secret value is correct
- Restart workflow (secrets require new run)
Issue: Build Hangs
Symptoms:
- Actions runs but never completes
Solutions:
- Check agent timeout settings
- Review task complexity (make simpler)
- Add timeout to agent script
- Check OpenHands logs for errors
Issue: Gitea Status Not Updated
Symptoms:
- Actions completes but Gitea status unchanged
Solutions:
- Check
GITEA_API_TOKENsecret - Verify Gitea API URL format
- Check repository owner/name
- Test API token manually:
curl -H "Authorization: token YOUR_TOKEN" \ https://git.oky.sh/api/v1/user
📈 Benefits Over SSH Approach
Complexity Reduction
| Aspect | SSH Approach | GitHub Actions Approach |
|---|---|---|
| Setup | n8n + SSH + Wrapper | n8n + GitHub Actions |
| Authentication | SSH keys | GitHub token |
| Data Flow | Complex $node pattern | Standard HTTP |
| Logging | Basic stdout/stderr | Structured + Artifacts |
| Error Handling | Custom retry logic | GitHub Actions native |
| Lines of Code | ~300 (11 nodes) | ~150 (5 nodes) |
Developer Experience
Before (SSH):
// Need to preserve data with $node pattern
const repoData = $node["Extract Repo Info"].json;
const sshOutput = $json;
return {
...repoData, // Manual data merging
code: sshOutput.code,
stdout: sshOutput.stdout
};
After (GitHub Actions):
// Standard HTTP response
const response = await fetch(url);
const result = await response.json();
return result;
Observability
SSH Approach:
- Logs: Only stdout/stderr in n8n
- Artifacts: None
- Debugging: Complex
GitHub Actions Approach:
- Logs: Structured logging to files
- Artifacts: Automatic upload
- Debugging: Full GitHub Actions UI
📚 Additional Resources
Files Created
/home/bam/claude/mvp-factory/.github/workflows/openhands-build.yml/home/bam/claude/mvp-factory/.github/scripts/agent_build.py/home/bam/claude/mvp-factory/NEW_APPROACH_ANALYSIS.md/home/bam/claude/mvp-factory/GITHUB_ACTIONS_INTEGRATION_GUIDE.md(this file)
Documentation
✅ Next Steps
Immediate (Today):
- Create GitHub repository
- Add workflow and agent script files
- Configure GitHub secrets
- Test GitHub Actions manually
Tomorrow:
- Modify n8n workflow
- Add GitHub Actions trigger
- Test end-to-end flow
- Fix any issues
Day 3:
- Test retry logic
- Test failure scenarios
- Verify Gitea integration
- Document configuration
Success Criteria:
- ✅ GitHub Actions runs successfully
- ✅ n8n orchestrates without SSH
- ✅ Gitea status updates automatically
- ✅ Simpler than SSH approach
- ✅ Better error handling and logging
Integration Guide - 2025-12-02 Ready for implementation