chore: bootstrap repo tooling, dependency and quality gates
uv-managed PEP 621 project with ruff, mypy (strict on packages/domain and packages/llm), pytest with coverage, and import-linter contracts that mechanically enforce the dependency rules of 架构文档 §4.2 -- including the two forbidden edges (compliance and identity must not depend on business domains). CI, pre-commit and a detect-secrets baseline gate every push; .env is gitignored before anything is ever staged.
This commit is contained in:
Executable
+114
@@ -0,0 +1,114 @@
|
||||
# 架构文档 §16.2:这些防线是机器可执行的检查,任一失败即阻断合并。
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
UV_CACHE_DIR: /tmp/.uv-cache
|
||||
|
||||
jobs:
|
||||
quality-gate:
|
||||
name: lint / typecheck / import-linter / tests / secrets
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
env:
|
||||
POSTGRES_USER: meida
|
||||
POSTGRES_PASSWORD: meida
|
||||
POSTGRES_DB: meida_test
|
||||
ports: ["5432:5432"]
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U meida"
|
||||
--health-interval 5s
|
||||
--health-timeout 5s
|
||||
--health-retries 20
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports: ["6379:6379"]
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 5s
|
||||
--health-timeout 5s
|
||||
--health-retries 20
|
||||
|
||||
env:
|
||||
APP_ENV: dev
|
||||
JWT_SECRET: ci-only-not-a-real-secret-0123456789abcdef
|
||||
DATABASE_URL: postgresql+asyncpg://meida:meida@localhost:5432/meida_test
|
||||
REDIS_URL: redis://localhost:6379/0
|
||||
CELERY_BROKER_URL: redis://localhost:6379/1
|
||||
CELERY_RESULT_BACKEND: redis://localhost:6379/2
|
||||
DEEPSEEK_API_KEY: ci-placeholder-no-network-calls-in-ci
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python 3.12
|
||||
run: uv python install 3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --extra dev --frozen
|
||||
|
||||
# --- 防线 1: 静态检查 (ruff lint + format) ---
|
||||
- name: Ruff lint
|
||||
run: uv run ruff check --output-format=github .
|
||||
- name: Ruff format check
|
||||
run: uv run ruff format --check .
|
||||
|
||||
# --- 防线 2: mypy strict 覆盖 packages/domain 与 packages/llm ---
|
||||
- name: Mypy (strict scope)
|
||||
run: uv run mypy packages/domain packages/llm
|
||||
- name: Mypy (remaining scope)
|
||||
run: uv run mypy apps packages/shared packages/identity packages/billing packages/task packages/agent packages/compliance
|
||||
|
||||
# --- 防线 3: 分层依赖检查 (架构文档 §4.2) ---
|
||||
- name: Import contracts
|
||||
run: uv run lint-imports --verbose
|
||||
|
||||
# --- 防线 4: 单元测试 + 覆盖率 ---
|
||||
- name: Pytest
|
||||
run: uv run pytest --cov-report=xml
|
||||
|
||||
# --- 防线 5: 数据库迁移必须可正向执行并可回滚 (T-P1-06) ---
|
||||
- name: Alembic upgrade/downgrade round-trip
|
||||
run: |
|
||||
uv run alembic upgrade head
|
||||
uv run alembic downgrade base
|
||||
uv run alembic upgrade head
|
||||
|
||||
# --- 防线 6: 敏感信息扫描 ---
|
||||
- name: Secrets scan (detect-secrets)
|
||||
run: |
|
||||
uv run detect-secrets scan --baseline .secrets.baseline
|
||||
git diff --exit-code .secrets.baseline
|
||||
|
||||
- name: Gitleaks
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload coverage
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage
|
||||
path: coverage.xml
|
||||
if-no-files-found: ignore
|
||||
Reference in New Issue
Block a user