From b6c4a7f75e8c5aa8f030f0477a562efa8fc654ba Mon Sep 17 00:00:00 2001 From: Yinghao Fan Date: Fri, 31 Oct 2025 02:06:20 +0800 Subject: [PATCH 1/4] fix: Correct error handling in decision parsing Changes: - Updated error handling in `GetFullDecision` and `parseFullDecisionResponse` functions to return the decision object even when an error occurs, improving the clarity of error messages. This ensures that the decision object is consistently returned, allowing for better debugging and handling of errors in the decision-making process. --- decision/engine.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/decision/engine.go b/decision/engine.go index 76bcffca..97181572 100644 --- a/decision/engine.go +++ b/decision/engine.go @@ -109,7 +109,7 @@ func GetFullDecision(ctx *Context, mcpClient *mcp.Client) (*FullDecision, error) // 4. 解析AI响应 decision, err := parseFullDecisionResponse(aiResponse, ctx.Account.TotalEquity, ctx.BTCETHLeverage, ctx.AltcoinLeverage) if err != nil { - return nil, fmt.Errorf("解析AI响应失败: %w", err) + return decision, fmt.Errorf("解析AI响应失败: %w", err) } decision.Timestamp = time.Now() @@ -427,7 +427,7 @@ func parseFullDecisionResponse(aiResponse string, accountEquity float64, btcEthL return &FullDecision{ CoTTrace: cotTrace, Decisions: []Decision{}, - }, fmt.Errorf("提取决策失败: %w\n\n=== AI思维链分析 ===\n%s", err, cotTrace) + }, fmt.Errorf("提取决策失败: %w", err) } // 3. 验证决策 @@ -435,7 +435,7 @@ func parseFullDecisionResponse(aiResponse string, accountEquity float64, btcEthL return &FullDecision{ CoTTrace: cotTrace, Decisions: decisions, - }, fmt.Errorf("决策验证失败: %w\n\n=== AI思维链分析 ===\n%s", err, cotTrace) + }, fmt.Errorf("决策验证失败: %w", err) } return &FullDecision{ From 9a604f9b27cc8ac5b50d4e6c01ed80bc9de9a097 Mon Sep 17 00:00:00 2001 From: zbhan Date: Sat, 1 Nov 2025 18:25:44 -0400 Subject: [PATCH 2/4] feat: pr validation --- .github/labeler.yml | 127 +++++ .github/labels.yml | 180 +++++++ .github/workflows/pr-checks-advisory.yml | 331 ++++++++++++ .github/workflows/pr-checks.yml | 237 +++++++++ CONTRIBUTING.md | 481 ++++++++++++++++++ docs/community/HOW_TO_MIGRATE_YOUR_PR.md | 272 ++++++++++ .../community/HOW_TO_MIGRATE_YOUR_PR.zh-CN.md | 272 ++++++++++ docs/community/MIGRATION_ANNOUNCEMENT.md | 358 +++++++++++++ .../community/MIGRATION_ANNOUNCEMENT.zh-CN.md | 358 +++++++++++++ docs/community/PR_COMMENT_TEMPLATE.md | 173 +++++++ docs/community/README.md | 14 + docs/i18n/zh-CN/CONTRIBUTING.md | 481 ++++++++++++++++++ docs/maintainers/PROJECT_MANAGEMENT.md | 398 +++++++++++++++ docs/maintainers/PROJECT_MANAGEMENT.zh-CN.md | 398 +++++++++++++++ docs/maintainers/PR_REVIEW_GUIDE.md | 458 +++++++++++++++++ docs/maintainers/PR_REVIEW_GUIDE.zh-CN.md | 457 +++++++++++++++++ docs/maintainers/README.md | 51 ++ docs/maintainers/README.zh-CN.md | 51 ++ docs/maintainers/SETUP_GUIDE.md | 381 ++++++++++++++ docs/maintainers/SETUP_GUIDE.zh-CN.md | 381 ++++++++++++++ scripts/pr-check.sh | 413 +++++++++++++++ scripts/pr-fix.sh | 335 ++++++++++++ 22 files changed, 6607 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/labels.yml create mode 100644 .github/workflows/pr-checks-advisory.yml create mode 100644 .github/workflows/pr-checks.yml create mode 100644 CONTRIBUTING.md create mode 100644 docs/community/HOW_TO_MIGRATE_YOUR_PR.md create mode 100644 docs/community/HOW_TO_MIGRATE_YOUR_PR.zh-CN.md create mode 100644 docs/community/MIGRATION_ANNOUNCEMENT.md create mode 100644 docs/community/MIGRATION_ANNOUNCEMENT.zh-CN.md create mode 100644 docs/community/PR_COMMENT_TEMPLATE.md create mode 100644 docs/i18n/zh-CN/CONTRIBUTING.md create mode 100644 docs/maintainers/PROJECT_MANAGEMENT.md create mode 100644 docs/maintainers/PROJECT_MANAGEMENT.zh-CN.md create mode 100644 docs/maintainers/PR_REVIEW_GUIDE.md create mode 100644 docs/maintainers/PR_REVIEW_GUIDE.zh-CN.md create mode 100644 docs/maintainers/README.md create mode 100644 docs/maintainers/README.zh-CN.md create mode 100644 docs/maintainers/SETUP_GUIDE.md create mode 100644 docs/maintainers/SETUP_GUIDE.zh-CN.md create mode 100755 scripts/pr-check.sh create mode 100755 scripts/pr-fix.sh diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..89bcae3f --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,127 @@ +# Auto-labeler configuration +# Automatically adds labels based on changed files + +# Area: Frontend +'area: frontend': + - changed-files: + - any-glob-to-any-file: + - 'web/**/*' + - '*.tsx' + - '*.ts' + - '*.jsx' + - '*.js' + - '*.css' + +# Area: Backend +'area: backend': + - changed-files: + - any-glob-to-any-file: + - '**/*.go' + - 'go.mod' + - 'go.sum' + - 'cmd/**/*' + - 'internal/**/*' + - 'pkg/**/*' + +# Area: Exchange +'area: exchange': + - changed-files: + - any-glob-to-any-file: + - 'internal/exchange/**/*' + - 'pkg/exchange/**/*' + - '**/binance*.go' + - '**/hyperliquid*.go' + - '**/aster*.go' + - '**/okx*.go' + - '**/bybit*.go' + +# Area: AI +'area: ai': + - changed-files: + - any-glob-to-any-file: + - 'internal/ai/**/*' + - 'pkg/ai/**/*' + - '**/deepseek*.go' + - '**/qwen*.go' + - '**/openai*.go' + - '**/claude*.go' + +# Area: API +'area: api': + - changed-files: + - any-glob-to-any-file: + - 'internal/api/**/*' + - 'pkg/api/**/*' + - '**/handler*.go' + - '**/router*.go' + +# Area: Security +'area: security': + - changed-files: + - any-glob-to-any-file: + - '**/auth*.go' + - '**/jwt*.go' + - '**/encryption*.go' + - '**/crypto*.go' + - 'SECURITY.md' + +# Area: Database +'area: database': + - changed-files: + - any-glob-to-any-file: + - 'internal/database/**/*' + - 'internal/db/**/*' + - '**/migration*.go' + - '**/*.sql' + - '**/schema*.go' + +# Area: UI/UX +'area: ui/ux': + - changed-files: + - any-glob-to-any-file: + - 'web/src/components/**/*' + - 'web/src/pages/**/*' + - '**/*.css' + - '**/style*.ts' + +# Area: Deployment +'area: deployment': + - changed-files: + - any-glob-to-any-file: + - 'Dockerfile' + - 'docker-compose*.yml' + - '.github/workflows/**/*' + - 'start.sh' + - '**/*deploy*.md' + +# Type: Documentation +'type: documentation': + - changed-files: + - any-glob-to-any-file: + - 'docs/**/*' + - '*.md' + - 'README*' + - 'CHANGELOG*' + - 'CONTRIBUTING.md' + - 'CODE_OF_CONDUCT.md' + +# Type: Test +'type: test': + - changed-files: + - any-glob-to-any-file: + - '**/*_test.go' + - 'test/**/*' + - '**/*.test.ts' + - '**/*.test.tsx' + - '**/*.spec.ts' + +# Dependencies +'dependencies': + - changed-files: + - any-glob-to-any-file: + - 'go.mod' + - 'go.sum' + - 'package.json' + - 'package-lock.json' + - 'web/package.json' + - 'web/package-lock.json' diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 00000000..26cadba4 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,180 @@ +# GitHub Labels Configuration +# Use https://github.com/crazy-max/ghaction-github-labeler to sync labels + +# Priority Labels +- name: "priority: critical" + color: "d73a4a" + description: "Critical priority - requires immediate attention" + +- name: "priority: high" + color: "ff6b6b" + description: "High priority - should be addressed soon" + +- name: "priority: medium" + color: "fbca04" + description: "Medium priority - normal queue" + +- name: "priority: low" + color: "0e8a16" + description: "Low priority - nice to have" + +# Type Labels +- name: "type: bug" + color: "d73a4a" + description: "Something isn't working" + +- name: "type: feature" + color: "a2eeef" + description: "New feature or request" + +- name: "type: enhancement" + color: "84b6eb" + description: "Improvement to existing feature" + +- name: "type: documentation" + color: "0075ca" + description: "Documentation improvements" + +- name: "type: security" + color: "ee0701" + description: "Security-related changes" + +- name: "type: performance" + color: "f9d0c4" + description: "Performance improvements" + +- name: "type: refactor" + color: "fbca04" + description: "Code refactoring" + +- name: "type: test" + color: "c5def5" + description: "Test-related changes" + +# Status Labels +- name: "status: needs review" + color: "fbca04" + description: "PR is ready for review" + +- name: "status: needs changes" + color: "d93f0b" + description: "PR needs changes based on review" + +- name: "status: on hold" + color: "fef2c0" + description: "PR/issue is on hold" + +- name: "status: in progress" + color: "0e8a16" + description: "Currently being worked on" + +- name: "status: blocked" + color: "d93f0b" + description: "Blocked by another issue/PR" + +# Area Labels (aligned with roadmap) +- name: "area: security" + color: "ee0701" + description: "Security enhancements (Phase 1.1)" + +- name: "area: ai" + color: "7057ff" + description: "AI capabilities and models (Phase 1.2)" + +- name: "area: exchange" + color: "0075ca" + description: "Exchange integrations (Phase 1.3)" + +- name: "area: architecture" + color: "d4c5f9" + description: "Project structure refactoring (Phase 1.4)" + +- name: "area: ui/ux" + color: "c2e0c6" + description: "User experience improvements (Phase 1.5)" + +- name: "area: frontend" + color: "bfdadc" + description: "Frontend (React/TypeScript)" + +- name: "area: backend" + color: "c5def5" + description: "Backend (Go)" + +- name: "area: api" + color: "0e8a16" + description: "API endpoints" + +- name: "area: database" + color: "f9d0c4" + description: "Database changes" + +- name: "area: deployment" + color: "fbca04" + description: "Deployment and CI/CD" + +# Special Labels +- name: "good first issue" + color: "7057ff" + description: "Good for newcomers" + +- name: "help wanted" + color: "008672" + description: "Extra attention is needed" + +- name: "bounty" + color: "1d76db" + description: "Bounty available for this issue" + +- name: "bounty: claimed" + color: "5319e7" + description: "Bounty has been claimed" + +- name: "bounty: paid" + color: "0e8a16" + description: "Bounty has been paid" + +- name: "RFC" + color: "d4c5f9" + description: "Request for Comments - needs discussion" + +- name: "breaking change" + color: "d73a4a" + description: "Includes breaking changes" + +- name: "duplicate" + color: "cfd3d7" + description: "This issue or pull request already exists" + +- name: "invalid" + color: "e4e669" + description: "This doesn't seem right" + +- name: "wontfix" + color: "ffffff" + description: "This will not be worked on" + +- name: "dependencies" + color: "0366d6" + description: "Dependency updates" + +# Roadmap Phases +- name: "roadmap: phase-1" + color: "0e8a16" + description: "Core Infrastructure Enhancement" + +- name: "roadmap: phase-2" + color: "fbca04" + description: "Testing & Stability" + +- name: "roadmap: phase-3" + color: "0075ca" + description: "Universal Market Expansion" + +- name: "roadmap: phase-4" + color: "7057ff" + description: "Advanced AI & Automation" + +- name: "roadmap: phase-5" + color: "d73a4a" + description: "Enterprise & Scaling" diff --git a/.github/workflows/pr-checks-advisory.yml b/.github/workflows/pr-checks-advisory.yml new file mode 100644 index 00000000..1c352233 --- /dev/null +++ b/.github/workflows/pr-checks-advisory.yml @@ -0,0 +1,331 @@ +name: PR Checks (Advisory) + +on: + pull_request: + types: [opened, synchronize, reopened] + branches: [main, dev] + +# These checks are advisory only - they won't block PR merging +# Results will be posted as comments to help contributors improve their PRs + +jobs: + pr-info: + name: PR Information + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Check PR title format + id: check-title + run: | + PR_TITLE="${{ github.event.pull_request.title }}" + + # Check if title follows conventional commits + if echo "$PR_TITLE" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|chore|ci|security)(\(.+\))?: .+"; then + echo "status=✅ Good" >> $GITHUB_OUTPUT + echo "message=PR title follows Conventional Commits format" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Suggestion" >> $GITHUB_OUTPUT + echo "message=Consider using Conventional Commits format: type(scope): description" >> $GITHUB_OUTPUT + fi + + - name: Calculate PR size + id: pr-size + run: | + ADDITIONS=${{ github.event.pull_request.additions }} + DELETIONS=${{ github.event.pull_request.deletions }} + TOTAL=$((ADDITIONS + DELETIONS)) + + if [ $TOTAL -lt 100 ]; then + echo "size=🟢 Small" >> $GITHUB_OUTPUT + echo "label=size: small" >> $GITHUB_OUTPUT + elif [ $TOTAL -lt 500 ]; then + echo "size=🟡 Medium" >> $GITHUB_OUTPUT + echo "label=size: medium" >> $GITHUB_OUTPUT + else + echo "size=🔴 Large" >> $GITHUB_OUTPUT + echo "label=size: large" >> $GITHUB_OUTPUT + echo "suggestion=Consider breaking this into smaller PRs for easier review" >> $GITHUB_OUTPUT + fi + echo "lines=$TOTAL" >> $GITHUB_OUTPUT + + - name: Post advisory comment + uses: actions/github-script@v7 + with: + script: | + const titleStatus = '${{ steps.check-title.outputs.status }}'; + const titleMessage = '${{ steps.check-title.outputs.message }}'; + const prSize = '${{ steps.pr-size.outputs.size }}'; + const prLines = '${{ steps.pr-size.outputs.lines }}'; + const sizeSuggestion = '${{ steps.pr-size.outputs.suggestion }}' || ''; + + let comment = '## 🤖 PR Advisory Feedback\n\n'; + comment += 'Thank you for your contribution! Here\'s some automated feedback to help improve your PR:\n\n'; + comment += '### PR Title\n'; + comment += titleStatus + ' ' + titleMessage + '\n\n'; + comment += '### PR Size\n'; + comment += prSize + ' (' + prLines + ' lines changed)\n'; + if (sizeSuggestion) { + comment += '\n💡 **Suggestion:** ' + sizeSuggestion + '\n'; + } + comment += '\n---\n\n'; + comment += '### 📖 New PR Management System\n\n'; + comment += 'We\'re introducing a new PR management system! These checks are **advisory only** and won\'t block your PR.\n\n'; + comment += '**Want to check your PR against new standards?**\n'; + comment += '```bash\n'; + comment += '# Run the PR health check tool\n'; + comment += './scripts/pr-check.sh\n'; + comment += '```\n\n'; + comment += 'This tool will:\n'; + comment += '- 🔍 Analyze your PR (doesn\'t modify anything)\n'; + comment += '- ✅ Show what\'s already good\n'; + comment += '- ⚠️ Point out issues\n'; + comment += '- 💡 Give specific suggestions on how to fix\n\n'; + comment += '**Learn more:**\n'; + comment += '- [Migration Guide](https://github.com/tinkle-community/nofx/blob/dev/docs/community/MIGRATION_ANNOUNCEMENT.md)\n'; + comment += '- [Contributing Guidelines](https://github.com/tinkle-community/nofx/blob/dev/CONTRIBUTING.md)\n\n'; + comment += '**Questions?** Just ask in the comments! We\'re here to help. 🙏\n\n'; + comment += '---\n\n'; + comment += '*This is an automated message. It won\'t affect your PR being merged.*'; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + + backend-checks: + name: Backend Checks (Advisory) + runs-on: ubuntu-latest + permissions: + pull-requests: write + continue-on-error: true + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libta-lib-dev || true + go mod download || true + + - name: Check Go formatting + id: go-fmt + continue-on-error: true + run: | + UNFORMATTED=$(gofmt -l . 2>/dev/null || echo "") + if [ -n "$UNFORMATTED" ]; then + echo "status=⚠️ Needs formatting" >> $GITHUB_OUTPUT + echo "files<> $GITHUB_OUTPUT + echo "$UNFORMATTED" | head -10 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "status=✅ Good" >> $GITHUB_OUTPUT + echo "files=" >> $GITHUB_OUTPUT + fi + + - name: Run go vet + id: go-vet + continue-on-error: true + run: | + if go vet ./... 2>&1 | tee vet-output.txt; then + echo "status=✅ Good" >> $GITHUB_OUTPUT + echo "output=" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Issues found" >> $GITHUB_OUTPUT + echo "output<> $GITHUB_OUTPUT + cat vet-output.txt | head -20 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Run tests + id: go-test + continue-on-error: true + run: | + if go test ./... -v 2>&1 | tee test-output.txt; then + echo "status=✅ Passed" >> $GITHUB_OUTPUT + echo "output=" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Failed" >> $GITHUB_OUTPUT + echo "output<> $GITHUB_OUTPUT + cat test-output.txt | tail -30 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Post backend feedback + if: always() + uses: actions/github-script@v7 + with: + script: | + const fmtStatus = '${{ steps.go-fmt.outputs.status }}' || '⚠️ Skipped'; + const vetStatus = '${{ steps.go-vet.outputs.status }}' || '⚠️ Skipped'; + const testStatus = '${{ steps.go-test.outputs.status }}' || '⚠️ Skipped'; + const fmtFiles = `${{ steps.go-fmt.outputs.files }}`; + const vetOutput = `${{ steps.go-vet.outputs.output }}`; + const testOutput = `${{ steps.go-test.outputs.output }}`; + + let comment = '## 🔧 Backend Checks (Advisory)\n\n'; + comment += '### Go Formatting\n'; + comment += fmtStatus + '\n'; + if (fmtFiles) { + comment += '\nFiles needing formatting:\n```\n' + fmtFiles + '\n```\n'; + } + comment += '\n### Go Vet\n'; + comment += vetStatus + '\n'; + if (vetOutput) { + comment += '\n```\n' + vetOutput.substring(0, 500) + '\n```\n'; + } + comment += '\n### Tests\n'; + comment += testStatus + '\n'; + if (testOutput) { + comment += '\n```\n' + testOutput.substring(0, 1000) + '\n```\n'; + } + comment += '\n---\n\n'; + comment += '💡 **To fix locally:**\n'; + comment += '```bash\n'; + comment += '# Format code\n'; + comment += 'go fmt ./...\n\n'; + comment += '# Check for issues\n'; + comment += 'go vet ./...\n\n'; + comment += '# Run tests\n'; + comment += 'go test ./...\n'; + comment += '```\n\n'; + comment += '*These checks are advisory and won\'t block merging. Need help? Just ask!*'; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + + frontend-checks: + name: Frontend Checks (Advisory) + runs-on: ubuntu-latest + permissions: + pull-requests: write + continue-on-error: true + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Check if web directory exists + id: check-web + run: | + if [ -d "web" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Install dependencies + if: steps.check-web.outputs.exists == 'true' + working-directory: ./web + continue-on-error: true + run: npm ci + + - name: Run linter + if: steps.check-web.outputs.exists == 'true' + id: lint + working-directory: ./web + continue-on-error: true + run: | + if npm run lint 2>&1 | tee lint-output.txt; then + echo "status=✅ Good" >> $GITHUB_OUTPUT + echo "output=" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Issues found" >> $GITHUB_OUTPUT + echo "output<> $GITHUB_OUTPUT + cat lint-output.txt | head -20 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Type check + if: steps.check-web.outputs.exists == 'true' + id: typecheck + working-directory: ./web + continue-on-error: true + run: | + if npm run type-check 2>&1 | tee typecheck-output.txt; then + echo "status=✅ Good" >> $GITHUB_OUTPUT + echo "output=" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Issues found" >> $GITHUB_OUTPUT + echo "output<> $GITHUB_OUTPUT + cat typecheck-output.txt | head -20 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Build + if: steps.check-web.outputs.exists == 'true' + id: build + working-directory: ./web + continue-on-error: true + run: | + if npm run build 2>&1 | tee build-output.txt; then + echo "status=✅ Success" >> $GITHUB_OUTPUT + echo "output=" >> $GITHUB_OUTPUT + else + echo "status=⚠️ Failed" >> $GITHUB_OUTPUT + echo "output<> $GITHUB_OUTPUT + cat build-output.txt | tail -20 >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Post frontend feedback + if: always() && steps.check-web.outputs.exists == 'true' + uses: actions/github-script@v7 + with: + script: | + const lintStatus = '${{ steps.lint.outputs.status }}' || '⚠️ Skipped'; + const typecheckStatus = '${{ steps.typecheck.outputs.status }}' || '⚠️ Skipped'; + const buildStatus = '${{ steps.build.outputs.status }}' || '⚠️ Skipped'; + const lintOutput = `${{ steps.lint.outputs.output }}`; + const typecheckOutput = `${{ steps.typecheck.outputs.output }}`; + const buildOutput = `${{ steps.build.outputs.output }}`; + + let comment = '## ⚛️ Frontend Checks (Advisory)\n\n'; + comment += '### Linting\n'; + comment += lintStatus + '\n'; + if (lintOutput) { + comment += '\n```\n' + lintOutput.substring(0, 500) + '\n```\n'; + } + comment += '\n### Type Checking\n'; + comment += typecheckStatus + '\n'; + if (typecheckOutput) { + comment += '\n```\n' + typecheckOutput.substring(0, 500) + '\n```\n'; + } + comment += '\n### Build\n'; + comment += buildStatus + '\n'; + if (buildOutput) { + comment += '\n```\n' + buildOutput.substring(0, 500) + '\n```\n'; + } + comment += '\n---\n\n'; + comment += '💡 **To fix locally:**\n'; + comment += '```bash\n'; + comment += 'cd web\n\n'; + comment += '# Fix linting issues\n'; + comment += 'npm run lint -- --fix\n\n'; + comment += '# Check types\n'; + comment += 'npm run type-check\n\n'; + comment += '# Test build\n'; + comment += 'npm run build\n'; + comment += '```\n\n'; + comment += '*These checks are advisory and won\'t block merging. Need help? Just ask!*'; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 00000000..a3141835 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,237 @@ +name: PR Checks + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + branches: + - dev + - main + +jobs: + # Validate PR title and description + validate-pr: + name: Validate PR Format + runs-on: ubuntu-latest + steps: + - name: Check PR title format + uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + docs + style + refactor + perf + test + chore + ci + security + scopes: | + exchange + trader + ai + api + ui + frontend + backend + security + deps + requireScope: false + + - name: Check PR size + uses: actions/github-script@v7 + with: + script: | + const pr = context.payload.pull_request; + const additions = pr.additions; + const deletions = pr.deletions; + const total = additions + deletions; + + let label = ''; + let comment = ''; + + if (total < 300) { + label = 'size: small'; + comment = '✅ This PR is **small** and easy to review!'; + } else if (total < 1000) { + label = 'size: medium'; + comment = '⚠️ This PR is **medium** sized. Consider breaking it into smaller PRs if possible.'; + } else { + label = 'size: large'; + comment = '🚨 This PR is **large** (>' + total + ' lines changed). Please consider breaking it into smaller, focused PRs for easier review.'; + } + + // Add size label + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: [label] + }); + + // Add comment for large PRs + if (total >= 1000) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + body: comment + }); + } + + # Backend tests + backend-tests: + name: Backend Tests (Go) + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Install TA-Lib + run: | + sudo apt-get update + sudo apt-get install -y libta-lib-dev + + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Download dependencies + run: go mod download + + - name: Run go fmt + run: | + if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then + echo "Please run 'go fmt' on your code" + gofmt -s -l . + exit 1 + fi + + - name: Run go vet + run: go vet ./... + + - name: Run tests + run: go test -v -race -coverprofile=coverage.out ./... + + - name: Build + run: go build -v -o nofx + + - name: Upload coverage + uses: codecov/codecov-action@v4 + with: + file: ./coverage.out + flags: backend + + # Frontend tests + frontend-tests: + name: Frontend Tests (React/TypeScript) + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Cache Node modules + uses: actions/cache@v4 + with: + path: web/node_modules + key: ${{ runner.os }}-node-${{ hashFiles('web/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + working-directory: ./web + run: npm ci + + - name: Run linter + working-directory: ./web + run: npm run lint + + - name: Run type check + working-directory: ./web + run: npm run type-check || true # Don't fail on type errors for now + + - name: Build + working-directory: ./web + run: npm run build + + # Auto-label based on files changed + auto-label: + name: Auto Label PR + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: actions/labeler@v5 + with: + configuration-path: .github/labeler.yml + repo-token: ${{ secrets.GITHUB_TOKEN }} + + # Check for security issues + security-check: + name: Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + scan-type: 'fs' + scan-ref: '.' + format: 'sarif' + output: 'trivy-results.sarif' + + - name: Upload Trivy results + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: 'trivy-results.sarif' + + # Check for secrets in code + secrets-check: + name: Check for Secrets + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run Gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # All checks passed + all-checks: + name: All Checks Passed + runs-on: ubuntu-latest + needs: [validate-pr, backend-tests, frontend-tests, security-check, secrets-check] + if: always() + steps: + - name: Check all jobs + run: | + if [ "${{ contains(needs.*.result, 'failure') }}" == "true" ]; then + echo "Some checks failed" + exit 1 + else + echo "All checks passed!" + fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..31fc7c02 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,481 @@ +# 🤝 Contributing to NOFX + +**Language:** [English](CONTRIBUTING.md) | [中文](docs/i18n/zh-CN/CONTRIBUTING.md) + +Thank you for your interest in contributing to NOFX! This document provides guidelines and workflows for contributing to the project. + +--- + +## 📑 Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [How Can I Contribute?](#how-can-i-contribute) +- [Development Workflow](#development-workflow) +- [PR Submission Guidelines](#pr-submission-guidelines) +- [Coding Standards](#coding-standards) +- [Commit Message Guidelines](#commit-message-guidelines) +- [Review Process](#review-process) +- [Bounty Program](#bounty-program) + +--- + +## 📜 Code of Conduct + +This project adheres to the [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. + +--- + +## 🎯 How Can I Contribute? + +### 1. Report Bugs 🐛 + +- Use the [Bug Report Template](.github/ISSUE_TEMPLATE/bug_report.md) +- Check if the bug has already been reported +- Include detailed reproduction steps +- Provide environment information (OS, Go version, etc.) + +### 2. Suggest Features ✨ + +- Use the [Feature Request Template](.github/ISSUE_TEMPLATE/feature_request.md) +- Explain the use case and benefits +- Check if it aligns with the [project roadmap](docs/roadmap/README.md) + +### 3. Submit Pull Requests 🔧 + +Before submitting a PR, please check the following: + +#### ✅ **Accepted Contributions** + +**High Priority** (aligned with roadmap): +- 🔒 Security enhancements (encryption, authentication, RBAC) +- 🧠 AI model integrations (GPT-4, Claude, Gemini Pro) +- 🔗 Exchange integrations (OKX, Bybit, Lighter, EdgeX) +- 📊 Trading data APIs (AI500, OI analysis, NetFlow) +- 🎨 UI/UX improvements (mobile responsiveness, charts) +- ⚡ Performance optimizations +- 🐛 Bug fixes +- 📝 Documentation improvements + +**Medium Priority:** +- ✅ Test coverage improvements +- 🌐 Internationalization (new language support) +- 🔧 Build/deployment tooling +- 📈 Monitoring and logging enhancements + +#### ❌ **Not Accepted** (without prior discussion) + +- Major architectural changes without RFC (Request for Comments) +- Features not aligned with project roadmap +- Breaking changes without migration path +- Code that introduces new dependencies without justification +- Experimental features without opt-in flag + +**⚠️ Important:** For major features, please open an issue for discussion **before** starting work. + +--- + +## 🛠️ Development Workflow + +### 1. Fork and Clone + +```bash +# Fork the repository on GitHub +# Then clone your fork +git clone https://github.com/YOUR_USERNAME/nofx.git +cd nofx + +# Add upstream remote +git remote add upstream https://github.com/tinkle-community/nofx.git +``` + +### 2. Create a Feature Branch + +```bash +# Update your local dev branch +git checkout dev +git pull upstream dev + +# Create a new branch +git checkout -b feature/your-feature-name +# or +git checkout -b fix/your-bug-fix +``` + +**Branch Naming Convention:** +- `feature/` - New features +- `fix/` - Bug fixes +- `docs/` - Documentation updates +- `refactor/` - Code refactoring +- `perf/` - Performance improvements +- `test/` - Test updates +- `chore/` - Build/config changes + +### 3. Set Up Development Environment + +```bash +# Install Go dependencies +go mod download + +# Install frontend dependencies +cd web +npm install +cd .. + +# Install TA-Lib (required) +# macOS: +brew install ta-lib + +# Ubuntu/Debian: +sudo apt-get install libta-lib0-dev +``` + +### 4. Make Your Changes + +- Follow the [coding standards](#coding-standards) +- Write tests for new features +- Update documentation as needed +- Keep commits focused and atomic + +### 5. Test Your Changes + +```bash +# Run backend tests +go test ./... + +# Build backend +go build -o nofx + +# Run frontend in dev mode +cd web +npm run dev + +# Build frontend +npm run build +``` + +### 6. Commit Your Changes + +Follow the [commit message guidelines](#commit-message-guidelines): + +```bash +git add . +git commit -m "feat: add support for OKX exchange integration" +``` + +### 7. Push and Create PR + +```bash +# Push to your fork +git push origin feature/your-feature-name + +# Go to GitHub and create a Pull Request +# Use the PR template and fill in all sections +``` + +--- + +## 📝 PR Submission Guidelines + +### Before Submitting + +- [ ] Code compiles successfully (`go build` and `npm run build`) +- [ ] All tests pass (`go test ./...`) +- [ ] No linting errors (`go fmt`, `go vet`) +- [ ] Documentation is updated +- [ ] Commits follow conventional commits format +- [ ] Branch is rebased on latest `dev` + +### PR Title Format + +Use [Conventional Commits](https://www.conventionalcommits.org/) format: + +``` +(): + +Examples: +feat(exchange): add OKX exchange integration +fix(trader): resolve position tracking bug +docs(readme): update installation instructions +perf(ai): optimize prompt generation +refactor(core): extract common exchange interface +``` + +**Types:** +- `feat` - New feature +- `fix` - Bug fix +- `docs` - Documentation +- `style` - Code style (formatting, no logic change) +- `refactor` - Code refactoring +- `perf` - Performance improvement +- `test` - Test updates +- `chore` - Build/config changes +- `ci` - CI/CD changes +- `security` - Security improvements + +### PR Description + +Use the [PR template](.github/PULL_REQUEST_TEMPLATE.md) and ensure: + +1. **Clear description** of what and why +2. **Type of change** is marked +3. **Related issues** are linked +4. **Testing steps** are documented +5. **Screenshots** for UI changes +6. **All checkboxes** are completed + +### PR Size + +Keep PRs focused and reasonably sized: + +- ✅ **Small PR** (< 300 lines): Ideal, fast review +- ⚠️ **Medium PR** (300-1000 lines): Acceptable, may take longer +- ❌ **Large PR** (> 1000 lines): Please break into smaller PRs + +--- + +## 💻 Coding Standards + +### Go Code + +```go +// ✅ Good: Clear naming, proper error handling +func ConnectToExchange(apiKey, secret string) (*Exchange, error) { + if apiKey == "" || secret == "" { + return nil, fmt.Errorf("API credentials are required") + } + + client, err := createClient(apiKey, secret) + if err != nil { + return nil, fmt.Errorf("failed to create client: %w", err) + } + + return &Exchange{client: client}, nil +} + +// ❌ Bad: Poor naming, no error handling +func ce(a, s string) *Exchange { + c := createClient(a, s) + return &Exchange{client: c} +} +``` + +**Best Practices:** +- Use meaningful variable names +- Handle all errors explicitly +- Add comments for complex logic +- Follow Go idioms and conventions +- Run `go fmt` before committing +- Use `go vet` and `golangci-lint` + +### TypeScript/React Code + +```typescript +// ✅ Good: Type-safe, clear naming +interface TraderConfig { + id: string; + exchange: 'binance' | 'hyperliquid' | 'aster'; + aiModel: string; + enabled: boolean; +} + +const TraderCard: React.FC<{ trader: TraderConfig }> = ({ trader }) => { + const [isRunning, setIsRunning] = useState(false); + + const handleStart = async () => { + try { + await startTrader(trader.id); + setIsRunning(true); + } catch (error) { + console.error('Failed to start trader:', error); + } + }; + + return
...
; +}; + +// ❌ Bad: No types, unclear naming +const TC = (props) => { + const [r, setR] = useState(false); + const h = () => { startTrader(props.t.id); setR(true); }; + return
...
; +}; +``` + +**Best Practices:** +- Use TypeScript strict mode +- Define interfaces for all data structures +- Avoid `any` type +- Use functional components with hooks +- Follow React best practices +- Run `npm run lint` before committing + +### File Structure + +``` +NOFX/ +├── cmd/ # Main applications +├── internal/ # Private code +│ ├── exchange/ # Exchange adapters +│ ├── trader/ # Trading logic +│ ├── ai/ # AI integrations +│ └── api/ # API handlers +├── pkg/ # Public libraries +├── web/ # Frontend +│ ├── src/ +│ │ ├── components/ +│ │ ├── pages/ +│ │ ├── hooks/ +│ │ └── utils/ +│ └── public/ +└── docs/ # Documentation +``` + +--- + +## 📋 Commit Message Guidelines + +### Format + +``` +(): + + + +