150 lines
5.1 KiB
YAML
150 lines
5.1 KiB
YAML
name: CI
|
|
|
|
# Runs on every push and every pull request. `build-practice-images.yml`
|
|
# (the k3s/ArgoCD production deploy path) triggers independently on push to
|
|
# master; until it is made to depend on this job, a red CI does NOT block a
|
|
# deploy — see docs/operations.md.
|
|
on:
|
|
push:
|
|
pull_request:
|
|
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
ai-service:
|
|
name: ai-service — ruff + pytest
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
# No lockfile exists for either Python project (docs/27-technical-debt.md
|
|
# D-07), so this mirrors apps/ai-service/Dockerfile's inline install. When
|
|
# a lockfile lands, replace this with an install from it.
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install \
|
|
"fastapi>=0.115,<1" \
|
|
"httpx>=0.27,<1" \
|
|
"psycopg[binary]>=3.2,<4" \
|
|
"pydantic-settings>=2.6,<3" \
|
|
"qdrant-client>=1.7,<2" \
|
|
"uvicorn[standard]>=0.30,<1" \
|
|
"prometheus-client>=0.20,<1" \
|
|
"opentelemetry-api>=1.27,<2" \
|
|
"opentelemetry-sdk>=1.27,<2" \
|
|
"opentelemetry-exporter-otlp-proto-http>=1.27,<2" \
|
|
"anthropic>=0.112,<1" \
|
|
"boto3" \
|
|
"pytest>=7.4,<9" \
|
|
"ruff"
|
|
|
|
- name: ruff
|
|
working-directory: apps/ai-service
|
|
run: ruff check .
|
|
|
|
# `tests/conftest.py` forces EMBEDDING_PROVIDER=disabled, because
|
|
# `main.py` builds the whole runtime at import time and would otherwise
|
|
# try to reach Qdrant during collection. No test needs a live datastore;
|
|
# `tests/test_live_datastores.py` gates itself behind RUN_INTEGRATION=1.
|
|
- name: pytest
|
|
working-directory: apps/ai-service
|
|
run: pytest tests -q
|
|
|
|
ingestion:
|
|
name: ingestion — pytest
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
# `ruff check` is not run here: `ingestion/pyproject.toml` declares no
|
|
# [tool.ruff] section, so ruff would apply its full default rule set and
|
|
# report ~426 pre-existing findings. Adding the same lint config
|
|
# apps/ai-service uses is tracked as follow-up work, not silenced here.
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -e "./ingestion[dev]"
|
|
|
|
- name: pytest
|
|
working-directory: ingestion
|
|
run: pytest tests -q
|
|
|
|
web:
|
|
name: web — lint + build
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "20"
|
|
|
|
# Same toolchain the production image uses (apps/web/Dockerfile).
|
|
- name: Enable pnpm
|
|
run: corepack enable
|
|
|
|
- name: Install
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
# api-gateway proxies /auth/* and nothing else (a single
|
|
# AuthProxyController). Preferring API_GATEWAY_URL in a RAG route
|
|
# therefore breaks chat, suggest, history, sections, section-text and
|
|
# feedback the moment apiGateway is enabled -- which is exactly what
|
|
# shipped in PR #27 and stayed invisible until the config was first
|
|
# rendered on 2026-08-19. Nothing else in CI would have caught it: the
|
|
# code compiles and lints fine, and it only misbehaves once a specific
|
|
# Helm value is set. Assert the boundary directly.
|
|
- name: Assert RAG routes never resolve through api-gateway
|
|
run: |
|
|
offenders=$(grep -rln 'API_GATEWAY_URL' apps/web/app/api/chat apps/web/app/api/suggest apps/web/app/api/history apps/web/app/api/sections apps/web/app/api/section-text apps/web/app/api/feedback || true)
|
|
if [ -n "$offenders" ]; then
|
|
echo "::error::RAG routes must use AI_SERVICE_URL, not API_GATEWAY_URL: $offenders"
|
|
exit 1
|
|
fi
|
|
# ...and auth must keep using it, or login silently talks to the
|
|
# wrong service instead.
|
|
grep -q 'API_GATEWAY_URL' apps/web/app/api/auth/login/route.ts
|
|
grep -q 'API_GATEWAY_URL' apps/web/app/api/auth/me/route.ts
|
|
|
|
- name: Lint
|
|
run: pnpm --filter @duoc-thu/web lint
|
|
|
|
- name: Build
|
|
run: pnpm --filter @duoc-thu/web build
|
|
|
|
auth-and-gateway:
|
|
name: auth-service + api-gateway — lint + build + test
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "20"
|
|
|
|
- name: Enable pnpm
|
|
run: corepack enable
|
|
|
|
- name: Install
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Lint
|
|
run: pnpm --filter @duoc-thu/auth-service --filter @duoc-thu/api-gateway lint
|
|
|
|
- name: Build
|
|
run: pnpm --filter @duoc-thu/auth-service --filter @duoc-thu/api-gateway build
|
|
|
|
- name: Test
|
|
run: pnpm --filter @duoc-thu/auth-service --filter @duoc-thu/api-gateway test
|