Files
awoooi/.github/workflows/ci.yaml
OG T 6ca2efe27b fix(ci): 修復 ESLint + spectral-cli 安裝錯誤
- 移除不存在的 @typescript-eslint/no-deprecated 規則
- 修復 npm ENOTEMPTY 錯誤 (先清理舊目錄)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 19:00:06 +08:00

366 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# AWOOOI CI Pipeline v2.0 (沿用 AIOPS 最佳實踐)
# =============================================================================
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: '20'
PNPM_VERSION: '9'
PYTHON_VERSION: '3.11'
# OTEL CI/CD 監控 (2026-03-24 批准, 2026-03-28 修正: SignOz 在 188)
OTEL_EXPORTER_OTLP_ENDPOINT: http://192.168.0.188:24318
OTEL_SERVICE_NAME: awoooi-ci
OTEL_RESOURCE_ATTRIBUTES: service.version=${{ github.sha }},deployment.environment=ci
jobs:
# ==================== Pre-flight (10s Fail-Fast) ====================
pre-flight:
name: "Pre-flight"
runs-on: [self-hosted, harbor, k8s]
timeout-minutes: 1
steps:
- name: Quick sanity check
run: |
echo "✅ Runner 可用"
node --version || echo "⚠️ Node not found"
python3 --version || echo "⚠️ Python not found"
# ==================== Lint & Type Check ====================
lint:
name: Lint & Type Check
runs-on: [self-hosted, harbor, k8s]
needs: pre-flight
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
clean: true
# 清理 worktrees (在 checkout 後,確保在 workspace 內)
- name: Clean worktrees
run: rm -rf ${{ github.workspace }}/.claude/worktrees 2>/dev/null || true
- 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
# Phase 14.2: 依賴治理 (2026-03-26)
- name: Dependency Check
run: pnpm dep-check
- name: ADR Compliance Check
run: |
echo "🔍 檢查 ADR 規定..."
# 檢查 1: 前端禁止直連資料庫 (ADR-005)
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)
if grep -rE "@reduxjs/toolkit|react-redux" apps/web/package.json 2>/dev/null; then
echo "❌ ADR-004 違規: 禁止 Redux"
exit 1
fi
# 檢查 3: 禁止 import 舊專案
if grep -rE "from ['\"].*wooo-aiops" apps/ packages/ 2>/dev/null; then
echo "❌ 禁止 import 舊專案"
exit 1
fi
echo "✅ ADR 檢查通過"
# Phase 14.2 #96: 後端分層檢查 (輕量版 import-linter)
- name: API Layer Check
run: |
echo "🔍 檢查後端分層規則..."
# 檢查 1: services 層禁止引用 api/routers 層 (反向依賴)
if grep -rE "from src\.(api|routers)" apps/api/src/services/ 2>/dev/null; then
echo "❌ 分層違規: services 禁止引用 api/routers 層"
exit 1
fi
# 檢查 2: repositories 層禁止引用 services 層
if grep -rE "from src\.services" apps/api/src/repositories/ 2>/dev/null; then
echo "❌ 分層違規: repositories 禁止引用 services 層"
exit 1
fi
# 檢查 3: models 層禁止引用業務層
if grep -rE "from src\.(services|api|routers)" apps/api/src/models/ 2>/dev/null; then
echo "❌ 分層違規: models 禁止引用業務層"
exit 1
fi
echo "✅ 後端分層檢查通過"
# ==================== Test ====================
test:
name: Test
runs-on: [self-hosted, harbor, k8s]
needs: lint
timeout-minutes: 15
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, harbor, k8s]
needs: lint
timeout-minutes: 15
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_PUBLIC_API_URL: https://awoooi.wooo.work
# Sentry DSN (透過 /api/sentry-tunnel 避免區域網路權限問題)
NEXT_PUBLIC_SENTRY_DSN: http://da02d4e5d6542e4d1ed6b2dd6542efeb@192.168.0.110:9000/2
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 Lint (Python) ====================
api-lint:
name: API Lint
runs-on: [self-hosted, harbor, k8s]
needs: pre-flight
timeout-minutes: 5
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 & Lint
working-directory: apps/api
run: |
uv sync
uv run ruff check .
- name: Type check
working-directory: apps/api
run: uv run mypy src/ --exclude 'tests/|scripts/' || true
continue-on-error: true
# ==================== API Test ====================
api-test:
name: API Test
runs-on: [self-hosted, harbor, k8s]
needs: api-lint
timeout-minutes: 10
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 & Test
working-directory: apps/api
env:
PYTHONPATH: ${{ github.workspace }}/apps/api
run: |
uv sync
uv run pytest tests/ --cov=src --cov-report=xml -v || true
continue-on-error: true
# ==================== Ollama Model Test (Phase 12.3 #67) ====================
# 🤖 自動化模型回歸測試 - 確保 OpenClaw 提案品質
ollama-test:
name: Ollama Model Test
runs-on: [self-hosted, harbor, k8s]
needs: api-lint
timeout-minutes: 5
continue-on-error: true # 不阻塞主 Pipeline
steps:
- uses: actions/checkout@v4
- name: Test Ollama Connectivity
run: |
echo "🔗 測試 Ollama 連線..."
if curl -s --connect-timeout 5 http://192.168.0.188:11434/api/tags > /dev/null; then
echo "✅ Ollama 可達"
# 使用 Python 替代 jq (Runner 未安裝 jq)
curl -s http://192.168.0.188:11434/api/tags | python3 -c "import sys,json; [print(m['name']) for m in json.load(sys.stdin).get('models',[])]"
else
echo "⚠️ Ollama 無法連線 (192.168.0.188:11434)"
exit 0 # 不失敗,只警告
fi
- name: Model Smoke Test
run: |
echo "🧪 模型冒煙測試..."
# 使用 Python 替代 jq
RESPONSE=$(curl -s --max-time 60 http://192.168.0.188:11434/api/generate -d '{
"model": "qwen2.5:7b-instruct",
"prompt": "你是 AIOps 助手。回答1+1=?",
"stream": false
}' | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('response','ERROR'))" 2>/dev/null || echo "ERROR")
if [ "$RESPONSE" != "ERROR" ] && [ -n "$RESPONSE" ]; then
echo "✅ 模型回應正常"
echo "回應: $RESPONSE"
else
echo "⚠️ 模型回應異常"
fi
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Action Parsing Test
working-directory: apps/api
env:
PYTHONPATH: ${{ github.workspace }}/apps/api
run: |
echo "🔍 Action Parsing 回歸測試..."
uv sync
uv run pytest tests/test_action_parsing.py -v --tb=short || echo "⚠️ 部分測試失敗"
# 🔴 LLM 測試移至 Nightly (2026-03-26)
# 原因: CPU 推理需 300+ 秒/測試,不適合每次 commit
# 完整測試: .github/workflows/nightly-llm.yaml
- name: LLM Test (Skip - See Nightly)
run: |
echo "⏭️ LLM 測試已移至 Nightly workflow"
echo " - test_model_regression.py"
echo " - test_prompt_validation.py"
echo " 原因: CPU 推理 ~300s/測試"
# ==================== OpenAPI Validation ====================
openapi-validate:
name: OpenAPI Validate
runs-on: [self-hosted, harbor, k8s]
needs: pre-flight
timeout-minutes: 3
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Validate
run: |
# 修復 ENOTEMPTY npm 錯誤 - 先清理舊目錄
rm -rf $(npm root -g)/@stoplight/spectral-cli 2>/dev/null || true
npm install -g @stoplight/spectral-cli || npm install -g @stoplight/spectral-cli
spectral lint docs/api/api-contract.yaml || true
# ==================== Docker Build Verify ====================
# 🚀 優化 (2026-03-24): 只在 PR 時執行main push 跳過 (CD 會構建)
docker-build:
name: Docker Verify
runs-on: [self-hosted, harbor, k8s]
needs: [test, api-test, build]
if: github.event_name == 'pull_request'
timeout-minutes: 20
strategy:
matrix:
app: [web, api]
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build (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
NEXT_PUBLIC_SENTRY_DSN=http://da02d4e5d6542e4d1ed6b2dd6542efeb@192.168.0.110:9000/2
cache-from: type=gha
cache-to: type=gha,mode=max