diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c88015776..93a2602a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,13 +50,31 @@ jobs: with: python-version: '3.11' cache: 'pip' + cache-dependency-path: | + requirements.txt + requirements-ci.txt - name: 📦 Install dependencies run: | - pip install --upgrade pip - pip install -r requirements.txt - pip install flake8 pytest - - name: ✅ Run backend gate - run: ./scripts/ci_gate.sh + python -m pip install --upgrade pip + for attempt in 1 2 3; do + if python -m pip install -r requirements-ci.txt; then + break + fi + if [ "$attempt" -eq 3 ]; then + echo "Dependency install failed after ${attempt} attempts." >&2 + exit 1 + fi + echo "Dependency install attempt ${attempt} failed, retrying in 15s..." >&2 + sleep 15 + done + - name: ✅ Python syntax check + run: ./scripts/ci_gate.sh syntax + - name: ✅ Flake8 critical checks + run: ./scripts/ci_gate.sh flake8 + - name: ✅ Local deterministic checks + run: ./scripts/ci_gate.sh deterministic + - name: ✅ Offline test suite + run: ./scripts/ci_gate.sh offline-tests docker-build: name: docker-build diff --git a/requirements-ci.txt b/requirements-ci.txt new file mode 100644 index 000000000..e145b8351 --- /dev/null +++ b/requirements-ci.txt @@ -0,0 +1,6 @@ +# Backend CI dependencies. +-r requirements.txt + +# Test and lint tooling used by backend-gate. +flake8 +pytest diff --git a/requirements.txt b/requirements.txt index f4c8716dc..7bc0acaac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,8 @@ numpy>=1.24.0 # 数值计算 json-repair>=0.55.1 # JSON 修复 # AI 分析 -litellm>=1.80.10 # Unified LLM client (Gemini/Anthropic/OpenAI/DeepSeek etc.) +# PyPI project was quarantined on 2026-03-24; install from the upstream GitHub stable tag for now. +litellm @ https://github.com/BerriAI/litellm/archive/refs/tags/v1.82.3-stable.patch.2.tar.gz # Unified LLM client (Gemini/Anthropic/OpenAI/DeepSeek etc.) tiktoken>=0.8.0,<0.12.0 # BPE tokenizer for LLM token counting (pin <0.12 to avoid plugin registration issues, #537) openai>=1.0.0 # OpenAI SDK (transitive dependency of litellm, kept explicit) PyYAML>=6.0 # YAML parser for LITELLM_CONFIG support diff --git a/scripts/ci_gate.sh b/scripts/ci_gate.sh index 687879339..bfd85ffef 100755 --- a/scripts/ci_gate.sh +++ b/scripts/ci_gate.sh @@ -2,20 +2,58 @@ set -euo pipefail -echo "==> backend-gate: Python syntax check" -python -m py_compile main.py src/config.py src/auth.py src/analyzer.py src/notification.py -python -m py_compile src/storage.py src/scheduler.py src/search_service.py -python -m py_compile src/market_analyzer.py src/stock_analyzer.py -python -m py_compile data_provider/*.py +syntax_check() { + echo "==> backend-gate: Python syntax check" + python -m py_compile main.py src/config.py src/auth.py src/analyzer.py src/notification.py + python -m py_compile src/storage.py src/scheduler.py src/search_service.py + python -m py_compile src/market_analyzer.py src/stock_analyzer.py + python -m py_compile data_provider/*.py +} -echo "==> backend-gate: flake8 critical checks" -flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics +flake8_checks() { + echo "==> backend-gate: flake8 critical checks" + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics +} -echo "==> backend-gate: local deterministic checks" -./test.sh code -./test.sh yfinance +deterministic_checks() { + echo "==> backend-gate: local deterministic checks" + ./test.sh code + ./test.sh yfinance +} -echo "==> backend-gate: offline test suite" -python -m pytest -m "not network" +offline_test_suite() { + echo "==> backend-gate: offline test suite" + python -m pytest -m "not network" +} -echo "==> backend-gate: all checks passed" +run_all() { + syntax_check + flake8_checks + deterministic_checks + offline_test_suite + echo "==> backend-gate: all checks passed" +} + +phase="${1:-all}" + +case "$phase" in + all) + run_all + ;; + syntax) + syntax_check + ;; + flake8) + flake8_checks + ;; + deterministic) + deterministic_checks + ;; + offline-tests) + offline_test_suite + ;; + *) + echo "Usage: $0 [all|syntax|flake8|deterministic|offline-tests]" >&2 + exit 2 + ;; +esac