399 lines
9.0 KiB
Markdown
399 lines
9.0 KiB
Markdown
# 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! 🚀**
|