diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0dbfd7a..3005ea9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,557 +1,29 @@ -name: CI - Comprehensive Pipeline +name: CI on: pull_request: - branches: - - main - - develop push: - branches: - - main - - develop - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + branches: [main] permissions: contents: read - checks: write - pull-requests: write jobs: - install: - name: Install Dependencies - runs-on: ubuntu-latest - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Install backend dependencies - run: npm ci - - - name: Cache backend node_modules - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install webapp dependencies - working-directory: ./webapp - run: npm ci - - - name: Cache webapp node_modules - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - lint: - name: Lint (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: install - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Run backend ESLint - run: npm run lint - # TODO: Remove continue-on-error once lint issues are fixed (see issue #TBD) - # Currently 122 linting problems (17 errors, 105 warnings) exist in the codebase - continue-on-error: true - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Run webapp ESLint - run: npm run lint:webapp - # TODO: Remove continue-on-error once lint issues are fixed (see issue #TBD) - # Currently has linting warnings that need to be addressed - continue-on-error: true - - typecheck: - name: Type Check (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: install - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Run backend type check - run: npm run type-check - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Run webapp type check - run: npm run type-check:webapp - - unit-tests-backend: - name: Backend Tests (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: [lint, typecheck] - timeout-minutes: 15 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Run backend tests - run: npm test - env: - NODE_ENV: test - JEST_TIMEOUT: 30000 - - - name: Upload backend coverage - uses: actions/upload-artifact@v6 - if: matrix.node-version == 20 - with: - name: backend-coverage - path: coverage/ - retention-days: 7 - if-no-files-found: ignore - - - name: Upload test results - if: always() - uses: actions/upload-artifact@v6 - with: - name: backend-test-results-node-${{ matrix.node-version }} - path: | - coverage/ - test-results/ - retention-days: 7 - if-no-files-found: ignore - - unit-tests-webapp: - name: Webapp Tests (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: [lint, typecheck] - timeout-minutes: 15 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - cache-dependency-path: webapp/package-lock.json - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Run webapp tests - run: npm run test:webapp - continue-on-error: true - env: - NODE_ENV: test - - - name: Upload webapp coverage - uses: actions/upload-artifact@v6 - if: matrix.node-version == 20 - with: - name: webapp-coverage - path: webapp/coverage/ - retention-days: 7 - if-no-files-found: ignore - - coverage-merge: - name: Merge Coverage & Upload + validate: runs-on: ubuntu-latest - needs: [unit-tests-backend, unit-tests-webapp] - if: always() - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: '20' - - - name: Download backend coverage - uses: actions/download-artifact@v7 - with: - name: backend-coverage - path: coverage/ - continue-on-error: true - - - name: Download webapp coverage - uses: actions/download-artifact@v7 - with: - name: webapp-coverage - path: webapp/coverage/ - continue-on-error: true - - - name: Merge coverage reports - run: bash scripts/merge-coverage.sh - continue-on-error: true - - - name: Upload to Codecov - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./coverage/merged/lcov.info,./coverage/lcov.info - flags: unittests - name: codecov-umbrella - fail_ci_if_error: false - verbose: true - continue-on-error: true - health-check: - name: Health Check Tests (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: [build] - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - node-version: [20] - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Download backend build artifacts - uses: actions/download-artifact@v7 - with: - name: backend-dist - path: dist/ - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Download webapp build artifacts - uses: actions/download-artifact@v7 - with: - name: webapp-build - path: webapp/.next/ - continue-on-error: true - - - name: Validate build artifacts - run: bash scripts/validate-build.sh - - - name: Test environment configuration - run: bash scripts/env-sync-check.sh - continue-on-error: true - - - name: Verify health check script - run: | - # Create minimal .env for testing - cat > .env << EOF - SOLANA_RPC_URL=https://api.mainnet-beta.solana.com - WALLET_PRIVATE_KEY=test_key_placeholder_not_real - JWT_SECRET=test_jwt_secret_for_ci_only - ADMIN_USERNAME=admin - ADMIN_PASSWORD=test_password - EOF - - # Run health check in dry-run mode - bash scripts/health-check.sh || echo "Health check completed with warnings (expected in CI)" + - uses: actions/checkout@v4 - security-scan: - name: Security Scan (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: install - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + - uses: actions/setup-node@v4 with: - node-version: ${{ matrix.node-version }} + node-version: 20 cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Run npm audit (backend) - run: npm audit --audit-level=high || echo "⚠️ Security vulnerabilities found - review required" - continue-on-error: true - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Run npm audit (webapp) - working-directory: ./webapp - run: npm audit --audit-level=high || echo "⚠️ Security vulnerabilities found - review required" - continue-on-error: true - build: - name: Build (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest - needs: [lint, typecheck] - timeout-minutes: 15 - strategy: - fail-fast: false - matrix: - node-version: [18, 20] - - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Restore backend cache - uses: actions/cache@v5 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }} - - - name: Install backend dependencies (if cache miss) - run: npm ci --prefer-offline || npm ci - - - name: Build backend - run: npm run build:backend - - - name: Upload backend build artifacts - uses: actions/upload-artifact@v6 - if: matrix.node-version == 20 - with: - name: backend-dist - path: dist/ - retention-days: 3 - - - name: Restore webapp cache - uses: actions/cache@v5 - with: - path: webapp/node_modules - key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }} - - - name: Install webapp dependencies (if cache miss) - working-directory: ./webapp - run: npm ci --prefer-offline || npm ci - - - name: Build webapp - run: npm run build:webapp - env: - NEXT_PUBLIC_RPC_URL: ${{ secrets.NEXT_PUBLIC_RPC_URL || 'https://api.mainnet-beta.solana.com' }} - - - name: Upload webapp build artifacts - uses: actions/upload-artifact@v6 - if: matrix.node-version == 20 - with: - name: webapp-build - path: webapp/.next/ - retention-days: 3 - if-no-files-found: ignore + - run: npm ci + if: hashFiles('package.json') != '' - ci-summary: - name: CI Summary - runs-on: ubuntu-latest - needs: - - lint - - typecheck - - unit-tests-backend - - unit-tests-webapp - - coverage-merge - - security-scan - - build - - health-check - if: always() - - steps: - - name: Check CI status - run: | - echo "## CI Pipeline Results" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY - echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY - echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Type Check | ${{ needs.typecheck.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Backend Tests | ${{ needs.unit-tests-backend.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Webapp Tests | ${{ needs.unit-tests-webapp.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Coverage Merge | ${{ needs.coverage-merge.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Security Scan | ${{ needs.security-scan.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Health Check | ${{ needs.health-check.result }} |" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - - if [[ "${{ needs.lint.result }}" == "failure" ]] || \ - [[ "${{ needs.typecheck.result }}" == "failure" ]] || \ - [[ "${{ needs.unit-tests-backend.result }}" == "failure" ]] || \ - [[ "${{ needs.build.result }}" == "failure" ]] || \ - [[ "${{ needs.health-check.result }}" == "failure" ]]; then - echo "❌ CI checks failed!" >> $GITHUB_STEP_SUMMARY - exit 1 - else - echo "✅ All CI checks passed!" >> $GITHUB_STEP_SUMMARY - fi - - - name: Comment on PR - if: github.event_name == 'pull_request' - uses: actions/github-script@v8 - with: - script: | - const summary = `## 🔍 CI Pipeline Results - - | Job | Status | - |-----|--------| - | Lint | ${{ needs.lint.result == 'success' ? '✅' : '❌' }} | - | Type Check | ${{ needs.typecheck.result == 'success' ? '✅' : '❌' }} | - | Backend Tests | ${{ needs.unit-tests-backend.result == 'success' ? '✅' : '❌' }} | - | Webapp Tests | ${{ needs.unit-tests-webapp.result == 'success' ? '✅' : '⚠️' }} | - | Coverage | ${{ needs.coverage-merge.result == 'success' ? '✅' : '⚠️' }} | - | Security Scan | ${{ needs.security-scan.result == 'success' ? '✅' : '⚠️' }} | - | Build | ${{ needs.build.result == 'success' ? '✅' : '❌' }} | - | Health Check | ${{ needs.health-check.result == 'success' ? '✅' : '❌' }} | - - ${needs.lint.result == 'failure' || needs.typecheck.result == 'failure' || needs.unit-tests-backend.result == 'failure' || needs.build.result == 'failure' || needs.health-check.result == 'failure' ? '❌ **CI checks failed!** Please review the errors above.' : '✅ **All CI checks passed!**'} - `; - - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: summary - }); + - run: npm run lint --if-present + - run: npm run typecheck --if-present + - run: npm test --if-present + - run: npm run build --if-present diff --git a/.github/workflows/copilot-universal-auto.yml b/.github/workflows/copilot-universal-auto.yml deleted file mode 100644 index e1b9926..0000000 --- a/.github/workflows/copilot-universal-auto.yml +++ /dev/null @@ -1,189 +0,0 @@ -name: Copilot Universal Auto - -on: - issue_comment: - types: [created] - pull_request: - types: [opened, synchronize, reopened] - push: - branches: [ main, master ] - -permissions: - contents: write - pull-requests: write - statuses: write - -jobs: - - auto-apply: - if: contains(github.event.comment.body, '@copilot apply-all') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.issue.pull_request.head.ref }} - - - name: Apply all suggestions - uses: github/copilot-apply-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - instructions: | - Apply all implementation suggestions. - Fix all comments. - Resolve all threads. - Reply to each comment. - Format + lint. - Sync branch with target. - Ensure build passes. - Ensure tests pass. - Re-run until CI is green. - Non-destructive changes only. - - fix-tests: - if: contains(github.event.comment.body, '@copilot fix-tests') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.issue.pull_request.head.ref }} - - - name: Repair tests - uses: github/copilot-apply-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - instructions: | - Fix all failing tests. - Fix build errors. - Fix TypeScript errors. - Fix lint errors. - Do not delete tests. - Do not weaken assertions. - Preserve architecture. - Re-run until CI is green. - Push fixes automatically. - - auto-heal: - if: contains(github.event.comment.body, '@copilot heal') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.issue.pull_request.head.ref }} - - - name: Heal repo - uses: github/copilot-apply-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - instructions: | - Fix all build issues. - Fix all dependency issues. - Fix all lint issues. - Fix all TypeScript issues. - Fix all test issues. - Ensure CI is green. - Ensure deterministic builds. - Ensure repo stability. - Push fixes automatically. - - vercel-deploy: - if: contains(github.event.comment.body, '@copilot deploy-vercel') - runs-on: ubuntu-latest - env: - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.issue.pull_request.head.ref }} - - - name: Install dependencies - run: | - if [ -f package-lock.json ]; then npm ci; fi - if [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm install; fi - if [ -f yarn.lock ]; then yarn install --frozen-lockfile; fi - - - name: Build project - run: | - if [ -f package.json ] && npm run | grep -q "build"; then npm run build; fi - - - name: Deploy to Vercel - if: env.VERCEL_TOKEN != '' - run: | - npm install -g vercel - vercel --prod --token "${VERCEL_TOKEN}" --yes - - branch-protection: - if: contains(github.event.comment.body, '@copilot protect-branch') - runs-on: ubuntu-latest - env: - GH_ADMIN_TOKEN: ${{ secrets.GH_ADMIN_TOKEN }} - steps: - - name: Protect branches - if: env.GH_ADMIN_TOKEN != '' - run: | - OWNER=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f1) - REPO=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f2) - for BRANCH in main master; do - gh api -H "Authorization: token ${GH_ADMIN_TOKEN}" -X PUT \ - "/repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" \ - -F required_status_checks.strict=true \ - -F enforce_admins=true \ - -F required_pull_request_reviews.dismiss_stale_reviews=true \ - -F required_pull_request_reviews.required_approving_review_count=1 \ - -F restrictions=null || true - done - - ci-enforce: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - if [ -f package-lock.json ]; then npm ci; fi - if [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm install; fi - if [ -f yarn.lock ]; then yarn install --frozen-lockfile; fi - - - name: Run lint/tests - run: | - if [ -f package.json ]; then - if npm run | grep -q "lint"; then npm run lint; fi - if npm run | grep -q "test"; then npm test -- --watch=false || npm test || true; fi - fi - - readme-health: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Update README with badges + health - uses: github/copilot-apply-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - instructions: | - Ensure README.md exists. - Add badges for CI, license, and coverage (placeholder if unknown). - Add a Repo Health section summarizing: - - Lint status - - Test status - - Build status - Keep it concise and operator-grade. - - pr-doctor: - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: PR Doctor Review - uses: github/copilot-apply-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - instructions: | - Act as an operator-grade PR doctor. - Review the diff for: - - Architectural drift - - Risky changes - - Missing tests - - Anti-patterns - Leave structured review comments. - Suggest minimal, safe fixes.