Files
awoooi/.github/workflows/ci.yaml
OG T cd7d63eeb1 feat(cicd): Add OTEL tracing to SignOz for CI/CD monitoring
- CI: awoooi-ci service with sha + ci environment
- CD: awoooi-cd service with sha + production environment
- Exports to SignOz at 192.168.0.121:4318

Approved: 2026-03-24 統帥指令

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-24 16:03:37 +08:00

265 lines
7.2 KiB
YAML

# =============================================================================
# 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 批准)
OTEL_EXPORTER_OTLP_ENDPOINT: http://192.168.0.121:4318
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
- 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)
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 檢查通過"
# ==================== 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 (會觸發區域網路權限對話框)
# TODO: 實作 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
# ==================== 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: |
npm install -g @stoplight/spectral-cli
spectral lint docs/api/api-contract.yaml || true
# ==================== Docker Build Verify ====================
docker-build:
name: Docker Verify
runs-on: [self-hosted, harbor, k8s]
needs: [test, api-test, build]
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