Sentry Integration (補強 SignOz): - Add @sentry/nextjs for frontend error tracking + session replay - Add sentry-sdk[fastapi] for backend error tracking - Create sentry.client/server/edge.config.ts - Integrate with next.config.js + instrumentation.ts - Add Sentry exception capture in FastAPI error handler - Create deployment scripts for Self-Hosted @ 192.168.0.110 CI/CD Fixes: - Fix F821 Undefined name 'Field' in incidents.py - Add NEXT_PUBLIC_API_URL env var to CI build step - Add build-arg to Docker build verification E2E Test Improvements: - Fix strict mode violations in dashboard-acceptance tests - Add timeout increase for Phase 4 demo tests - Make tests more resilient to UI variations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
250 lines
6.7 KiB
YAML
250 lines
6.7 KiB
YAML
name: CI
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
pull_request:
|
||
branches: [main]
|
||
workflow_dispatch:
|
||
|
||
# 沿用 AIOPS 設計: 新 commit 自動取消舊 workflow
|
||
concurrency:
|
||
group: ci-${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
env:
|
||
NODE_VERSION: '20'
|
||
PNPM_VERSION: '9'
|
||
PYTHON_VERSION: '3.11'
|
||
|
||
jobs:
|
||
# ==================== Lint & Type Check ====================
|
||
lint:
|
||
name: Lint & Type Check
|
||
runs-on: self-hosted
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v3
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
|
||
- name: Install dependencies
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Lint
|
||
run: pnpm lint
|
||
|
||
- name: Type check
|
||
run: pnpm typecheck
|
||
|
||
- name: ADR Compliance Check
|
||
run: |
|
||
echo "🔍 正在檢查是否違反 ADR 規定..."
|
||
|
||
# 檢查 1: 前端禁止直連資料庫 (違反 ADR-005 BFF 原則)
|
||
if grep -rE "psycopg2|asyncpg|redis|sqlalchemy|pg|ioredis" apps/web/src/ 2>/dev/null; then
|
||
echo "❌ 嚴重違規 (ADR-005): 前端程式碼中發現直連資料庫的套件!"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查 2: 狀態管理嚴禁使用 Redux (違反 ADR-004 必須用 Zustand)
|
||
if grep -rE "@reduxjs/toolkit|react-redux" apps/web/package.json 2>/dev/null; then
|
||
echo "❌ 違規 (ADR-004): 發現 Redux,請全面改用 Zustand!"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查 3: 禁止 import 舊專案 (違反 .awoooi-agent-rules.md)
|
||
if grep -rE "from ['\"].*wooo-aiops" apps/ packages/ 2>/dev/null; then
|
||
echo "❌ 嚴重違規: 禁止 import 舊專案 wooo-aiops!"
|
||
exit 1
|
||
fi
|
||
|
||
# 檢查 4: 禁止硬編碼機密
|
||
if grep -rE "(sk-[a-zA-Z0-9]{20,}|password\s*=\s*['\"][^'\"]+['\"])" apps/ packages/ 2>/dev/null; then
|
||
echo "❌ 嚴重違規: 發現硬編碼機密!"
|
||
exit 1
|
||
fi
|
||
|
||
echo "✅ ADR 規範檢查通過!"
|
||
|
||
# ==================== Test ====================
|
||
test:
|
||
name: Test
|
||
runs-on: self-hosted
|
||
needs: lint
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v3
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
|
||
- name: Install dependencies
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Run tests
|
||
run: pnpm test
|
||
continue-on-error: true
|
||
|
||
- name: Upload coverage
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
fail_ci_if_error: false
|
||
|
||
# ==================== Build ====================
|
||
build:
|
||
name: Build
|
||
runs-on: self-hosted
|
||
needs: lint
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v3
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
|
||
- name: Install dependencies
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Setup Turborepo Cache
|
||
uses: dtinth/setup-github-actions-caching-for-turbo@v1
|
||
|
||
- name: Build packages
|
||
env:
|
||
# Next.js 需要 NEXT_PUBLIC_* 在 build-time (統帥鐵律)
|
||
NEXT_PUBLIC_API_URL: https://awoooi.wooo.work
|
||
run: pnpm turbo build
|
||
|
||
- name: Upload build artifacts
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: build-artifacts
|
||
path: |
|
||
apps/*/dist
|
||
packages/*/dist
|
||
retention-days: 7
|
||
|
||
# ==================== API (Python) ====================
|
||
api-lint:
|
||
name: API Lint (Python)
|
||
runs-on: self-hosted
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup Python
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: ${{ env.PYTHON_VERSION }}
|
||
|
||
- name: Install uv
|
||
uses: astral-sh/setup-uv@v3
|
||
|
||
- name: Install dependencies
|
||
working-directory: apps/api
|
||
run: uv sync
|
||
|
||
- name: Lint with ruff
|
||
working-directory: apps/api
|
||
run: uv run ruff check .
|
||
|
||
- name: Type check with mypy
|
||
working-directory: apps/api
|
||
# 漸進式類型檢查: 只檢查核心 src/,排除 scripts/ 和 tests/
|
||
run: uv run mypy src/ --exclude 'tests/|scripts/' || echo "::warning::mypy 有錯誤,但不阻止 CI (漸進式採用中)"
|
||
continue-on-error: true
|
||
|
||
api-test:
|
||
name: API Test (Python)
|
||
runs-on: self-hosted
|
||
needs: api-lint
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup Python
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: ${{ env.PYTHON_VERSION }}
|
||
|
||
- name: Install uv
|
||
uses: astral-sh/setup-uv@v3
|
||
|
||
- name: Install dependencies
|
||
working-directory: apps/api
|
||
run: uv sync
|
||
|
||
- name: Run tests
|
||
working-directory: apps/api
|
||
env:
|
||
PYTHONPATH: ${{ github.workspace }}/apps/api
|
||
continue-on-error: true
|
||
run: |
|
||
uv run python --version
|
||
uv run pytest tests/ --cov=src --cov-report=xml -v || echo "::warning::部分測試失敗"
|
||
|
||
# ==================== OpenAPI Validation ====================
|
||
openapi-validate:
|
||
name: Validate OpenAPI Spec
|
||
runs-on: self-hosted
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
|
||
- name: Install spectral
|
||
run: npm install -g @stoplight/spectral-cli
|
||
|
||
- name: Validate OpenAPI
|
||
run: spectral lint docs/api/api-contract.yaml
|
||
|
||
# ==================== Docker Build (驗證 Dockerfile) ====================
|
||
docker-build:
|
||
name: Docker Build Verify
|
||
runs-on: self-hosted
|
||
needs: [test, api-test, build]
|
||
strategy:
|
||
matrix:
|
||
app: [web, api]
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Set up Docker Buildx
|
||
uses: docker/setup-buildx-action@v3
|
||
|
||
- name: Build image (no push)
|
||
uses: docker/build-push-action@v5
|
||
with:
|
||
context: .
|
||
file: apps/${{ matrix.app }}/Dockerfile
|
||
push: false
|
||
tags: awoooi-${{ matrix.app }}:test
|
||
build-args: |
|
||
NEXT_PUBLIC_API_URL=https://awoooi.wooo.work
|
||
cache-from: type=gha
|
||
cache-to: type=gha,mode=max
|