name: ๐Ÿงช Test Suite on: push: branches: [main, dev] pull_request: branches: [main, dev] # ๅ–ๆถˆๅŒไธ€ๅˆ†ๆ”ฏ็š„่ฟ›่กŒไธญ็š„ๅทฅไฝœๆต concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # ==================== ไปฃ็ ่ดจ้‡ๆฃ€ๆŸฅ ==================== quality: name: ๐Ÿ“‹ Code Quality runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install --frozen-lockfile - name: Run linting run: bun run lint - name: Run type checking run: bun run typecheck - name: Check formatting run: bun run format:check # ==================== ๅ•ๅ…ƒๆต‹่ฏ• ==================== unit-tests: name: โšก Unit Tests runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 - name: Install dependencies run: bun install --frozen-lockfile - name: Run unit tests run: bun run test -- tests/unit/ --passWithNoTests # ==================== ้›†ๆˆๆต‹่ฏ•๏ผˆ้œ€่ฆๆ•ฐๆฎๅบ“๏ผ‰==================== integration-tests: name: ๐Ÿ”— Integration Tests runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine env: POSTGRES_USER: test_user POSTGRES_PASSWORD: test_password POSTGRES_DB: claude_code_hub_test options: >- --health-cmd "pg_isready -U test_user -d claude_code_hub_test" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7-alpine options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 env: DSN: postgres://test_user:test_password@localhost:5432/claude_code_hub_test REDIS_URL: redis://localhost:6379/1 ADMIN_TOKEN: test-admin-token-for-ci AUTO_MIGRATE: true ENABLE_RATE_LIMIT: true SESSION_TTL: 300 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 - name: Install dependencies run: bun install --frozen-lockfile - name: Run database migrations run: bun run db:migrate - name: Run integration tests run: bun run test -- tests/integration/ --passWithNoTests # ==================== API ๆต‹่ฏ•๏ผˆ้œ€่ฆ่ฟ่กŒๆœๅŠก๏ผ‰==================== api-tests: name: ๐ŸŒ API Tests runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine env: POSTGRES_USER: test_user POSTGRES_PASSWORD: test_password POSTGRES_DB: claude_code_hub_test options: >- --health-cmd "pg_isready -U test_user -d claude_code_hub_test" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7-alpine options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 env: DSN: postgres://test_user:test_password@localhost:5432/claude_code_hub_test REDIS_URL: redis://localhost:6379/1 ADMIN_TOKEN: test-admin-token-for-ci AUTO_MIGRATE: true PORT: 13500 ENABLE_RATE_LIMIT: true SESSION_TTL: 300 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 - name: Install dependencies run: bun install --frozen-lockfile - name: Run database migrations run: bun run db:migrate - name: Build application run: bun run build - name: Start server (background) run: | bun run start & echo $! > server.pid sleep 15 # ็ญ‰ๅพ…ๆœๅŠกๅฏๅŠจ - name: Wait for server ready run: | timeout 60 bash -c 'until curl -f http://localhost:13500/api/actions/health; do sleep 2; done' - name: Run E2E API tests run: bun run test:e2e env: API_BASE_URL: http://localhost:13500/api/actions TEST_ADMIN_TOKEN: test-admin-token-for-ci AUTO_CLEANUP_TEST_DATA: true - name: Stop server if: always() run: | if [ -f server.pid ]; then kill $(cat server.pid) || true fi # ==================== ๆต‹่ฏ•็ป“ๆžœๆฑ‡ๆ€ป ==================== test-summary: name: ๐Ÿ“Š Test Summary runs-on: ubuntu-latest needs: [quality, unit-tests, integration-tests, api-tests] if: always() steps: - name: Check test results run: | if [ "${{ needs.quality.result }}" != "success" ] || \ [ "${{ needs.unit-tests.result }}" != "success" ] || \ [ "${{ needs.integration-tests.result }}" != "success" ] || \ [ "${{ needs.api-tests.result }}" != "success" ]; then echo "โŒ ้ƒจๅˆ†ๆต‹่ฏ•ๅคฑ่ดฅ" exit 1 else echo "โœ… ๆ‰€ๆœ‰ๆต‹่ฏ•้€š่ฟ‡" fi - name: Create summary if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository uses: actions/github-script@v7 with: script: | const summary = `## ๐Ÿงช ๆต‹่ฏ•็ป“ๆžœ | ๆต‹่ฏ•็ฑปๅž‹ | ็Šถๆ€ | |---------|------| | ไปฃ็ ่ดจ้‡ | ${{ needs.quality.result == 'success' && 'โœ…' || 'โŒ' }} | | ๅ•ๅ…ƒๆต‹่ฏ• | ${{ needs.unit-tests.result == 'success' && 'โœ…' || 'โŒ' }} | | ้›†ๆˆๆต‹่ฏ• | ${{ needs.integration-tests.result == 'success' && 'โœ…' || 'โŒ' }} | | API ๆต‹่ฏ• | ${{ needs.api-tests.result == 'success' && 'โœ…' || 'โŒ' }} | **ๆ€ปไฝ“็ป“ๆžœ**: ${{ (needs.quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.api-tests.result == 'success') && 'โœ… ๆ‰€ๆœ‰ๆต‹่ฏ•้€š่ฟ‡' || 'โŒ ้ƒจๅˆ†ๆต‹่ฏ•ๅคฑ่ดฅ' }} `; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: summary });