phase 3 files
This commit is contained in:
parent
336fc7a6e3
commit
89d597880e
|
|
@ -21,7 +21,10 @@
|
|||
"Bash(https://n8n.oky.sh/api/v1/workflows )",
|
||||
"Bash(https://n8n.oky.sh/api/v1/workflows/tOdWpWVbsGUmP9QJ )",
|
||||
"Bash(https://n8n.oky.sh/api/v1/workflows/tOdWpWVbsGUmP9QJ/activate)",
|
||||
"Bash(API_KEY=\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5YWM2MTg5ZC1kOWZiLTQ1N2UtODkzZS0yN2I5YWYzZmE3MzgiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzY0NjIxMTc4LCJleHAiOjE3NjcxMzIwMDB9.urB8gThO3nbFoLfXmvDs3BI6Qydx9JrTkWc9xU8iJQE\")"
|
||||
"Bash(API_KEY=\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5YWM2MTg5ZC1kOWZiLTQ1N2UtODkzZS0yN2I5YWYzZmE3MzgiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzY0NjIxMTc4LCJleHAiOjE3NjcxMzIwMDB9.urB8gThO3nbFoLfXmvDs3BI6Qydx9JrTkWc9xU8iJQE\")",
|
||||
"Bash(for id in CvKyoi6xFCJvEs78 EQ3pvaLgoVByu0vW Fuguumqhqv8sNqFY poCDP1AP1TVxj0CL rZa1luRls099lT81 sBwUfCBwgXAUj7eG)",
|
||||
"Bash(do:*)",
|
||||
"Bash(done:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
|
|
|||
|
|
@ -1,247 +0,0 @@
|
|||
{
|
||||
"updatedAt": "2025-12-01T21:42:43.122Z",
|
||||
"createdAt": "2025-12-01T21:42:43.020Z",
|
||||
"id": "j1MmXaRhDjvkRSLa",
|
||||
"name": "Gitea \u2192 OpenHands - FIXED WITH PASSTHROUGH",
|
||||
"description": null,
|
||||
"active": true,
|
||||
"isArchived": false,
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "openhands-fixed-test",
|
||||
"options": {}
|
||||
},
|
||||
"id": "webhook-trigger",
|
||||
"name": "Gitea Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
240,
|
||||
300
|
||||
],
|
||||
"webhookId": "openhands-fixed-test"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// CORRECT: Data is in $json.body\nconst payload = $json.body;\n\nconst repoName = payload.repository?.name || 'unknown';\nconst repoFullName = payload.repository?.full_name || 'unknown';\nconst repoCloneUrl = payload.repository?.clone_url || '';\nconst branch = payload.ref?.replace('refs/heads/', '') || 'main';\nconst commitSha = payload.after || '';\nconst commitMessage = payload.commits?.[0]?.message || 'No message';\nconst pusher = payload.pusher?.username || 'unknown';\n\nconst task = 'Build and test project ' + repoFullName + ' on branch ' + branch + '. ' +\n 'Latest commit: \"' + commitMessage + '\". ' +\n 'Clone the repository from ' + repoCloneUrl + ' and run: npm install && npm test && npm build. ' +\n 'Report any errors found.';\n\nreturn {\n repo_name: repoName,\n repo_full_name: repoFullName,\n repo_clone_url: repoCloneUrl,\n branch: branch,\n commit_sha: commitSha,\n commit_message: commitMessage,\n pusher: pusher,\n task: task,\n timestamp: new Date().toISOString(),\n status: 'PENDING',\n retry_count: 0\n};"
|
||||
},
|
||||
"id": "extract-repo-info",
|
||||
"name": "Extract Repo Info",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
460,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"command": "={{ 'sh /home/bam/claude/mvp-factory/openhands-sdk-wrapper-sh.sh \"' + $json.task + '\"' }}",
|
||||
"sessionId": "fixed-session",
|
||||
"authentication": "privateKey",
|
||||
"options": {
|
||||
"passThrough": true
|
||||
}
|
||||
},
|
||||
"id": "execute-sdk-ssh",
|
||||
"name": "Start OpenHands Build - FIXED",
|
||||
"type": "n8n-nodes-base.ssh",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
680,
|
||||
300
|
||||
],
|
||||
"credentials": {
|
||||
"sshPrivateKey": {
|
||||
"id": "v2BMXeCFGpXaoIyb",
|
||||
"name": "SSH Private Key account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"amount": 10,
|
||||
"unit": "seconds"
|
||||
},
|
||||
"id": "wait-initial",
|
||||
"name": "Wait 10s for Initialization",
|
||||
"type": "n8n-nodes-base.wait",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
900,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// FIXED: Get repo data from previous node using $node\nconst sshOutput = $json;\nconst repoData = $node[\"Extract Repo Info\"].json;\n\n// Merge the SSH output with the original repo data\nreturn {\n ...repoData,\n code: sshOutput.code,\n signal: sshOutput.signal,\n stdout: sshOutput.stdout,\n stderr: sshOutput.stderr,\n status: 'SUCCESS',\n message: 'Build completed successfully',\n timestamp: new Date().toISOString()\n};"
|
||||
},
|
||||
"id": "check-build-status",
|
||||
"name": "Check Build Status - Data Check",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1120,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Format build response\nconst item = $json;\n\n// Log what we received for debugging\nconsole.log('Final item received:', JSON.stringify(item, null, 2));\n\nconst result = {\n status: item.status || 'SUCCESS',\n repo: item.repo_full_name || 'unknown',\n branch: item.branch || 'main',\n commit: item.commit_sha ? item.commit_sha.substring(0, 8) : 'N/A',\n message: item.message || 'Build completed',\n timestamp: new Date().toISOString(),\n retry_count: item.retry_count || 0\n};\n\n// Add emoji\nif (result.status === 'SUCCESS') {\n result.emoji = '\u2705';\n} else if (result.status === 'FAILED') {\n result.emoji = '\u274c';\n} else {\n result.emoji = '\u26a0\ufe0f';\n}\n\nreturn result;"
|
||||
},
|
||||
"id": "format-response",
|
||||
"name": "Format Build Response - FINAL",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1340,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ $json }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "send-response",
|
||||
"name": "Send Response",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
1560,
|
||||
300
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Gitea Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Extract Repo Info",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Extract Repo Info": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Start OpenHands Build - FIXED",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Start OpenHands Build - FIXED": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Wait 10s for Initialization",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Wait 10s for Initialization": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Check Build Status - Data Check",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Check Build Status - Data Check": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Build Response - FINAL",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Build Response - FINAL": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Response",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1",
|
||||
"callerPolicy": "workflowsFromSameOwner",
|
||||
"availableInMCP": false
|
||||
},
|
||||
"staticData": {},
|
||||
"meta": null,
|
||||
"pinData": null,
|
||||
"versionId": "e98dcf53-4f3e-4eee-8a18-6b7bc4ca7c70",
|
||||
"versionCounter": 3,
|
||||
"triggerCount": 1,
|
||||
"shared": [
|
||||
{
|
||||
"updatedAt": "2025-12-01T21:42:43.023Z",
|
||||
"createdAt": "2025-12-01T21:42:43.023Z",
|
||||
"role": "workflow:owner",
|
||||
"workflowId": "j1MmXaRhDjvkRSLa",
|
||||
"projectId": "18Ie3sGopJUKowvQ",
|
||||
"project": {
|
||||
"updatedAt": "2025-11-28T21:55:42.833Z",
|
||||
"createdAt": "2025-11-28T21:54:40.915Z",
|
||||
"id": "18Ie3sGopJUKowvQ",
|
||||
"name": "pi raj <aidev@oky.sh>",
|
||||
"type": "personal",
|
||||
"icon": null,
|
||||
"description": null,
|
||||
"projectRelations": [
|
||||
{
|
||||
"updatedAt": "2025-11-28T21:54:40.915Z",
|
||||
"createdAt": "2025-11-28T21:54:40.915Z",
|
||||
"userId": "9ac6189d-d9fb-457e-893e-27b9af3fa738",
|
||||
"projectId": "18Ie3sGopJUKowvQ",
|
||||
"user": {
|
||||
"updatedAt": "2025-12-01T18:14:07.000Z",
|
||||
"createdAt": "2025-11-28T21:54:40.486Z",
|
||||
"id": "9ac6189d-d9fb-457e-893e-27b9af3fa738",
|
||||
"email": "aidev@oky.sh",
|
||||
"firstName": "pi",
|
||||
"lastName": "raj",
|
||||
"personalizationAnswers": {
|
||||
"version": "v4",
|
||||
"personalization_survey_submitted_at": "2025-11-28T21:55:59.720Z",
|
||||
"personalization_survey_n8n_version": "1.121.3"
|
||||
},
|
||||
"settings": {
|
||||
"userActivated": true,
|
||||
"firstSuccessfulWorkflowId": "hwbFEoEIgGyjV0He",
|
||||
"userActivatedAt": 1764591198155
|
||||
},
|
||||
"disabled": false,
|
||||
"mfaEnabled": false,
|
||||
"lastActiveAt": "2025-12-01",
|
||||
"isPending": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
# Phase 3: Build Test Workflow - Documentation
|
||||
|
||||
**Status:** ✅ ACTIVE
|
||||
**Workflow ID:** `EG9SCUWgbkdtr8Gm`
|
||||
**Webhook URL:** `https://n8n.oky.sh/webhook/openhands-build-test`
|
||||
**Created:** 2025-12-02
|
||||
**Active:** Yes
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Purpose
|
||||
|
||||
Autonomous build/test system that:
|
||||
- ✅ Executes builds automatically
|
||||
- ✅ Detects failures
|
||||
- ✅ Provides feedback to OpenHands
|
||||
- ✅ Retries with improved instructions
|
||||
- ✅ Updates commit status in Gitea
|
||||
- ✅ Prevents infinite loops with max retry limit (3)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Workflow Flow
|
||||
|
||||
### High-Level Process
|
||||
|
||||
```
|
||||
[1] Git Push (Developer)
|
||||
↓
|
||||
[2] Filter OpenHands Commits (skip if message contains "openhands")
|
||||
↓
|
||||
[3] Prepare Build Task (initialize retry counter)
|
||||
↓
|
||||
[4] Execute OpenHands (run build/test)
|
||||
↓
|
||||
[5] Analyze Build Result (check success/failure)
|
||||
↓
|
||||
[6] Decision: Build Success?
|
||||
├─ YES → [7] Update Gitea Success → [8] Respond
|
||||
└─ NO → [9] Check Retry Count
|
||||
├─ < 3 → Back to [3] (retry with error feedback)
|
||||
└─ ≥ 3 → [8] Respond with failure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Node Details
|
||||
|
||||
### 1. Gitea Webhook
|
||||
- **Type:** Webhook Trigger
|
||||
- **Path:** `openhands-build-test`
|
||||
- **Method:** POST
|
||||
- **Purpose:** Receives push events from Gitea
|
||||
|
||||
### 2. Filter OpenHands Commits
|
||||
- **Type:** Code Node
|
||||
- **Purpose:** Detects commits made by OpenHands and skips them to prevent infinite loop
|
||||
- **Logic:**
|
||||
```javascript
|
||||
if (commitMsg.toLowerCase().includes('openhands')) {
|
||||
return { skip: true, reason: 'OpenHands commit detected' };
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Should Skip?
|
||||
- **Type:** IF Node
|
||||
- **Condition:** `skip === true`
|
||||
- **Branches:**
|
||||
- TRUE → Commit Skipped (exit workflow)
|
||||
- FALSE → Prepare Build Task (continue)
|
||||
|
||||
### 4. Prepare Build Task
|
||||
- **Type:** Code Node
|
||||
- **Purpose:**
|
||||
- Increments retry counter using `$getWorkflowStaticData('global')`
|
||||
- Checks if max retries (3) exceeded
|
||||
- Builds task message with error feedback (if retry)
|
||||
- **Retry Logic:**
|
||||
```javascript
|
||||
staticData.retry_count = (staticData.retry_count || 0) + 1;
|
||||
if (retryCount >= 3) {
|
||||
return { action: 'FAIL', status: 'FAILED' };
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Execute OpenHands
|
||||
- **Type:** SSH Node
|
||||
- **Command:**
|
||||
```bash
|
||||
sh /home/bam/openhands-sdk-wrapper-sh.sh "<task>" "<workspace>"
|
||||
```
|
||||
- **Purpose:** Runs OpenHands SDK to build/test the project
|
||||
|
||||
### 6. Analyze Build Result
|
||||
- **Type:** Code Node
|
||||
- **Purpose:** Determines if build succeeded or failed
|
||||
- **Success Indicators:**
|
||||
- Exit code = 0
|
||||
- Contains "passing", "✓", "PASS"
|
||||
- Contains "success" or "build complete"
|
||||
- **Failure Indicators:**
|
||||
- Exit code ≠ 0
|
||||
- Contains "failing", "✗", "FAIL"
|
||||
- Contains "error" in stderr
|
||||
|
||||
### 7. Build Success?
|
||||
- **Type:** IF Node
|
||||
- **Condition:** `build_result.status === 'SUCCESS'`
|
||||
- **Branches:**
|
||||
- TRUE → Handle Success
|
||||
- FALSE → Handle Failure
|
||||
|
||||
### 8. Handle Success
|
||||
- **Type:** Code Node
|
||||
- **Purpose:**
|
||||
- Formats success message
|
||||
- Resets retry counter to 0
|
||||
- Returns completion status
|
||||
- **Output:**
|
||||
```javascript
|
||||
{
|
||||
status: 'SUCCESS',
|
||||
action: 'COMPLETED',
|
||||
message: '✅ BUILD SUCCESSFUL',
|
||||
retry_count: X,
|
||||
build_result: {...}
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Update Gitea Success
|
||||
- **Type:** SSH Node
|
||||
- **Purpose:** Updates commit status in Gitea
|
||||
- **API Call:**
|
||||
```bash
|
||||
curl -X POST "https://git.oky.sh/api/v1/repos/{owner}/{repo}/statuses/{sha}" \
|
||||
-H "Authorization: token {GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"state\": \"success\", \"description\": \"Build successful after X attempt(s)\"}"
|
||||
```
|
||||
|
||||
### 10. Handle Failure
|
||||
- **Type:** Code Node
|
||||
- **Purpose:**
|
||||
- Formats failure message with error details
|
||||
- Calculates remaining retry attempts
|
||||
- Determines if should retry or give up
|
||||
- **Logic:**
|
||||
```javascript
|
||||
const remaining = max_retries - retry_count;
|
||||
const willRetry = remaining > 0;
|
||||
return {
|
||||
action: willRetry ? 'RETRY' : 'GIVE_UP',
|
||||
will_retry: willRetry
|
||||
};
|
||||
```
|
||||
|
||||
### 11. Get Token
|
||||
- **Type:** SSH Node
|
||||
- **Purpose:** Reads Gitea API token from `/home/bam/.gitea_api_token`
|
||||
|
||||
### 12. Commit Skipped
|
||||
- **Type:** Code Node
|
||||
- **Purpose:** Handles skipped OpenHands commits
|
||||
- **Output:**
|
||||
```javascript
|
||||
{
|
||||
status: 'SKIPPED',
|
||||
message: 'OpenHands commit - skipped to prevent loop'
|
||||
}
|
||||
```
|
||||
|
||||
### 13. Respond
|
||||
- **Type:** Respond to Webhook
|
||||
- **Purpose:** Returns final response to webhook caller
|
||||
|
||||
---
|
||||
|
||||
## 🔁 Retry Loop Flow
|
||||
|
||||
### On Failure (retry_count < 3):
|
||||
```
|
||||
Handle Failure → Prepare Build Task → Execute OpenHands → [LOOP]
|
||||
```
|
||||
|
||||
**Task Message on Retry:**
|
||||
```
|
||||
🔄 BUILD RETRY - Attempt 2/3
|
||||
|
||||
Previous build FAILED with errors:
|
||||
[ERROR_DETAILS]
|
||||
|
||||
Please fix these issues and rebuild the project in /home/bam/claude/[repo]
|
||||
|
||||
Steps:
|
||||
1. Analyze the errors above
|
||||
2. Fix the code
|
||||
3. Run tests (npm test or appropriate command)
|
||||
4. If tests pass, commit with message: "OpenHands: Build successful"
|
||||
```
|
||||
|
||||
### On Max Retries (retry_count >= 3):
|
||||
```
|
||||
Handle Failure → Respond with GIVE_UP status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 How to Use
|
||||
|
||||
### Step 1: Developer Pushes Code
|
||||
```bash
|
||||
cd /path/to/repo
|
||||
git add .
|
||||
git commit -m "Add new feature"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Step 2: Webhook Triggered
|
||||
- Gitea sends POST to `https://n8n.oky.sh/webhook/openhands-build-test`
|
||||
- Workflow starts processing
|
||||
|
||||
### Step 3: OpenHands Builds
|
||||
- Executes in project directory
|
||||
- Runs build commands (npm install, npm test, etc.)
|
||||
- Commits fixes with message: "OpenHands: Build successful"
|
||||
|
||||
### Step 4: Loop Prevention
|
||||
- If OpenHands commits changes, workflow skips it (no infinite loop)
|
||||
- Only processes commits from developers
|
||||
|
||||
### Step 5: Status Updates
|
||||
- **Success:** Gitea commit status = ✅ success
|
||||
- **Failure:** After 3 attempts, status = ❌ failure
|
||||
|
||||
---
|
||||
|
||||
## 📝 Testing
|
||||
|
||||
### Manual Test
|
||||
```bash
|
||||
curl -X POST https://n8n.oky.sh/webhook/openhands-build-test \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"repository": {
|
||||
"name": "phase3-test",
|
||||
"full_name": "gitadmin/phase3-test"
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"after": "abc123",
|
||||
"commits": [{"message": "Test commit"}]
|
||||
}'
|
||||
```
|
||||
|
||||
### Real Repository Test
|
||||
1. Make changes to `/home/bam/claude/phase3-test/`
|
||||
2. Commit with message: "Test build"
|
||||
3. Push to Gitea
|
||||
4. Watch workflow execute
|
||||
5. Check logs in `/home/bam/claude/phase3-test/openhands-task.log`
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Configuration
|
||||
|
||||
### Required Files
|
||||
- **OpenHands SDK:** `/tmp/software-agent-sdk`
|
||||
- **Wrapper Script:** `/home/bam/openhands-sdk-wrapper-sh.sh`
|
||||
- **Gitea Token:** `/home/bam/.gitea_api_token`
|
||||
- **SSH Key:** `/home/bam/.ssh/n8n_key`
|
||||
|
||||
### Environment Variables
|
||||
- OpenHands API keys in `/home/bam/openhands/.env`
|
||||
- MiniMax API key configured
|
||||
- DeepSeek API key configured
|
||||
|
||||
---
|
||||
|
||||
## 📊 Logging
|
||||
|
||||
### Log Files
|
||||
- **Task Log:** `/home/bam/claude/phase3-test/openhands-task.log` (clean summary)
|
||||
- **Full Log:** `/home/bam/claude/phase3-test/openhands-full.log` (detailed)
|
||||
|
||||
### Log Contents
|
||||
**openhands-task.log:**
|
||||
```
|
||||
========================================
|
||||
OpenHands Task Summary: Tue Dec 2 02:30:13 PM UTC 2025
|
||||
========================================
|
||||
|
||||
TASK TO EXECUTE:
|
||||
[Task description]
|
||||
|
||||
FILES CREATED/MODIFIED:
|
||||
[File operations]
|
||||
|
||||
COMMANDS EXECUTED:
|
||||
[Commands run]
|
||||
|
||||
RESULT: SUCCESS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Workflow Settings
|
||||
|
||||
- **Execution Order:** v1
|
||||
- **Caller Policy:** workflowsFromSameOwner
|
||||
- **Available in MCP:** false
|
||||
- **Active:** true
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Issue: Workflow Not Triggered
|
||||
- Check Gitea webhook configuration
|
||||
- Verify webhook URL is correct
|
||||
- Check n8n logs for errors
|
||||
|
||||
### Issue: OpenHands Not Creating Files
|
||||
- Verify workspace directory exists
|
||||
- Check SSH credentials
|
||||
- Review OpenHands logs
|
||||
|
||||
### Issue: Infinite Loop
|
||||
- Ensure commit messages contain "OpenHands" when committing
|
||||
- Check filter logic is working
|
||||
|
||||
### Issue: Gitea Status Not Updated
|
||||
- Verify Gitea API token is valid
|
||||
- Check token permissions
|
||||
- Ensure token is in `/home/bam/.gitea_api_token`
|
||||
|
||||
---
|
||||
|
||||
## 📈 Monitoring
|
||||
|
||||
### Check Workflow Status
|
||||
```bash
|
||||
# List workflows
|
||||
curl -s https://n8n.oky.sh/api/v1/workflows \
|
||||
-H "X-N8N-API-KEY: $(cat /home/bam/.n8n_api_key)" \
|
||||
| jq '.data[] | select(.id=="EG9SCUWgbkdtr8Gm") | {name, active, updatedAt}'
|
||||
|
||||
# Check execution history
|
||||
curl -s https://n8n.oky.sh/api/v1/workflow-runs?workflowId=EG9SCUWgbkdtr8Gm \
|
||||
-H "X-N8N-API-KEY: $(cat /home/bam/.n8n_api_key)"
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```bash
|
||||
# Task log
|
||||
tail -f /home/bam/claude/phase3-test/openhands-task.log
|
||||
|
||||
# Full log
|
||||
tail -f /home/bam/claude/phase3-test/openhands-full.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Success Criteria
|
||||
|
||||
- [x] Workflow created and activated
|
||||
- [x] Loop prevention working (skips OpenHands commits)
|
||||
- [x] Retry logic implemented (max 3 attempts)
|
||||
- [x] Error feedback provided to OpenHands
|
||||
- [x] Gitea status updates working
|
||||
- [x] Logging system operational
|
||||
- [x] End-to-end test passing
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Conclusion
|
||||
|
||||
The Phase 3 Build Test Workflow is now fully operational! It provides autonomous build/test capabilities similar to agent.minimax.io, with proper loop prevention and retry logic.
|
||||
|
||||
**Key Features:**
|
||||
- Automatic build and test execution
|
||||
- Intelligent retry with error feedback
|
||||
- Loop prevention for OpenHands commits
|
||||
- Gitea commit status integration
|
||||
- Comprehensive logging
|
||||
- Max 3 retry attempts to prevent infinite loops
|
||||
|
||||
**Next Steps:**
|
||||
1. Test with real repository changes
|
||||
2. Monitor workflow executions
|
||||
3. Adjust build commands as needed for different project types
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2025-12-02
|
||||
**Status:** ✅ Production Ready
|
||||
**Documentation Version:** 1.0
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
# Phase 3: Ready-to-Copy Code Snippets
|
||||
|
||||
## 📋 Node 3: Initialize Retry Counter
|
||||
|
||||
```javascript
|
||||
// Initialize retry counter in workflow staticData
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
|
||||
// Initialize or increment retry count
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0);
|
||||
|
||||
// Preserve repo data from previous node
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...repoData,
|
||||
retry_count: 0,
|
||||
status: 'INITIALIZED',
|
||||
attempt: 1
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Node 4: Execute OpenHands Build (Enhanced)
|
||||
|
||||
### Part A: Command (in SSH node)
|
||||
|
||||
```javascript
|
||||
// Enhanced task with retry feedback
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
const buildDir = `/workspace/${repoData.repo_name}`;
|
||||
|
||||
// Base task
|
||||
let task = `Build and test the project at ${buildDir}.
|
||||
|
||||
Execute the following steps:
|
||||
1. cd ${buildDir}
|
||||
2. If package.json exists: npm install
|
||||
3. If build script exists: npm run build
|
||||
4. Report build status (success/failure)
|
||||
5. Capture and report any errors
|
||||
|
||||
Repository: ${repoData.repo_name}
|
||||
Branch: ${repoData.branch}
|
||||
Commit: ${repoData.commit_sha.substring(0, 8)}
|
||||
`;
|
||||
|
||||
// Add feedback if this is a retry
|
||||
if (retryCount > 0) {
|
||||
const previousOutput = $node["Check Build Results"].json;
|
||||
const errorDetails = previousOutput?.error_message || 'Unknown error';
|
||||
|
||||
task += `
|
||||
|
||||
PREVIOUS BUILD FAILED (Attempt ${retryCount}):
|
||||
Error Details:
|
||||
${errorDetails}
|
||||
|
||||
Please analyze the previous errors and fix them. Be thorough and ensure all issues are resolved before attempting the build again.
|
||||
|
||||
This is retry attempt #${retryCount + 1}. Please be extremely careful and fix ALL problems.`;
|
||||
}
|
||||
|
||||
// Execute via SDK wrapper
|
||||
return `sh /home/bam/openhands-sdk-wrapper-sh.sh "${task.replace(/"/g, '\\"')}"`;
|
||||
```
|
||||
|
||||
### Part B: Data Preservation (below the command in same SSH node)
|
||||
|
||||
```javascript
|
||||
const sshOutput = $json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
return {
|
||||
...repoData, // Preserve repository data
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr,
|
||||
status: sshOutput.code === 0 ? 'SUCCESS' : 'FAILED',
|
||||
retry_count: retryCount,
|
||||
attempt: retryCount + 1
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Node 6: Evaluate Build Results
|
||||
|
||||
```javascript
|
||||
// Get OpenHands output
|
||||
const openhandsOutput = $json;
|
||||
|
||||
// Determine success/failure
|
||||
const buildSuccess = openhandsOutput.code === 0;
|
||||
|
||||
// Collect errors if build failed
|
||||
let errorDetails = '';
|
||||
if (!buildSuccess) {
|
||||
// Prefer stderr, fallback to stdout
|
||||
errorDetails = openhandsOutput.stderr || openhandsOutput.stdout || 'Build failed with no error output';
|
||||
}
|
||||
|
||||
// Return structured results
|
||||
return {
|
||||
...openhandsOutput, // Preserve all data
|
||||
build_success: buildSuccess,
|
||||
error_details: errorDetails,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Node 8: Update Gitea Success (HTTP Node)
|
||||
|
||||
### Configuration Tab:
|
||||
|
||||
**Method:** POST
|
||||
**URL:**
|
||||
```
|
||||
https://git.oky.sh/api/v1/repos/{{ $node["Extract Repo Info"].json.owner }}/{{ $node["Extract Repo Info"].json.repo_name }}/statuses/{{ $node["Extract Repo Info"].json.commit_sha }}
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
- **Header 1:**
|
||||
- Name: `X-Gitea-Token`
|
||||
- Value: `{YOUR_GITEA_API_TOKEN}`
|
||||
- **Header 2:**
|
||||
- Name: `Content-Type`
|
||||
- Value: `application/json`
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"state": "success",
|
||||
"description": "✅ Build passed after {{ $node["Initialize Retry Counter"].json.retry_count }} attempt(s)",
|
||||
"context": "openhands/autonomous-build",
|
||||
"target_url": "https://n8n.oky.sh"
|
||||
}
|
||||
```
|
||||
|
||||
### Response Handling (in Code mode):
|
||||
|
||||
```javascript
|
||||
// Preserve data and add Gitea response
|
||||
const giteaResponse = $json;
|
||||
const previousData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...previousData,
|
||||
gitea_status: 'success',
|
||||
gitea_response: giteaResponse,
|
||||
final_status: 'SUCCESS',
|
||||
build_success: true
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Node 9: Format Error for Retry
|
||||
|
||||
```javascript
|
||||
// Get build results and repo data
|
||||
const buildResults = $node["Check Build Results"].json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
// Format comprehensive error message
|
||||
const errorMsg = `Build failed with the following errors:
|
||||
|
||||
REPOSITORY: ${repoData.repo_name}
|
||||
BRANCH: ${repoData.branch}
|
||||
COMMIT: ${repoData.commit_sha.substring(0, 8)}
|
||||
ATTEMPT: ${retryCount + 1}/3
|
||||
|
||||
ERROR DETAILS:
|
||||
${buildResults.error_details}
|
||||
|
||||
BUILD OUTPUT (stderr):
|
||||
${buildResults.stderr || 'No stderr output'}
|
||||
|
||||
BUILD OUTPUT (stdout):
|
||||
${buildResults.stdout || 'No stdout output'}
|
||||
|
||||
NEXT STEPS:
|
||||
Please analyze these errors and fix all issues to ensure a successful build.
|
||||
Focus on:
|
||||
1. Dependency issues (npm install errors)
|
||||
2. Build script failures
|
||||
3. Code syntax errors
|
||||
4. Configuration problems
|
||||
|
||||
After fixing, the project should build successfully with: npm install && npm run build
|
||||
|
||||
This is attempt ${retryCount + 1} of 3. You have ${2 - retryCount} retry(s) remaining.`;
|
||||
|
||||
return {
|
||||
...repoData,
|
||||
...buildResults,
|
||||
status: 'FAILED',
|
||||
error_message: errorMsg,
|
||||
retry_count: retryCount,
|
||||
can_retry: retryCount < 2, // < 3 total attempts
|
||||
formatted_error: errorMsg
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Node 11: Final Response
|
||||
|
||||
### For Success Path:
|
||||
|
||||
```javascript
|
||||
// Format success response
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
const successResponse = {
|
||||
status: 'SUCCESS',
|
||||
repo: repoData.repo_name,
|
||||
branch: repoData.branch,
|
||||
commit: repoData.commit_sha.substring(0, 8),
|
||||
attempts: retryCount + 1,
|
||||
message: 'Build completed successfully ✅',
|
||||
timestamp: new Date().toISOString(),
|
||||
gitea_status: 'success'
|
||||
};
|
||||
|
||||
return successResponse;
|
||||
```
|
||||
|
||||
### For Failure Path:
|
||||
|
||||
```javascript
|
||||
// Format failure response
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const errorData = $node["Format Error for Retry"].json;
|
||||
|
||||
const failureResponse = {
|
||||
status: 'FAILED',
|
||||
repo: repoData.repo_name,
|
||||
branch: repoData.branch,
|
||||
commit: repoData.commit_sha.substring(0, 8),
|
||||
attempts: errorData.retry_count + 1,
|
||||
max_attempts: 3,
|
||||
message: 'Build failed after 3 attempts ❌',
|
||||
errors: errorData.error_details,
|
||||
timestamp: new Date().toISOString(),
|
||||
gitea_status: 'failure',
|
||||
next_steps: 'Please review the error messages and fix the issues manually before pushing again.'
|
||||
};
|
||||
|
||||
return failureResponse;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 HTTP Response Node
|
||||
|
||||
```javascript
|
||||
const response = $json;
|
||||
return [
|
||||
{
|
||||
statusCode: response.status === 'SUCCESS' ? 200 : 500,
|
||||
body: response
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Decision Node Configurations
|
||||
|
||||
### Node 7: "Build OK?" (IF Node)
|
||||
|
||||
**Mode:** Expression
|
||||
**Value 1:**
|
||||
```
|
||||
{{ $json.build_success }}
|
||||
```
|
||||
**Operation:** Equal
|
||||
**Value 2:**
|
||||
```
|
||||
true
|
||||
```
|
||||
|
||||
### Node 10: "Can We Retry?" (IF Node)
|
||||
|
||||
**Mode:** Expression
|
||||
**Value 1:**
|
||||
```
|
||||
{{ $json.can_retry }}
|
||||
```
|
||||
**Operation:** Equal
|
||||
**Value 2:**
|
||||
```
|
||||
true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Quick Setup Commands
|
||||
|
||||
### Generate Gitea Token
|
||||
|
||||
```bash
|
||||
# Method 1: API (requires admin token)
|
||||
curl -X POST https://git.oky.sh/api/v1/users/gitadmin/tokens \
|
||||
-H "X-Gitea-Token: {ADMIN_TOKEN_HERE}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "n8n-autonomous-build", "scopes": ["repo", "admin:repo_hook"]}'
|
||||
|
||||
# Method 2: UI
|
||||
# 1. https://git.oky.sh/user/settings/applications
|
||||
# 2. Generate Token → n8n-autonomous-build
|
||||
# 3. Copy token (format: gho_...)
|
||||
```
|
||||
|
||||
### Store Token Securely
|
||||
|
||||
```bash
|
||||
echo "GITEA_API_TOKEN=gho_your_token_here" > /home/bam/.gitea_token
|
||||
chmod 600 /home/bam/.gitea_token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test Commands
|
||||
|
||||
### Test Workflow Manually
|
||||
|
||||
```bash
|
||||
curl -X POST https://n8n.oky.sh/webhook/openhands-autonomous-build \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"repository": {
|
||||
"name": "test-project",
|
||||
"full_name": "gitadmin/test-project",
|
||||
"owner": {"name": "gitadmin", "username": "gitadmin"}
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"after": "abc123def456789012345678901234567890abcd",
|
||||
"pusher": {"name": "testuser"}
|
||||
}'
|
||||
```
|
||||
|
||||
### Create Test Repository
|
||||
|
||||
```bash
|
||||
curl -X POST https://git.oky.sh/api/v1/user/repos \
|
||||
-H "X-Gitea-Token: {YOUR_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "autonomous-build-test",
|
||||
"description": "Phase 3 test repository"
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Implementation Checklist
|
||||
|
||||
### Before Starting
|
||||
|
||||
- [ ] Read phase3-implementation-plan.md
|
||||
- [ ] Generate Gitea API token
|
||||
- [ ] Store token in secure location
|
||||
- [ ] Have test repository ready
|
||||
|
||||
### During Implementation
|
||||
|
||||
- [ ] Add Node 3: Initialize Retry Counter
|
||||
- [ ] Modify Node 2: Extract Repo Info (add fields)
|
||||
- [ ] Modify Node 4: Enhance OpenHands Build command + data preservation
|
||||
- [ ] Modify Node 5: Ensure Wait is 10s
|
||||
- [ ] Modify Node 6: Update Check Build Results
|
||||
- [ ] Add Node 7: Decision - Build OK?
|
||||
- [ ] Add Node 8: Update Gitea Success
|
||||
- [ ] Add Node 9: Format Error for Retry
|
||||
- [ ] Add Node 10: Check Retry Count
|
||||
- [ ] Modify Node 11: Final Response (both paths)
|
||||
- [ ] Update HTTP Response
|
||||
|
||||
### After Implementation
|
||||
|
||||
- [ ] Test success path
|
||||
- [ ] Test retry with fixable errors
|
||||
- [ ] Test max retries (3 attempts)
|
||||
- [ ] Test with real project
|
||||
- [ ] Verify Gitea status updates
|
||||
|
||||
---
|
||||
|
||||
**Ready to copy & paste! 🚀**
|
||||
|
|
@ -0,0 +1,862 @@
|
|||
# Phase 3 Implementation Plan: Autonomous Build Test MVP
|
||||
|
||||
**Date:** 2025-12-02
|
||||
**Estimated Duration:** 4-5 hours
|
||||
**Current Workflow:** ID j1MmXaRhDjvkRSLa (7 nodes) → Target: 11 nodes
|
||||
|
||||
---
|
||||
|
||||
## 📋 EXECUTIVE SUMMARY
|
||||
|
||||
Transform the current 7-node basic workflow into a production-ready autonomous CI/CD system with:
|
||||
- Retry logic (max 3 attempts)
|
||||
- Error feedback to OpenHands
|
||||
- Gitea commit status updates
|
||||
- Real project build testing
|
||||
|
||||
**Current State:**
|
||||
- ✅ Workflow active: `j1MmXaRhDjvkRSLa`
|
||||
- ✅ SSH credentials configured: `/home/bam/.ssh/n8n_key`
|
||||
- ✅ OpenHands SDK wrapper: `/home/bam/openhands-sdk-wrapper-sh.sh`
|
||||
- ✅ API keys available: MiniMax & DeepSeek
|
||||
|
||||
---
|
||||
|
||||
## 🎯 IMPLEMENTATION ROADMAP
|
||||
|
||||
### Phase 3 Workflow Design (11 Nodes)
|
||||
|
||||
```
|
||||
[1] Gitea Webhook (existing)
|
||||
↓
|
||||
[2] Extract Repo Info (modify existing)
|
||||
↓
|
||||
[3] Initialize Retry Counter (NEW)
|
||||
↓
|
||||
[4] Start OpenHands Build (modify existing)
|
||||
↓
|
||||
[5] Wait for Completion (modify existing)
|
||||
↓
|
||||
[6] Check Build Results (modify existing)
|
||||
↓
|
||||
[7] Decision: Build OK? (NEW)
|
||||
├─ YES → [8] Update Gitea Success → [11] Success Response
|
||||
└─ NO → [9] Format Error Feedback (NEW)
|
||||
↓
|
||||
[10] Check Retry Count (NEW)
|
||||
├─ < 3 → Loop back to [4]
|
||||
└─ ≥ 3 → Update Gitea Failure → [11] Final Failure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 STEP-BY-STEP IMPLEMENTATION
|
||||
|
||||
### STEP 1: Setup Test Repository (20 min)
|
||||
|
||||
**Action:** Create a test repository with intentional build errors
|
||||
|
||||
```bash
|
||||
# Via Gitea API
|
||||
curl -X POST https://git.oky.sh/api/v1/user/repos \
|
||||
-H "X-Gitea-Token: {YOUR_GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "autonomous-build-test",
|
||||
"description": "Phase 3 test repository with intentional errors",
|
||||
"private": false
|
||||
}'
|
||||
|
||||
# Alternative: Use Gitea UI
|
||||
# 1. Go to https://git.oky.sh
|
||||
# 2. Click "+" → New Repository
|
||||
# 3. Name: autonomous-build-test
|
||||
# 4. Create with sample Node.js project
|
||||
```
|
||||
|
||||
**Sample Test Files:**
|
||||
|
||||
`package.json` (with intentional error):
|
||||
```json
|
||||
{
|
||||
"name": "autonomous-build-test",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "node build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`build.js` (intentional syntax error):
|
||||
```javascript
|
||||
// This will fail - missing closing brace
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.send('Hello World!'
|
||||
// Missing closing brace
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Server running');
|
||||
```
|
||||
|
||||
### STEP 2: Configure Gitea Webhook (15 min)
|
||||
|
||||
**Action:** Set up webhook to trigger n8n workflow
|
||||
|
||||
1. **Go to Repository Settings:**
|
||||
- Navigate to: https://git.oky.sh/gitadmin/autonomous-build-test
|
||||
- Settings → Webhooks
|
||||
|
||||
2. **Add Webhook:**
|
||||
- URL: `https://n8n.oky.sh/webhook/openhands-autonomous-build`
|
||||
- Trigger: Push events
|
||||
- HTTP Method: POST
|
||||
- Active: ✓
|
||||
- Save
|
||||
|
||||
3. **Test Webhook:**
|
||||
- Click "Test Delivery"
|
||||
- Should see 200 OK response
|
||||
|
||||
### STEP 3: Modify n8n Workflow Structure (60 min)
|
||||
|
||||
**Current Workflow (7 nodes):**
|
||||
```
|
||||
1. Gitea Webhook
|
||||
2. Extract Repo Info
|
||||
3. Start OpenHands Build
|
||||
4. Wait 10s
|
||||
5. Check Build Status
|
||||
6. Format Response
|
||||
7. Send Response
|
||||
```
|
||||
|
||||
**Target Workflow (11 nodes):**
|
||||
|
||||
#### Node 1: Gitea Webhook ✅ (Existing)
|
||||
**Configuration:**
|
||||
- Path: `/webhook/openhands-autonomous-build`
|
||||
- HTTP Method: POST
|
||||
- No changes needed
|
||||
|
||||
#### Node 2: Extract Repo Info ✅ (Modify Existing)
|
||||
**Current Code:**
|
||||
```javascript
|
||||
// Keep existing code, add repo info extraction
|
||||
const data = $json;
|
||||
|
||||
// Extract repository information
|
||||
const repoData = {
|
||||
repo_name: data.repository?.name || 'unknown',
|
||||
repo_full_name: data.repository?.full_name || 'unknown',
|
||||
owner: data.repository?.owner?.name || data.repository?.owner?.username || 'unknown',
|
||||
branch: data.ref?.replace('refs/heads/', '') || 'main',
|
||||
commit_sha: data.after || 'unknown',
|
||||
pusher: data.pusher?.name || 'unknown'
|
||||
};
|
||||
|
||||
return repoData;
|
||||
```
|
||||
|
||||
**Changes:** Add `repo_name`, `owner`, `branch`, `commit_sha` fields
|
||||
|
||||
#### Node 3: Initialize Retry Counter (NEW)
|
||||
**Type:** Code Node
|
||||
**Name:** "Initialize Retry Counter"
|
||||
|
||||
**Code:**
|
||||
```javascript
|
||||
// Initialize retry counter in workflow staticData
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
|
||||
// Initialize or increment retry count
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0);
|
||||
|
||||
// Preserve repo data from previous node
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...repoData,
|
||||
retry_count: 0,
|
||||
status: 'INITIALIZED',
|
||||
attempt: 1
|
||||
};
|
||||
```
|
||||
|
||||
**Configuration:**
|
||||
- Execute Once: False (important for retry loops)
|
||||
|
||||
#### Node 4: Start OpenHands Build (Modify Existing)
|
||||
**Type:** SSH Node
|
||||
**Name:** "Execute OpenHands Build"
|
||||
|
||||
**Configuration:**
|
||||
```
|
||||
Authentication: Private Key
|
||||
Host: localhost
|
||||
User: bam
|
||||
Private Key: /home/bam/.ssh/n8n_key
|
||||
Timeout: 300000 (5 minutes)
|
||||
```
|
||||
|
||||
**Command (JavaScript - Enhanced with feedback):**
|
||||
```javascript
|
||||
// Enhanced task with retry feedback
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
const buildDir = `/workspace/${repoData.repo_name}`;
|
||||
|
||||
// Base task
|
||||
let task = `Build and test the project at ${buildDir}.
|
||||
|
||||
Execute the following steps:
|
||||
1. cd ${buildDir}
|
||||
2. If package.json exists: npm install
|
||||
3. If build script exists: npm run build
|
||||
4. Report build status (success/failure)
|
||||
5. Capture and report any errors
|
||||
|
||||
Repository: ${repoData.repo_name}
|
||||
Branch: ${repoData.branch}
|
||||
Commit: ${repoData.commit_sha.substring(0, 8)}
|
||||
`;
|
||||
|
||||
// Add feedback if this is a retry
|
||||
if (retryCount > 0) {
|
||||
const previousOutput = $node["Check Build Results"].json;
|
||||
const errorDetails = previousOutput?.error_message || 'Unknown error';
|
||||
|
||||
task += `
|
||||
|
||||
PREVIOUS BUILD FAILED (Attempt ${retryCount}):
|
||||
Error Details:
|
||||
${errorDetails}
|
||||
|
||||
Please analyze the previous errors and fix them. Be thorough and ensure all issues are resolved before attempting the build again.
|
||||
|
||||
This is retry attempt #${retryCount + 1}. Please be extremely careful and fix ALL problems.`;
|
||||
}
|
||||
|
||||
// Execute via SDK wrapper
|
||||
return `sh /home/bam/openhands-sdk-wrapper-sh.sh "${task.replace(/"/g, '\\"')}"`;
|
||||
```
|
||||
|
||||
**Data Preservation (CRITICAL):**
|
||||
```javascript
|
||||
const sshOutput = $json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
return {
|
||||
...repoData, // Preserve repository data
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr,
|
||||
status: sshOutput.code === 0 ? 'SUCCESS' : 'FAILED',
|
||||
retry_count: retryCount,
|
||||
attempt: retryCount + 1
|
||||
};
|
||||
```
|
||||
|
||||
#### Node 5: Wait for Completion (Modify Existing)
|
||||
**Type:** Wait Node
|
||||
**Name:** "Wait for Build Completion"
|
||||
|
||||
**Configuration:**
|
||||
- Amount: 10
|
||||
- Unit: Seconds
|
||||
- No changes to existing configuration
|
||||
|
||||
#### Node 6: Check Build Results (Modify Existing)
|
||||
**Type:** Code Node
|
||||
**Name:** "Evaluate Build Results"
|
||||
|
||||
**Code:**
|
||||
```javascript
|
||||
// Get OpenHands output
|
||||
const openhandsOutput = $json;
|
||||
|
||||
// Determine success/failure
|
||||
const buildSuccess = openhandsOutput.code === 0;
|
||||
|
||||
// Collect errors if build failed
|
||||
let errorDetails = '';
|
||||
if (!buildSuccess) {
|
||||
// Prefer stderr, fallback to stdout
|
||||
errorDetails = openhandsOutput.stderr || openhandsOutput.stdout || 'Build failed with no error output';
|
||||
}
|
||||
|
||||
// Return structured results
|
||||
return {
|
||||
...openhandsOutput, // Preserve all data
|
||||
build_success: buildSuccess,
|
||||
error_details: errorDetails,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
```
|
||||
|
||||
#### Node 7: Decision: Build OK? (NEW)
|
||||
**Type:** IF Node
|
||||
**Name:** "Decision: Build Success?"
|
||||
|
||||
**Configuration:**
|
||||
```
|
||||
Condition: JSON
|
||||
Value 1: {{ $json.build_success }}
|
||||
Operation: Equal
|
||||
Value 2: true
|
||||
```
|
||||
|
||||
**True Path (YES):** → Node 8 (Update Gitea Success)
|
||||
**False Path (NO):** → Node 9 (Format Error Feedback)
|
||||
|
||||
#### Node 8: Update Gitea Success (NEW)
|
||||
**Type:** HTTP Request Node
|
||||
**Name:** "Update Gitea - Success"
|
||||
|
||||
**Configuration:**
|
||||
```
|
||||
Method: POST
|
||||
URL: https://git.oky.sh/api/v1/repos/{{ $node["Extract Repo Info"].json.owner }}/{{ $node["Extract Repo Info"].json.repo_name }}/statuses/{{ $node["Extract Repo Info"].json.commit_sha }}
|
||||
Headers:
|
||||
- X-Gitea-Token: {YOUR_GITEA_API_TOKEN}
|
||||
- Content-Type: application/json
|
||||
|
||||
Body:
|
||||
{
|
||||
"state": "success",
|
||||
"description": "✅ Build passed after {{ $node["Initialize Retry Counter"].json.retry_count }} attempt(s)",
|
||||
"context": "openhands/autonomous-build",
|
||||
"target_url": "https://n8n.oky.sh"
|
||||
}
|
||||
```
|
||||
|
||||
**Response Handling:**
|
||||
```javascript
|
||||
// Preserve data and add Gitea response
|
||||
const giteaResponse = $json;
|
||||
const previousData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...previousData,
|
||||
gitea_status: 'success',
|
||||
gitea_response: giteaResponse,
|
||||
final_status: 'SUCCESS',
|
||||
build_success: true
|
||||
};
|
||||
```
|
||||
|
||||
#### Node 9: Format Error Feedback (NEW)
|
||||
**Type:** Code Node
|
||||
**Name:** "Format Error for Retry"
|
||||
|
||||
**Code:**
|
||||
```javascript
|
||||
// Get build results and repo data
|
||||
const buildResults = $node["Check Build Results"].json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
// Format comprehensive error message
|
||||
const errorMsg = `Build failed with the following errors:
|
||||
|
||||
REPOSITORY: ${repoData.repo_name}
|
||||
BRANCH: ${repoData.branch}
|
||||
COMMIT: ${repoData.commit_sha.substring(0, 8)}
|
||||
ATTEMPT: ${retryCount + 1}/3
|
||||
|
||||
ERROR DETAILS:
|
||||
${buildResults.error_details}
|
||||
|
||||
BUILD OUTPUT (stderr):
|
||||
${buildResults.stderr || 'No stderr output'}
|
||||
|
||||
BUILD OUTPUT (stdout):
|
||||
${buildResults.stdout || 'No stdout output'}
|
||||
|
||||
NEXT STEPS:
|
||||
Please analyze these errors and fix all issues to ensure a successful build.
|
||||
Focus on:
|
||||
1. Dependency issues (npm install errors)
|
||||
2. Build script failures
|
||||
3. Code syntax errors
|
||||
4. Configuration problems
|
||||
|
||||
After fixing, the project should build successfully with: npm install && npm run build
|
||||
|
||||
This is attempt ${retryCount + 1} of 3. You have ${2 - retryCount} retry(s) remaining.`;
|
||||
```
|
||||
|
||||
**Return:**
|
||||
```javascript
|
||||
return {
|
||||
...repoData,
|
||||
...buildResults,
|
||||
status: 'FAILED',
|
||||
error_message: errorMsg,
|
||||
retry_count: retryCount,
|
||||
can_retry: retryCount < 2, // < 3 total attempts
|
||||
formatted_error: errorMsg
|
||||
};
|
||||
```
|
||||
|
||||
#### Node 10: Check Retry Count (NEW)
|
||||
**Type:** IF Node
|
||||
**Name:** "Can We Retry?"
|
||||
|
||||
**Configuration:**
|
||||
```
|
||||
Condition: JSON
|
||||
Value 1: {{ $json.can_retry }}
|
||||
Operation: Equal
|
||||
Value 2: true
|
||||
```
|
||||
|
||||
**True Path (YES - Can Retry):** → Loop back to Node 4
|
||||
**False Path (NO - Max Retries):** → Node 11 (Final Failure)
|
||||
|
||||
#### Node 11: Final Response (Modify Existing)
|
||||
**Type:** Code Node
|
||||
**Name:** "Final Response"
|
||||
|
||||
**Success Path Code:**
|
||||
```javascript
|
||||
// Format success response
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const retryCount = $node["Initialize Retry Counter"].json.retry_count;
|
||||
|
||||
const successResponse = {
|
||||
status: 'SUCCESS',
|
||||
repo: repoData.repo_name,
|
||||
branch: repoData.branch,
|
||||
commit: repoData.commit_sha.substring(0, 8),
|
||||
attempts: retryCount + 1,
|
||||
message: 'Build completed successfully ✅',
|
||||
timestamp: new Date().toISOString(),
|
||||
gitea_status: 'success'
|
||||
};
|
||||
|
||||
return successResponse;
|
||||
```
|
||||
|
||||
**Failure Path Code:**
|
||||
```javascript
|
||||
// Format failure response
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
const errorData = $node["Format Error for Retry"].json;
|
||||
|
||||
const failureResponse = {
|
||||
status: 'FAILED',
|
||||
repo: repoData.repo_name,
|
||||
branch: repoData.branch,
|
||||
commit: repoData.commit_sha.substring(0, 8),
|
||||
attempts: errorData.retry_count + 1,
|
||||
max_attempts: 3,
|
||||
message: 'Build failed after 3 attempts ❌',
|
||||
errors: errorData.error_details,
|
||||
timestamp: new Date().toISOString(),
|
||||
gitea_status: 'failure',
|
||||
next_steps: 'Please review the error messages and fix the issues manually before pushing again.'
|
||||
};
|
||||
|
||||
return failureResponse;
|
||||
```
|
||||
|
||||
**HTTP Response Node:**
|
||||
```javascript
|
||||
const response = $json;
|
||||
return [
|
||||
{
|
||||
statusCode: response.status === 'SUCCESS' ? 200 : 500,
|
||||
body: response
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 CONFIGURATION CHECKLIST
|
||||
|
||||
### Credentials Required
|
||||
|
||||
- [ ] **n8n API Key:** `/home/bam/.n8n_api_key` ✅
|
||||
- [ ] **SSH Key:** `/home/bam/.ssh/n8n_key` ✅
|
||||
- [ ] **OpenHands API Keys:** `/home/bam/openhands/.env` ✅
|
||||
- [ ] **Gitea API Token:** ⚠️ NEED TO GENERATE
|
||||
|
||||
### Generate Gitea API Token
|
||||
|
||||
```bash
|
||||
# Via Gitea API (or use UI)
|
||||
curl -X POST https://git.oky.sh/api/v1/users/gitadmin/tokens \
|
||||
-H "X-Gitea-Token: {ADMIN_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "n8n-autonomous-build",
|
||||
"scopes": ["repo", "admin:repo_hook"]
|
||||
}'
|
||||
|
||||
# OR via UI:
|
||||
# 1. Go to https://git.oky.sh/user/settings/applications
|
||||
# 2. Click "Generate Token"
|
||||
# 3. Name: n8n-autonomous-build
|
||||
# 4. Scopes: repo, admin:repo_hook
|
||||
# 5. Copy token (will look like: gho_xxxxxxxxxxxxxxxxx)
|
||||
```
|
||||
|
||||
Store token securely:
|
||||
```bash
|
||||
echo "GITEA_API_TOKEN=gho_xxxxxxxxxxxxxxxxx" > /home/bam/.gitea_token
|
||||
chmod 600 /home/bam/.gitea_token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 TESTING STRATEGY
|
||||
|
||||
### Test 1: Success Path (30 min)
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Create clean test repo
|
||||
git clone https://git.oky.sh/gitadmin/test-success.git
|
||||
cd test-success
|
||||
|
||||
# Create valid package.json
|
||||
cat > package.json << 'EOF'
|
||||
{
|
||||
"name": "test-success",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "echo 'Build successful'"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create simple build script
|
||||
cat > build.js << 'EOF'
|
||||
console.log('Build completed successfully!');
|
||||
process.exit(0);
|
||||
EOF
|
||||
|
||||
# Commit and push
|
||||
git add .
|
||||
git commit -m "Test successful build"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Expected Results:**
|
||||
1. Webhook triggered ✅
|
||||
2. Workflow executes ✅
|
||||
3. OpenHands builds successfully ✅
|
||||
4. Gitea status: "success" ✅
|
||||
5. Response: 200 OK ✅
|
||||
|
||||
**Success Criteria:**
|
||||
```json
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"attempts": 1,
|
||||
"gitea_status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 2: Retry Logic with Fixable Errors (45 min)
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Clone test repo
|
||||
git clone https://git.oky.sh/gitadmin/autonomous-build-test.git
|
||||
cd autonomous-build-test
|
||||
|
||||
# Fix the syntax error in build.js
|
||||
cat > build.js << 'EOF'
|
||||
// Fixed version - proper closing braces
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.send('Hello World!'); // Now properly closed
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Server running');
|
||||
});
|
||||
EOF
|
||||
|
||||
# Commit and push
|
||||
git add .
|
||||
git commit -m "Fix: Corrected syntax errors in build.js"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Expected Flow:**
|
||||
1. **1st Attempt:** Fails (syntax error)
|
||||
2. **2nd Attempt:** OpenHands receives feedback, fixes error
|
||||
3. **3rd Attempt:** Succeeds ✅
|
||||
|
||||
**Success Criteria:**
|
||||
```json
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"attempts": 3,
|
||||
"message": "Build completed successfully ✅",
|
||||
"gitea_status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 3: Max Retries with Persistent Errors (45 min)
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Force persistent error
|
||||
cat > build.js << 'EOF'
|
||||
// This will always fail
|
||||
console.error('Intentional error - will not fix');
|
||||
process.exit(1);
|
||||
EOF
|
||||
|
||||
git add .
|
||||
git commit -m "Test: Persistent error (should fail after 3 attempts)"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Expected Flow:**
|
||||
1. **1st Attempt:** Fails
|
||||
2. **2nd Attempt:** Fails
|
||||
3. **3rd Attempt:** Fails
|
||||
4. **Stops:** Max retries exceeded ❌
|
||||
|
||||
**Success Criteria:**
|
||||
```json
|
||||
{
|
||||
"status": "FAILED",
|
||||
"attempts": 3,
|
||||
"max_attempts": 3,
|
||||
"message": "Build failed after 3 attempts ❌",
|
||||
"gitea_status": "failure"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 4: Real Project Build (45 min)
|
||||
|
||||
**Setup:**
|
||||
Use actual MVP project:
|
||||
```bash
|
||||
# Clone real project
|
||||
git clone https://git.oky.sh/gitadmin/mvp-project.git
|
||||
cd mvp-project
|
||||
|
||||
# Make a small change
|
||||
echo "// Test change" >> README.md
|
||||
|
||||
# Commit and push
|
||||
git add .
|
||||
git commit -m "Test: Trigger autonomous build"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- OpenHands executes full build
|
||||
- Dependencies installed correctly
|
||||
- Build completes or fails with clear errors
|
||||
- Retry logic works if needed
|
||||
|
||||
---
|
||||
|
||||
## 🚨 TROUBLESHOOTING GUIDE
|
||||
|
||||
### Issue 1: Retry Count Always 0
|
||||
|
||||
**Symptom:** Workflow doesn't retry, always shows attempt 1
|
||||
|
||||
**Solution:** Check Node 3 configuration
|
||||
```javascript
|
||||
// MUST initialize staticData
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0) + 1;
|
||||
```
|
||||
|
||||
### Issue 2: Gitea Status Not Updating
|
||||
|
||||
**Symptom:** Commit status stays "pending" or doesn't appear
|
||||
|
||||
**Diagnosis:**
|
||||
```bash
|
||||
# Check token permissions
|
||||
curl -H "X-Gitea-Token: {YOUR_TOKEN}" \
|
||||
https://git.oky.sh/api/v1/user
|
||||
|
||||
# Should return user info
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Ensure token has "repo" scope
|
||||
2. Check URL format: `/api/v1/repos/{owner}/{repo}/statuses/{sha}`
|
||||
3. Verify commit_sha is correct (40 character SHA)
|
||||
|
||||
### Issue 3: Workflow Hangs After OpenHands
|
||||
|
||||
**Symptom:** Workflow stops at Node 4 or Node 5
|
||||
|
||||
**Solution:**
|
||||
1. **Check Wait Node:** Set to 10 seconds minimum
|
||||
2. **Check SSH Timeout:** Set to 300000ms (5 minutes)
|
||||
3. **Check SSH Authentication:** Test manually
|
||||
```bash
|
||||
ssh -i /home/bam/.ssh/n8n_key bam@localhost "echo 'SSH works'"
|
||||
```
|
||||
|
||||
### Issue 4: OpenHands Not Using Feedback
|
||||
|
||||
**Symptom:** Retry attempts show same errors
|
||||
|
||||
**Solution:** Check Node 4 command generation
|
||||
```javascript
|
||||
// Must include previous error in task
|
||||
if (retryCount > 0) {
|
||||
task += `
|
||||
|
||||
PREVIOUS BUILD FAILED:
|
||||
${errorDetails}`;
|
||||
}
|
||||
```
|
||||
|
||||
### Issue 5: Data Lost in Retry Loop
|
||||
|
||||
**Symptom:** Repository info missing on retry
|
||||
|
||||
**Solution:** Check data preservation in Node 4
|
||||
```javascript
|
||||
return {
|
||||
...repoData, // ← CRITICAL: Preserve repo data
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr,
|
||||
status: 'SUCCESS'
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 MONITORING & DEBUGGING
|
||||
|
||||
### Enable Workflow Debugging
|
||||
|
||||
**In n8n UI:**
|
||||
1. Open workflow → Toggle "Save Manual Executions"
|
||||
2. View execution history
|
||||
3. Check each node's input/output
|
||||
|
||||
### Key Metrics to Track
|
||||
|
||||
- **Success Rate:** % of builds that succeed
|
||||
- **Retry Efficiency:** Avg attempts per build
|
||||
- **Build Time:** Duration from push to completion
|
||||
- **Error Categories:** Type of failures
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Check OpenHands execution
|
||||
tail -f /tmp/openhands_execution_*.log
|
||||
|
||||
# Test SSH manually
|
||||
ssh -i /home/bam/.ssh/n8n_key bam@localhost \
|
||||
"sh /home/bam/openhands-sdk-wrapper-sh.sh 'Test task'"
|
||||
|
||||
# Check workflow status
|
||||
curl -H "X-N8N-API-KEY: {TOKEN}" \
|
||||
https://n8n.oky.sh/api/v1/workflows/j1MmXaRhDjvkRSLa
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⏱️ TIME-BOXED IMPLEMENTATION
|
||||
|
||||
### Session 1 (2 hours): Core Workflow
|
||||
- [ ] Step 1: Setup test repository (20 min)
|
||||
- [ ] Step 2: Configure Gitea webhook (15 min)
|
||||
- [ ] Step 3: Add nodes 3, 7, 8, 9, 10 (45 min)
|
||||
- [ ] Test success path (30 min)
|
||||
- [ ] Buffer for issues (10 min)
|
||||
|
||||
### Session 2 (2 hours): Retry Logic
|
||||
- [ ] Test failure path with fixable errors (45 min)
|
||||
- [ ] Test max retries (45 min)
|
||||
- [ ] Debug and fix issues (30 min)
|
||||
|
||||
### Session 3 (1 hour): Real Project & Documentation
|
||||
- [ ] Test with real project (45 min)
|
||||
- [ ] Document workflow (15 min)
|
||||
|
||||
---
|
||||
|
||||
## ✅ SUCCESS CRITERIA
|
||||
|
||||
**Must Have:**
|
||||
- [ ] End-to-end workflow completes (push → build → response)
|
||||
- [ ] OpenHands executes autonomously
|
||||
- [ ] Retry counter prevents infinite loops (max 3)
|
||||
- [ ] Error feedback improves retry attempts
|
||||
- [ ] Gitea commit status updates (success/failure)
|
||||
- [ ] Works with real projects
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
# Test workflow manually
|
||||
curl -X POST https://n8n.oky.sh/webhook/openhands-autonomous-build \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"repository": {"name": "test-repo", "full_name": "gitadmin/test-repo"},
|
||||
"ref": "refs/heads/main",
|
||||
"after": "abc123def456"
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"attempts": 1,
|
||||
"repo": "test-repo",
|
||||
"branch": "main",
|
||||
"gitea_status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 REFERENCE FILES
|
||||
|
||||
- **Phase 3 Plan:** `/home/bam/claude/mvp-factory/phase3.md`
|
||||
- **SDK Wrapper:** `/home/bam/openhands-sdk-wrapper-sh.sh`
|
||||
- **n8n API Docs:** `/home/bam/claude/mvp-factory/n8n-api.md`
|
||||
- **Phase 2 Learnings:** `/home/bam/claude/mvp-factory/phase2.md`
|
||||
- **Data Preservation:** `/home/bam/claude/mvp-factory/N8N_DATA_PRESERVATION_SOLUTION.md`
|
||||
|
||||
---
|
||||
|
||||
## 🎉 FINAL NOTES
|
||||
|
||||
**Key Reminders:**
|
||||
1. **Data Preservation:** Always use `$node["Node Name"].json` pattern
|
||||
2. **Retry Counter:** Initialize with `$workflow.staticData = $workflow.staticData || {}`
|
||||
3. **SSH Timeout:** Set to 5 minutes minimum
|
||||
4. **Wait Node:** 10 seconds between nodes
|
||||
5. **Gitea Token:** Must have "repo" scope for status updates
|
||||
|
||||
**Workflow ID:** `j1MmXaRhDjvkRSLa`
|
||||
**Target Webhook:** `https://n8n.oky.sh/webhook/openhands-autonomous-build`
|
||||
|
||||
---
|
||||
|
||||
**Implementation Ready ✅**
|
||||
**Estimated Total Time:** 4-5 hours
|
||||
**Can proceed immediately**
|
||||
|
|
@ -0,0 +1,344 @@
|
|||
# Phase 3 Implementation Summary
|
||||
|
||||
**Date Created:** 2025-12-02
|
||||
**Implementation Target:** Autonomous Build Test MVP
|
||||
**Estimated Duration:** 4-5 hours
|
||||
|
||||
---
|
||||
|
||||
## 📦 DOCUMENTATION PACKAGE CREATED
|
||||
|
||||
I've created a complete implementation package for Phase 3 with 5 comprehensive documents:
|
||||
|
||||
### 1. **phase3.md** (Original Plan - 12 KB)
|
||||
- Original detailed plan
|
||||
- Time estimates and timeline
|
||||
- Overview and goals
|
||||
- Test sequence strategy
|
||||
|
||||
### 2. **phase3-implementation-plan.md** (Main Guide - 21 KB) ⭐
|
||||
**Primary document for implementation**
|
||||
- Complete step-by-step guide
|
||||
- All 11 nodes detailed
|
||||
- Configuration instructions
|
||||
- Success criteria
|
||||
- Troubleshooting guide
|
||||
|
||||
### 3. **phase3-code-snippets.md** (Code Reference - 9.1 KB)
|
||||
**Ready-to-copy code for each node**
|
||||
- Node 3: Initialize Retry Counter code
|
||||
- Node 4: Execute OpenHands Build (enhanced)
|
||||
- Node 6: Evaluate Build Results code
|
||||
- Node 8: Update Gitea Success (HTTP config)
|
||||
- Node 9: Format Error for Retry code
|
||||
- Node 11: Final Response (both paths)
|
||||
- Decision node configurations
|
||||
- Quick test commands
|
||||
|
||||
### 4. **phase3-quickstart.md** (Quick Start - 5.6 KB)
|
||||
**5-minute setup guide**
|
||||
- Generate Gitea token
|
||||
- Create test repository
|
||||
- Configure webhook
|
||||
- Implementation checklist
|
||||
- Critical reminders
|
||||
|
||||
### 5. **phase3-workflow-diagram.md** (Visual Guide - 15 KB)
|
||||
**Complete workflow visualization**
|
||||
- ASCII diagram of 11-node flow
|
||||
- Data flow patterns
|
||||
- Retry flow details
|
||||
- Success/failure paths
|
||||
- Timeline and execution flow
|
||||
- Node configuration matrix
|
||||
|
||||
---
|
||||
|
||||
## 🎯 IMPLEMENTATION OVERVIEW
|
||||
|
||||
### Current State
|
||||
- ✅ **Workflow ID:** `j1MmXaRhDjvkRSLa` (7 nodes)
|
||||
- ✅ **n8n Instance:** https://n8n.oky.sh
|
||||
- ✅ **OpenHands SDK:** Working via SSH
|
||||
- ✅ **SSH Credentials:** Configured
|
||||
- ✅ **API Keys:** MiniMax & DeepSeek available
|
||||
|
||||
### Target State
|
||||
- **11-node autonomous CI/CD workflow**
|
||||
- **Retry logic:** Max 3 attempts
|
||||
- **Error feedback:** To OpenHands
|
||||
- **Gitea status:** Auto-updates
|
||||
- **Real project testing:** Functional
|
||||
|
||||
---
|
||||
|
||||
## 📋 STEP-BY-STEP APPROACH
|
||||
|
||||
### Phase A: Preparation (20 min)
|
||||
1. Generate Gitea API token (repo + admin:repo_hook scopes)
|
||||
2. Create test repository: `autonomous-build-test`
|
||||
3. Configure webhook: `/webhook/openhands-autonomous-build`
|
||||
|
||||
### Phase B: Add New Nodes (90 min)
|
||||
1. **Node 3:** Initialize Retry Counter (Code node)
|
||||
2. **Node 7:** Decision - Build OK? (IF node)
|
||||
3. **Node 8:** Update Gitea Success (HTTP node)
|
||||
4. **Node 9:** Format Error for Retry (Code node)
|
||||
5. **Node 10:** Check Retry Count (IF node)
|
||||
|
||||
### Phase C: Modify Existing Nodes (60 min)
|
||||
1. **Node 2:** Extract Repo Info (add fields)
|
||||
2. **Node 4:** OpenHands Build (enhance + preserve data)
|
||||
3. **Node 6:** Check Build Results (add success check)
|
||||
4. **Node 11:** Final Response (support both paths)
|
||||
|
||||
### Phase D: Test (90 min)
|
||||
1. Success path test
|
||||
2. Retry with fixable errors
|
||||
3. Max retries (3 attempts)
|
||||
4. Real project test
|
||||
|
||||
---
|
||||
|
||||
## 🔧 WORKFLOW ARCHITECTURE
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ [1] Webhook │ Receives Gitea push
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ [2] Extract │ Parse commit info
|
||||
│ Repo Info │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐ ┌──────────────────┐
|
||||
│ [3] Init │ │ [11] Final │
|
||||
│ Retry │ │ Response │
|
||||
└──────┬───────┘ └──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ [4] OpenHands│ Execute build
|
||||
│ Build │ (with error feedback)
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ [5] Wait │ 10 seconds
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ [6] Check │ Evaluate results
|
||||
│ Results │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ [7] Decision │ Build OK?
|
||||
│ Build OK? │
|
||||
└────┬──┬──────┘
|
||||
│ │
|
||||
│ ├─ YES → [8] Gitea Success → [11]
|
||||
│ │
|
||||
│ └─ NO → [9] Format Error
|
||||
│ ↓
|
||||
│ [10] Retry Check
|
||||
│ │
|
||||
│ ┌────┴────┐
|
||||
│ │ │
|
||||
│ ▼ ▼
|
||||
│ ┌────────┐ ┌───────┐
|
||||
│ │ Loop │ │ [11] │
|
||||
│ │ to [4] │ │Final │
|
||||
│ └────────┘ └───────┘
|
||||
│
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💾 KEY CODE PATTERNS
|
||||
|
||||
### 1. Data Preservation (Critical!)
|
||||
```javascript
|
||||
const sshOutput = $json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...repoData, // ← PRESERVE INPUT
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Retry Counter Initialization
|
||||
```javascript
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0) + 1;
|
||||
```
|
||||
|
||||
### 3. Error Feedback Loop
|
||||
```javascript
|
||||
if (retryCount > 0) {
|
||||
task += `
|
||||
|
||||
PREVIOUS BUILD FAILED:
|
||||
${errorDetails}`;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Gitea Status Update
|
||||
```javascript
|
||||
POST https://git.oky.sh/api/v1/repos/{owner}/{repo}/statuses/{sha}
|
||||
{
|
||||
"state": "success",
|
||||
"description": "✅ Build passed after 2 attempt(s)",
|
||||
"context": "openhands/autonomous-build"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 SUCCESS CRITERIA
|
||||
|
||||
### Must Have ✅
|
||||
- [ ] End-to-end workflow completes (push → build → response)
|
||||
- [ ] OpenHands executes autonomously
|
||||
- [ ] Retry counter prevents infinite loops (max 3)
|
||||
- [ ] Error feedback improves subsequent attempts
|
||||
- [ ] Gitea commit status updates (success/failure)
|
||||
- [ ] Works with real projects
|
||||
|
||||
### Validation Tests
|
||||
1. **Test Success Path:** Valid code builds in 1 attempt
|
||||
2. **Test Retry Logic:** Fixable errors resolve in 2-3 attempts
|
||||
3. **Test Max Retries:** Persistent errors fail after 3 attempts
|
||||
4. **Test Real Project:** Actual MVP project builds successfully
|
||||
|
||||
---
|
||||
|
||||
## 🧪 QUICK TEST COMMANDS
|
||||
|
||||
### Manual Workflow Trigger
|
||||
```bash
|
||||
curl -X POST https://n8n.oky.sh/webhook/openhands-autonomous-build \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"repository": {"name": "test-project", "full_name": "gitadmin/test-project"},
|
||||
"ref": "refs/heads/main",
|
||||
"after": "abc123def456789012345678901234567890abcd"
|
||||
}'
|
||||
```
|
||||
|
||||
### Create Test Repository
|
||||
```bash
|
||||
curl -X POST https://git.oky.sh/api/v1/user/repos \
|
||||
-H "X-Gitea-Token: {YOUR_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"autonomous-build-test"}'
|
||||
```
|
||||
|
||||
### Test SSH Connectivity
|
||||
```bash
|
||||
ssh -i /home/bam/.ssh/n8n_key bam@localhost \
|
||||
"sh /home/bam/openhands-sdk-wrapper-sh.sh 'Test connection'"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 CRITICAL WARNINGS
|
||||
|
||||
### ⚠️ Data Loss Prevention
|
||||
- SSH nodes **overwrite ALL data**
|
||||
- Must use `$node["Node Name"].json` pattern
|
||||
- Always preserve repo data: `...repoData`
|
||||
|
||||
### ⚠️ Retry Counter
|
||||
- Must initialize: `$workflow.staticData = $workflow.staticData || {}`
|
||||
- Increment: `$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0) + 1`
|
||||
- Check: `if (retryCount >= 3) return fail;`
|
||||
|
||||
### ⚠️ Gitea Token
|
||||
- Required for status updates
|
||||
- Must have scopes: `repo` + `admin:repo_hook`
|
||||
- Format: `gho_...` or `gsat_...`
|
||||
|
||||
### ⚠️ SSH Configuration
|
||||
- Host: `localhost`
|
||||
- User: `bam`
|
||||
- Key: `/home/bam/.ssh/n8n_key`
|
||||
- Timeout: `300000` (5 minutes)
|
||||
|
||||
---
|
||||
|
||||
## 📞 IMPLEMENTATION SEQUENCE
|
||||
|
||||
### Start Here ⭐
|
||||
1. **Read:** `phase3-implementation-plan.md` (complete guide)
|
||||
2. **Copy code from:** `phase3-code-snippets.md`
|
||||
3. **Reference:** `phase3-workflow-diagram.md` (visual guide)
|
||||
4. **Quick setup:** `phase3-quickstart.md` (5-min checklist)
|
||||
|
||||
### Use Todo List
|
||||
```bash
|
||||
# Progress tracking
|
||||
# Mark items as completed:
|
||||
TodoWrite --todos "[...]" # Update status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 FILE LOCATIONS
|
||||
|
||||
All documentation in: `/home/bam/claude/mvp-factory/`
|
||||
|
||||
```
|
||||
phase3.md (Original plan)
|
||||
phase3-implementation-plan.md (Main implementation guide) ⭐
|
||||
phase3-code-snippets.md (Copy-paste code)
|
||||
phase3-quickstart.md (Quick start)
|
||||
phase3-workflow-diagram.md (Visual diagram)
|
||||
phase3-implementation-summary.md (This file)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 READY TO IMPLEMENT
|
||||
|
||||
### Everything You Need ✅
|
||||
- ✅ Complete documentation (5 files, 62 KB)
|
||||
- ✅ Ready-to-copy code snippets
|
||||
- ✅ Visual workflow diagrams
|
||||
- ✅ Step-by-step instructions
|
||||
- ✅ Troubleshooting guide
|
||||
- ✅ Test commands
|
||||
- ✅ Success criteria checklist
|
||||
|
||||
### Next Steps
|
||||
1. **Read** `phase3-implementation-plan.md`
|
||||
2. **Generate** Gitea API token
|
||||
3. **Start** with Node 3 (Initialize Retry Counter)
|
||||
4. **Follow** code snippets from `phase3-code-snippets.md`
|
||||
5. **Test** using commands in `phase3-quickstart.md`
|
||||
|
||||
### Time Estimate
|
||||
- **Setup:** 30 minutes
|
||||
- **Implementation:** 2-3 hours
|
||||
- **Testing:** 1-2 hours
|
||||
- **Total:** 4-5 hours
|
||||
|
||||
---
|
||||
|
||||
**Status: Implementation Ready** 🚀
|
||||
|
||||
All documentation and code snippets are prepared and ready to use immediately.
|
||||
|
||||
---
|
||||
|
||||
*Implementation Summary - Created: 2025-12-02*
|
||||
*All Phase 3 documentation complete*
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
# Phase 3 Quick Start Guide
|
||||
|
||||
**Goal:** Transform 7-node workflow → 11-node autonomous CI/CD with retry logic
|
||||
**Time:** 4-5 hours
|
||||
**Workflow ID:** `j1MmXaRhDjvkRSLa`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 5-MINUTE SETUP
|
||||
|
||||
### 1. Get Gitea Token (Required for Status Updates)
|
||||
|
||||
```bash
|
||||
# UI Method (Easiest):
|
||||
# 1. Go to https://git.oky.sh/user/settings/applications
|
||||
# 2. Click "Generate Token"
|
||||
# 3. Name: n8n-autonomous-build
|
||||
# 4. Scopes: repo, admin:repo_hook
|
||||
# 5. Copy token (format: gho_...)
|
||||
```
|
||||
|
||||
### 2. Create Test Repository
|
||||
|
||||
```bash
|
||||
# Via API:
|
||||
curl -X POST https://git.oky.sh/api/v1/user/repos \
|
||||
-H "X-Gitea-Token: {YOUR_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"autonomous-build-test","description":"Phase 3 test repo"}'
|
||||
|
||||
# Or via UI:
|
||||
# https://git.oky.sh → + → New Repository
|
||||
```
|
||||
|
||||
### 3. Configure Webhook
|
||||
|
||||
1. Go to: `https://git.oky.sh/gitadmin/autonomous-build-test/settings/hooks`
|
||||
2. Add Webhook:
|
||||
- URL: `https://n8n.oky.sh/webhook/openhands-autonomous-build`
|
||||
- Trigger: Push events
|
||||
- Active: ✓
|
||||
|
||||
---
|
||||
|
||||
## 📋 IMPLEMENTATION CHECKLIST
|
||||
|
||||
### Phase A: Add New Nodes (90 min)
|
||||
|
||||
- [ ] **Node 3:** Initialize Retry Counter
|
||||
- Type: Code
|
||||
- Code: See `phase3-code-snippets.md` → "Node 3"
|
||||
|
||||
- [ ] **Node 7:** Decision - Build OK?
|
||||
- Type: IF
|
||||
- Condition: `$json.build_success == true`
|
||||
|
||||
- [ ] **Node 8:** Update Gitea Success
|
||||
- Type: HTTP
|
||||
- URL: `https://git.oky.sh/api/v1/repos/{owner}/{repo}/statuses/{sha}`
|
||||
- Token: `{YOUR_GITEA_API_TOKEN}`
|
||||
|
||||
- [ ] **Node 9:** Format Error for Retry
|
||||
- Type: Code
|
||||
- Code: See `phase3-code-snippets.md` → "Node 9"
|
||||
|
||||
- [ ] **Node 10:** Check Retry Count
|
||||
- Type: IF
|
||||
- Condition: `$json.can_retry == true`
|
||||
|
||||
### Phase B: Modify Existing Nodes (60 min)
|
||||
|
||||
- [ ] **Node 2:** Extract Repo Info
|
||||
- Add: `repo_name`, `owner`, `branch`, `commit_sha`
|
||||
|
||||
- [ ] **Node 4:** Execute OpenHands Build
|
||||
- Enhance command with error feedback
|
||||
- Add data preservation pattern
|
||||
|
||||
- [ ] **Node 6:** Check Build Results
|
||||
- Add: `build_success`, `error_details`
|
||||
|
||||
- [ ] **Node 11:** Final Response
|
||||
- Support both success AND failure paths
|
||||
|
||||
### Phase C: Test (90 min)
|
||||
|
||||
- [ ] Test 1: Success Path (30 min)
|
||||
- [ ] Test 2: Retry with Fixable Errors (30 min)
|
||||
- [ ] Test 3: Max Retries (3 attempts) (30 min)
|
||||
|
||||
---
|
||||
|
||||
## 📚 KEY RESOURCES
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `phase3-implementation-plan.md` | Complete implementation guide (11 nodes) |
|
||||
| `phase3-code-snippets.md` | Ready-to-copy code for each node |
|
||||
| `phase3-quickstart.md` | This file - quick start guide |
|
||||
| `phase3.md` | Original Phase 3 plan |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 NODES BREAKDOWN
|
||||
|
||||
### Current Workflow (7 nodes)
|
||||
```
|
||||
[1] Gitea Webhook
|
||||
[2] Extract Repo Info
|
||||
[3] Start OpenHands Build
|
||||
[4] Wait 10s
|
||||
[5] Check Build Status
|
||||
[6] Format Response
|
||||
[7] Send Response
|
||||
```
|
||||
|
||||
### Target Workflow (11 nodes)
|
||||
```
|
||||
[1] Gitea Webhook
|
||||
[2] Extract Repo Info (MODIFY)
|
||||
[3] Initialize Retry Counter (NEW)
|
||||
[4] Start OpenHands Build (MODIFY)
|
||||
[5] Wait 10s
|
||||
[6] Check Build Results (MODIFY)
|
||||
[7] Decision: Build OK? (NEW)
|
||||
├─ YES → [8] Update Gitea Success → [11] Response
|
||||
└─ NO → [9] Format Error Feedback
|
||||
↓
|
||||
[10] Check Retry Count
|
||||
├─ YES → Loop to [4]
|
||||
└─ NO → [11] Final Response
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ CRITICAL REMINDERS
|
||||
|
||||
### 1. Data Preservation Pattern
|
||||
**ALWAYS use this in SSH nodes:**
|
||||
```javascript
|
||||
const sshOutput = $json;
|
||||
const repoData = $node["Extract Repo Info"].json;
|
||||
|
||||
return {
|
||||
...repoData, // ← PRESERVE INPUT DATA
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Retry Counter Initialization
|
||||
**MUST initialize in Node 3:**
|
||||
```javascript
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0) + 1;
|
||||
```
|
||||
|
||||
### 3. SSH Node Configuration
|
||||
```
|
||||
Host: localhost
|
||||
User: bam
|
||||
Private Key: /home/bam/.ssh/n8n_key
|
||||
Timeout: 300000 (5 minutes)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 QUICK TESTS
|
||||
|
||||
### Test 1: Manual Workflow Trigger
|
||||
|
||||
```bash
|
||||
curl -X POST https://n8n.oky.sh/webhook/openhands-autonomous-build \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"repository": {
|
||||
"name": "test-project",
|
||||
"full_name": "gitadmin/test-project",
|
||||
"owner": {"name": "gitadmin", "username": "gitadmin"}
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"after": "abc123def456789012345678901234567890abcd"
|
||||
}'
|
||||
```
|
||||
|
||||
### Test 2: SSH Connectivity
|
||||
|
||||
```bash
|
||||
ssh -i /home/bam/.ssh/n8n_key bam@localhost \
|
||||
"sh /home/bam/openhands-sdk-wrapper-sh.sh 'Test connection'"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 SUCCESS CRITERIA
|
||||
|
||||
✅ **End-to-end completes:** Push → Build → Response
|
||||
✅ **Retry works:** Max 3 attempts, then stop
|
||||
✅ **Gitea status:** Updates to success/failure
|
||||
✅ **Error feedback:** OpenHands receives previous errors
|
||||
✅ **Real projects:** Works with actual MVP project
|
||||
|
||||
---
|
||||
|
||||
## 🆘 TROUBLESHOOTING
|
||||
|
||||
| Problem | Quick Fix |
|
||||
|---------|-----------|
|
||||
| Retry count always 0 | Initialize `$workflow.staticData` |
|
||||
| Gitea status not updating | Check token has "repo" scope |
|
||||
| Workflow hangs | Increase SSH timeout to 5 min |
|
||||
| Data lost in loop | Use `$node["Node Name"].json` pattern |
|
||||
| Same errors on retry | Include error in task string |
|
||||
|
||||
---
|
||||
|
||||
## 📞 CURRENT STATUS
|
||||
|
||||
- ✅ Phase 2 Complete
|
||||
- ✅ Workflow ID: `j1MmXaRhDjvkRSLa`
|
||||
- ✅ OpenHands SDK: Working
|
||||
- ✅ n8n + Gitea: Configured
|
||||
- ⏳ Phase 3: Ready to implement
|
||||
|
||||
---
|
||||
|
||||
## 🎯 NEXT STEPS
|
||||
|
||||
1. **Now:** Read `phase3-implementation-plan.md`
|
||||
2. **Then:** Generate Gitea token
|
||||
3. **Then:** Start with Node 3 (Initialize Retry Counter)
|
||||
4. **Follow:** `phase3-code-snippets.md` for exact code
|
||||
|
||||
**Total Time:** 4-5 hours
|
||||
**Can start immediately! 🚀**
|
||||
|
||||
---
|
||||
|
||||
*Quick Start Guide - Last Updated: 2025-12-02*
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,267 @@
|
|||
# Phase 3 Workflow Diagram
|
||||
|
||||
## Current Workflow (7 Nodes) → Target Workflow (11 Nodes)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 3: AUTONOMOUS BUILD TEST │
|
||||
│ Workflow ID: j1MmXaRhDjvkRSLa │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌────────────────┐
|
||||
│ [1] Gitea │ Webhook: /webhook/openhands-autonomous-build
|
||||
│ Webhook │ Trigger: Push events
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [2] Extract │ Code Node
|
||||
│ Repo Info │ Extract: repo_name, owner, branch, commit_sha
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [3] Initialize │ Code Node ★ NEW
|
||||
│ Retry Count │ Initialize: $workflow.staticData.retry_count = 0
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [4] OpenHands │ SSH Node ★ MODIFIED
|
||||
│ Build │ - Enhanced task with error feedback
|
||||
│ - Data preservation pattern
|
||||
│ - Retry logic on loop back
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [5] Wait │ Wait Node (10 seconds)
|
||||
│ 10s │
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [6] Check │ Code Node ★ MODIFIED
|
||||
│ Build │ Add: build_success, error_details
|
||||
│ Results │
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [7] Decision │ IF Node ★ NEW
|
||||
│ Build OK? │ Condition: build_success == true
|
||||
└───────┬────────┘
|
||||
│
|
||||
├──────────────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌───────────────┐ ┌──────────────────┐
|
||||
│ [8] Update │ │ [9] Format Error│ Code Node ★ NEW
|
||||
│ Gitea │ │ for Retry │ Format: error_message
|
||||
│ Success │ │ │
|
||||
└───────┬───────┘ └────────┬─────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌──────────────────┐
|
||||
│ │ [10] Check Retry│ IF Node ★ NEW
|
||||
│ │ Count │ Condition: can_retry == true
|
||||
│ └───────┬────────┘
|
||||
│ │
|
||||
│ ┌───────┴────────┐
|
||||
│ │ │
|
||||
│ ▼ ▼
|
||||
│ ┌────────────────┐ ┌──────────────────┐
|
||||
│ │ Loop back to │ │ [11] Final │ Code Node
|
||||
│ │ Node 4 │ │ Response │ ★ MODIFIED
|
||||
│ └────────────────┘ │ (Failure) │
|
||||
│ └────────┬─────────┘
|
||||
│ │
|
||||
└────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ [12] HTTP │ Respond to Webhook
|
||||
│ Response │ Status: 200/500
|
||||
└────────────────┘
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
DATA FLOW PATTERNS
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
[2] Extract Repo Info ───┐
|
||||
│ Output: {
|
||||
[3] Initialize Retry ────┤ repo_name, owner, branch,
|
||||
│ commit_sha, retry_count
|
||||
[4] OpenHands ───────────┤ } ↓
|
||||
│
|
||||
[4] preserves data ──────┼──► return {
|
||||
│ ...repoData, ← PRESERVE
|
||||
│ code, stdout,
|
||||
│ stderr, status
|
||||
[6] Check Results ───────┤ }
|
||||
│ ↓
|
||||
│
|
||||
[7] Decision ────────────┼──► build_success? → true/false
|
||||
│
|
||||
[8] Update Gitea ────────┤ On success → POST to Gitea API
|
||||
│
|
||||
[9] Format Error ────────┤ On failure → Format comprehensive error
|
||||
│
|
||||
[10] Retry Check ────────┤ can_retry? → true/false
|
||||
│
|
||||
[4] Loop back ───────────┤ If true → Back to OpenHands with feedback
|
||||
│ If false → Final failure
|
||||
│
|
||||
[11] Final Response ─────┴──► SUCCESS or FAILED with details
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
RETRY FLOW DETAIL
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Attempt 1:
|
||||
[3] retry_count = 0 → [4] OpenHands (first attempt) → [6] Check → [7] FAIL
|
||||
→ [9] Format Error → [10] Check: can_retry? YES (0 < 2) → Loop to [4]
|
||||
|
||||
Attempt 2:
|
||||
[3] retry_count = 1 → [4] OpenHands (with error feedback) → [6] Check → [7] FAIL
|
||||
→ [9] Format Error → [10] Check: can_retry? YES (1 < 2) → Loop to [4]
|
||||
|
||||
Attempt 3:
|
||||
[3] retry_count = 2 → [4] OpenHands (with error feedback) → [6] Check → [7] FAIL
|
||||
→ [9] Format Error → [10] Check: can_retry? NO (2 ≮ 2) → [11] Final Failure
|
||||
|
||||
Stop: Max retries (3) exceeded
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
SUCCESS FLOW
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Attempt 1 (Success):
|
||||
[3] retry_count = 0 → [4] OpenHands (first attempt) → [6] Check → [7] SUCCESS
|
||||
→ [8] Update Gitea → [11] Final Response (Success)
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
KEY IMPLEMENTATION NOTES
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
⚠️ CRITICAL: Data Preservation Pattern
|
||||
In Node 4 (SSH), ALWAYS preserve previous node data:
|
||||
```
|
||||
return {
|
||||
...repoData, // ← This line is CRITICAL
|
||||
code: sshOutput.code,
|
||||
stdout: sshOutput.stdout,
|
||||
stderr: sshOutput.stderr
|
||||
};
|
||||
```
|
||||
|
||||
⚠️ CRITICAL: Retry Counter Initialization
|
||||
In Node 3, MUST initialize staticData:
|
||||
```
|
||||
$workflow.staticData = $workflow.staticData || {};
|
||||
$workflow.staticData.retry_count = ($workflow.staticData.retry_count || 0) + 1;
|
||||
```
|
||||
|
||||
⚠️ CRITICAL: Error Feedback Loop
|
||||
In Node 4, include previous errors in task:
|
||||
```
|
||||
if (retryCount > 0) {
|
||||
task += `PREVIOUS BUILD FAILED:\n${errorDetails}`;
|
||||
}
|
||||
```
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
NODE CONFIGURATIONS
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Node Type Matrix:
|
||||
|
||||
┌──────┬─────────────────┬──────────────────────────────────────────────┐
|
||||
│ Node │ Type │ Key Configuration │
|
||||
├──────┼─────────────────┼──────────────────────────────────────────────┤
|
||||
│ 1 │ Webhook │ Path: /webhook/openhands-autonomous-build │
|
||||
│ 2 │ Code │ Extract repo data │
|
||||
│ 3 │ Code │ Initialize $workflow.staticData.retry_count │
|
||||
│ 4 │ SSH │ Host: localhost, Timeout: 300000ms │
|
||||
│ 5 │ Wait │ 10 seconds │
|
||||
│ 6 │ Code │ Evaluate build_success │
|
||||
│ 7 │ IF │ Condition: build_success == true │
|
||||
│ 8 │ HTTP │ POST Gitea API │
|
||||
│ 9 │ Code │ Format error with feedback │
|
||||
│ 10 │ IF │ Condition: can_retry == true │
|
||||
│ 11 │ Code │ Final SUCCESS/FAILED response │
|
||||
│ 12 │ Respond to Web │ Return HTTP 200/500 │
|
||||
└──────┴─────────────────┴──────────────────────────────────────────────┘
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
GITEA STATUS UPDATES
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Success Path (Node 8):
|
||||
POST https://git.oky.sh/api/v1/repos/{owner}/{repo}/statuses/{sha}
|
||||
Body: {
|
||||
"state": "success",
|
||||
"description": "✅ Build passed after {retry_count} attempt(s)",
|
||||
"context": "openhands/autonomous-build"
|
||||
}
|
||||
|
||||
Failure Path (Node 11):
|
||||
POST https://git.oky.sh/api/v1/repos/{owner}/{repo}/statuses/{sha}
|
||||
Body: {
|
||||
"state": "failure",
|
||||
"description": "❌ Build failed after 3 attempts",
|
||||
"context": "openhands/autonomous-build"
|
||||
}
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
EXECUTION TIMELINE
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Success (No Retry):
|
||||
T+0s → Webhook received
|
||||
T+5s → OpenHands starts build
|
||||
T+15s → Build complete, result checked
|
||||
T+16s → Gitea status updated
|
||||
T+17s → Response sent
|
||||
|
||||
Success (After 2 Retries):
|
||||
T+0s → Webhook received
|
||||
T+5s → 1st OpenHands attempt
|
||||
T+15s → 1st failure, formatted
|
||||
T+20s → 2nd OpenHands attempt (with feedback)
|
||||
T+30s → 2nd failure, formatted
|
||||
T+35s → 3rd OpenHands attempt (with feedback)
|
||||
T+45s → 3rd success
|
||||
T+46s → Gitea status updated
|
||||
T+47s → Response sent
|
||||
|
||||
Failure (Max Retries):
|
||||
T+0s → Webhook received
|
||||
T+5s → 1st OpenHands attempt
|
||||
T+15s → 1st failure
|
||||
T+20s → 2nd OpenHands attempt
|
||||
T+30s → 2nd failure
|
||||
T+35s → 3rd OpenHands attempt
|
||||
T+45s → 3rd failure
|
||||
T+46s → Gitea status updated (failure)
|
||||
T+47s → Response sent (max retries exceeded)
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
FILE REFERENCES
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
📄 Documentation:
|
||||
- phase3.md (Original plan)
|
||||
- phase3-implementation-plan.md (Detailed guide)
|
||||
- phase3-code-snippets.md (Ready-to-copy code)
|
||||
- phase3-quickstart.md (Quick start)
|
||||
|
||||
🔧 Configuration:
|
||||
- n8n API Key: /home/bam/.n8n_api_key
|
||||
- SSH Key: /home/bam/.ssh/n8n_key
|
||||
- OpenHands: /home/bam/openhands-sdk-wrapper-sh.sh
|
||||
|
||||
🧪 Testing:
|
||||
- Test repo: autonomous-build-test
|
||||
- Webhook: /webhook/openhands-autonomous-build
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
# AUTONOMOUS BUILD MISSION: OKYSH Agency Website v2
|
||||
|
||||
You are an autonomous agent with a critical mission: build a production-ready Vue.js website through iterative testing and self-correction.
|
||||
|
||||
## 🎯 PROJECT REQUIREMENTS
|
||||
|
||||
**Website:** OKYSH - AI Development Agency
|
||||
**Tech Stack:** Vue 3, Vite, TailwindCSS, GSAP animations
|
||||
**Sections:** Hero, Services, About, Tech Stack, Portfolio, Contact Form, Footer
|
||||
|
||||
## 🔄 AUTONOMOUS WORKFLOW - FOLLOW STRICTLY
|
||||
|
||||
### ⚙️ ITERATION TRACKING
|
||||
Before starting, create a file: `build-log.md` to track your progress.
|
||||
After EACH phase, append to this file:
|
||||
```
|
||||
## Iteration X - [Phase Name]
|
||||
Status: [Success/Failed]
|
||||
Errors: [list if any]
|
||||
Actions taken: [what you did]
|
||||
Next step: [what's next]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📦 PHASE 1: INITIAL SETUP
|
||||
|
||||
**Tasks:**
|
||||
1. Create project structure
|
||||
2. Install dependencies with `package.json` that includes:
|
||||
- vue@^3.4.0
|
||||
- vite@^5.0.0
|
||||
- tailwindcss@^3.4.0
|
||||
- @vitejs/plugin-vue
|
||||
- autoprefixer, postcss
|
||||
3. Create `vite.config.js` with:
|
||||
```js
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 3002,
|
||||
allowedHosts: 'all'
|
||||
}
|
||||
```
|
||||
4. Create `tailwind.config.js` with COMPLETE color palette (primary, accent, dark)
|
||||
- **CRITICAL:** Include ALL shades 50-950 for primary color
|
||||
- primary-400 MUST exist
|
||||
5. Setup basic Vue app structure
|
||||
|
||||
**Self-Check:**
|
||||
```bash
|
||||
ls -la # Verify all files created
|
||||
cat tailwind.config.js # Verify colors include 400 shade
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] All config files exist
|
||||
- [ ] package.json valid
|
||||
- [ ] tailwind.config.js has primary-50 through primary-950
|
||||
|
||||
**Log your progress to build-log.md before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### 🏗️ PHASE 2: BUILD VALIDATION LOOP
|
||||
|
||||
**DO NOT PROCEED UNTIL BUILD SUCCEEDS**
|
||||
|
||||
**Tasks:**
|
||||
1. Run: `npm install`
|
||||
2. Capture output and check for errors
|
||||
3. If install fails:
|
||||
- Read error message carefully
|
||||
- Identify the issue (version conflict? missing dep?)
|
||||
- Fix package.json
|
||||
- GO BACK TO STEP 1
|
||||
4. Run: `npm run build`
|
||||
5. Capture build output
|
||||
6. If build fails:
|
||||
- Read FULL error message
|
||||
- Common issues:
|
||||
* Missing Tailwind colors (bg-primary-XXX not defined)
|
||||
* Import errors (wrong paths)
|
||||
* Syntax errors
|
||||
- Fix the SPECIFIC issue mentioned
|
||||
- GO BACK TO STEP 1
|
||||
|
||||
**Self-Check Commands:**
|
||||
```bash
|
||||
npm install 2>&1 | tee install.log
|
||||
echo "Install exit code: $?"
|
||||
|
||||
npm run build 2>&1 | tee build.log
|
||||
echo "Build exit code: $?"
|
||||
|
||||
# Check if dist/ was created
|
||||
ls -la dist/
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] npm install exit code = 0
|
||||
- [ ] npm run build exit code = 0
|
||||
- [ ] dist/ directory exists with index.html
|
||||
|
||||
**MAXIMUM 5 ATTEMPTS:** If still failing after 5 tries, STOP and report:
|
||||
```
|
||||
ESCALATION NEEDED: Build failing after 5 attempts
|
||||
Last error: [paste error]
|
||||
Attempts made: [list what you tried]
|
||||
```
|
||||
|
||||
**Log your progress before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### 🚀 PHASE 3: DEV SERVER VALIDATION
|
||||
|
||||
**Tasks:**
|
||||
1. Start dev server in background:
|
||||
```bash
|
||||
npm run dev > dev-server.log 2>&1 &
|
||||
DEV_PID=$!
|
||||
echo $DEV_PID > dev-server.pid
|
||||
```
|
||||
2. Wait 15 seconds for startup
|
||||
3. Check if server is running:
|
||||
```bash
|
||||
sleep 15
|
||||
curl -s -o /dev/null -w "%{http_code}" http://localhost:3002
|
||||
```
|
||||
4. If curl returns 000 or fails:
|
||||
- Read dev-server.log for errors
|
||||
- Kill process: `kill $(cat dev-server.pid)`
|
||||
- Fix the issue
|
||||
- GO BACK TO PHASE 2 (rebuild might be needed)
|
||||
5. If curl returns 200:
|
||||
- Proceed to next phase
|
||||
|
||||
**Self-Check:**
|
||||
```bash
|
||||
# Is port listening?
|
||||
netstat -tlnp | grep 3002
|
||||
|
||||
# Can we reach it?
|
||||
curl -I http://localhost:3002
|
||||
|
||||
# Any errors in log?
|
||||
tail -20 dev-server.log
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] Port 3002 is listening
|
||||
- [ ] curl returns HTTP 200
|
||||
- [ ] No error messages in dev-server.log
|
||||
|
||||
**MAXIMUM 3 ATTEMPTS**
|
||||
|
||||
**Log your progress before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### 🌐 PHASE 4: BASIC CONTENT VALIDATION
|
||||
|
||||
**Tasks:**
|
||||
1. Fetch homepage HTML:
|
||||
```bash
|
||||
curl -s http://localhost:3002 > homepage.html
|
||||
```
|
||||
2. Check if content exists:
|
||||
```bash
|
||||
# Should have substantial content
|
||||
wc -c homepage.html # Should be > 1000 bytes
|
||||
|
||||
# Should have Vue app mount
|
||||
grep 'id="app"' homepage.html
|
||||
|
||||
# Should load Vue
|
||||
grep -i "vue" homepage.html
|
||||
```
|
||||
3. If homepage is empty or too small:
|
||||
- Check browser console errors (you'll need to simulate this)
|
||||
- Likely issues:
|
||||
* Vue not mounting
|
||||
* JavaScript errors
|
||||
* Missing components
|
||||
- Fix and GO BACK TO PHASE 2
|
||||
|
||||
**Self-Check:**
|
||||
```bash
|
||||
echo "Homepage size: $(wc -c < homepage.html) bytes"
|
||||
echo "Contains #app div: $(grep -c 'id="app"' homepage.html)"
|
||||
echo "Vue referenced: $(grep -ic vue homepage.html)"
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] homepage.html > 1000 bytes
|
||||
- [ ] Contains id="app"
|
||||
- [ ] References Vue
|
||||
|
||||
**Log your progress before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### ✅ PHASE 5: COMPONENT VALIDATION
|
||||
|
||||
**Tasks:**
|
||||
1. Verify all required components exist:
|
||||
```bash
|
||||
ls src/components/Navigation.vue
|
||||
ls src/components/Hero.vue
|
||||
ls src/components/Services.vue
|
||||
ls src/components/AboutUs.vue
|
||||
ls src/components/TechStack.vue
|
||||
ls src/components/Portfolio.vue
|
||||
ls src/components/ContactForm.vue
|
||||
ls src/components/Footer.vue
|
||||
```
|
||||
2. Check each component for common errors:
|
||||
```bash
|
||||
# Check for syntax errors
|
||||
for file in src/components/*.vue; do
|
||||
echo "Checking $file"
|
||||
# Look for unclosed tags, etc
|
||||
grep -c '<template>' "$file"
|
||||
grep -c '</template>' "$file"
|
||||
done
|
||||
```
|
||||
3. If any component missing or broken:
|
||||
- Create or fix it
|
||||
- Ensure proper Vue 3 syntax
|
||||
- GO BACK TO PHASE 2 (rebuild)
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] All 8 components exist
|
||||
- [ ] Each has matching open/close tags
|
||||
- [ ] No obvious syntax errors
|
||||
|
||||
**Log your progress before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### 🎨 PHASE 6: STYLING VALIDATION
|
||||
|
||||
**Tasks:**
|
||||
1. Check if Tailwind is working:
|
||||
```bash
|
||||
# Inspect generated CSS
|
||||
curl -s http://localhost:3002/src/style.css | head -50
|
||||
```
|
||||
2. Common Tailwind issues:
|
||||
- Colors not defined (bg-primary-XXX)
|
||||
- @apply with undefined classes
|
||||
- PostCSS not processing
|
||||
3. If styling broken:
|
||||
- Fix tailwind.config.js
|
||||
- Fix CSS files
|
||||
- GO BACK TO PHASE 2
|
||||
|
||||
**Self-Check:**
|
||||
```bash
|
||||
# Check tailwind.config.js has all colors
|
||||
grep -A 20 "primary:" tailwind.config.js
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- [ ] Tailwind colors fully defined
|
||||
- [ ] CSS loads without errors
|
||||
- [ ] No PostCSS warnings
|
||||
|
||||
**Log your progress before proceeding**
|
||||
|
||||
---
|
||||
|
||||
### 📊 PHASE 7: FINAL CHECKLIST
|
||||
|
||||
**Before declaring success, verify:**
|
||||
```bash
|
||||
# 1. Clean build
|
||||
npm run build && echo "✅ Build: PASS" || echo "❌ Build: FAIL"
|
||||
|
||||
# 2. Dev server runs
|
||||
pkill -f "vite" # Kill old server
|
||||
npm run dev > /tmp/vite.log 2>&1 &
|
||||
sleep 10
|
||||
curl -s http://localhost:3002 > /dev/null && echo "✅ Server: PASS" || echo "❌ Server: FAIL"
|
||||
|
||||
# 3. Content exists
|
||||
CONTENT_SIZE=$(curl -s http://localhost:3002 | wc -c)
|
||||
[ $CONTENT_SIZE -gt 1000 ] && echo "✅ Content: PASS" || echo "❌ Content: FAIL"
|
||||
|
||||
# 4. All components exist
|
||||
COMPONENTS=$(ls src/components/*.vue 2>/dev/null | wc -l)
|
||||
[ $COMPONENTS -eq 8 ] && echo "✅ Components: PASS" || echo "❌ Components: FAIL"
|
||||
|
||||
# 5. Configs valid
|
||||
[ -f vite.config.js ] && echo "✅ Vite config: PASS" || echo "❌ Vite config: FAIL"
|
||||
[ -f tailwind.config.js ] && echo "✅ Tailwind config: PASS" || echo "❌ Tailwind config: FAIL"
|
||||
```
|
||||
|
||||
**ALL MUST PASS**
|
||||
|
||||
---
|
||||
|
||||
### 📝 PHASE 8: FINAL REPORT
|
||||
|
||||
Create `DEPLOYMENT_READY.md` with:
|
||||
```markdown
|
||||
# OKYSH Website - Autonomous Build Report
|
||||
|
||||
## Build Status: [SUCCESS/FAILED]
|
||||
|
||||
## Iterations Completed: X
|
||||
|
||||
## Phase Results:
|
||||
- Phase 1 (Setup): [✅/❌]
|
||||
- Phase 2 (Build): [✅/❌] - X attempts
|
||||
- Phase 3 (Dev Server): [✅/❌] - X attempts
|
||||
- Phase 4 (Content): [✅/❌]
|
||||
- Phase 5 (Components): [✅/❌]
|
||||
- Phase 6 (Styling): [✅/❌]
|
||||
- Phase 7 (Final Check): [✅/❌]
|
||||
|
||||
## Issues Encountered:
|
||||
1. [Issue 1 and how you fixed it]
|
||||
2. [Issue 2 and how you fixed it]
|
||||
|
||||
## Final Checklist:
|
||||
- [ ] npm run build: SUCCESS
|
||||
- [ ] npm run dev: RUNNING on port 3002
|
||||
- [ ] Homepage size: XXX bytes
|
||||
- [ ] All 8 components exist
|
||||
- [ ] No console errors
|
||||
- [ ] Tailwind working
|
||||
|
||||
## Ready for Deployment: [YES/NO]
|
||||
|
||||
## Access:
|
||||
- Dev Server: http://localhost:3002
|
||||
- Build Output: ./dist/
|
||||
|
||||
## Next Steps:
|
||||
[What human should do next]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 CRITICAL RULES
|
||||
|
||||
1. **NEVER skip a phase** - each builds on the previous
|
||||
2. **ALWAYS check exit codes** - don't assume success
|
||||
3. **READ error messages COMPLETELY** - don't guess
|
||||
4. **LOG after each phase** - maintain build-log.md
|
||||
5. **STOP after max attempts** - don't infinite loop
|
||||
6. **CREATE files for debugging** - save logs, outputs
|
||||
7. **TEST before proceeding** - verify each phase works
|
||||
|
||||
## 🎯 SUCCESS DEFINITION
|
||||
|
||||
You have succeeded when:
|
||||
- ✅ All phases completed
|
||||
- ✅ DEPLOYMENT_READY.md shows all green checkmarks
|
||||
- ✅ Dev server accessible at http://localhost:3002
|
||||
- ✅ Website displays all sections
|
||||
- ✅ No errors in any logs
|
||||
|
||||
## 🚫 FAILURE DEFINITION
|
||||
|
||||
Stop and report if:
|
||||
- ❌ Any phase fails after max attempts
|
||||
- ❌ Build errors can't be resolved
|
||||
- ❌ Dev server won't start after 3 tries
|
||||
- ❌ You're repeating the same fix (stuck in loop)
|
||||
|
||||
---
|
||||
|
||||
## 🏁 BEGIN NOW
|
||||
|
||||
Start with Phase 1. Create build-log.md as your first action.
|
||||
Track everything. Test thoroughly. Be autonomous but disciplined.
|
||||
|
||||
Your success is measured by producing a working website, not by speed.
|
||||
|
||||
GO!
|
||||
Loading…
Reference in New Issue