Skip to content

Commit 76714b8

Browse files
Pigbibicodex
andcommitted
build: use uv dependency lock
Co-Authored-By: Codex <noreply@openai.com>
1 parent 65b87de commit 76714b8

11 files changed

Lines changed: 1678 additions & 33 deletions

.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@
66
__pycache__
77
*.py[cod]
88
.env
9+
build
10+
dist
11+
*.egg-info
12+
.venv-*
13+
.ruff_cache

.github/workflows/ci.yml

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,12 @@ jobs:
8484
- name: Install dependencies
8585
run: |
8686
set -euo pipefail
87-
python -m pip install --upgrade pip
88-
# Install non-git deps via pyproject.toml (moved from requirements.txt)
89-
grep -vE "^\s*(#|$)|git\+" requirements.txt | xargs -r python -m pip install -c https://raw.githubusercontent.com/QuantStrategyLab/QuantPlatformKit/main/constraints.txt
90-
# Install git-based packages individually with --no-deps (editable installs below)
91-
grep 'git+' requirements.txt | while IFS= read -r pkg; do
92-
[ -n "$pkg" ] && python -m pip install --no-deps "$pkg"
93-
done
94-
python -m pip install pytest pytest-cov ruff
95-
87+
python -m pip install --upgrade pip uv
88+
uv sync --frozen --extra test --no-install-project
9689
- name: Smoke import pinned shared packages
9790
run: |
9891
set -euo pipefail
99-
python - <<'PY'
92+
uv run --no-sync python - <<'PY'
10093
from quant_platform_kit.common.port_adapters import CallableNotificationPort, CallablePortfolioPort
10194
from hk_equity_strategies import resolve_canonical_profile as resolve_hk_canonical_profile
10295
from us_equity_strategies import resolve_canonical_profile
@@ -110,17 +103,17 @@ jobs:
110103
- name: Install editable shared repositories
111104
run: |
112105
set -euo pipefail
113-
python -m pip install --no-deps -e external/QuantPlatformKit -e external/UsEquityStrategies -e external/UsEquitySnapshotPipelines
106+
uv pip install --no-deps -e external/QuantPlatformKit -e external/UsEquityStrategies -e external/UsEquitySnapshotPipelines
114107
115108
- name: Run ruff
116109
run: |
117110
set -euo pipefail
118-
ruff check --exclude external .
111+
uv run --no-sync ruff check --exclude external .
119112
120113
- name: Check QPK pin consistency
121-
run: python scripts/check_qpk_pin_consistency.py
114+
run: uv run --no-sync python scripts/check_qpk_pin_consistency.py
122115

123116
- name: Run unit tests
124117
run: |
125118
set -euo pipefail
126-
PYTHONPATH=. PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -q tests --ignore=tests/test_request_handling.py --ignore=tests/test_event_loop.py --ignore=tests/test_monitor_dispatcher.py --ignore=tests/test_notifications.py --ignore=tests/test_connect_timeout_alert.py || true
119+
PYTHONPATH=. PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 uv run --no-sync python -m pytest -q tests --ignore=tests/test_request_handling.py --ignore=tests/test_event_loop.py --ignore=tests/test_monitor_dispatcher.py --ignore=tests/test_notifications.py --ignore=tests/test_connect_timeout_alert.py || true

.github/workflows/sync-cloud-run-env.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,15 +302,14 @@ jobs:
302302
if: steps.config.outputs.env_sync_enabled == 'true'
303303
run: |
304304
set -euo pipefail
305-
python -m pip install --upgrade pip
306-
python -m pip install -r requirements.txt
307-
305+
python -m pip install --upgrade pip uv
306+
uv sync --frozen --no-dev --no-install-project
308307
- name: Resolve Cloud Run sync targets
309308
id: strategy_requirements
310309
if: steps.config.outputs.env_sync_enabled == 'true'
311310
run: |
312311
set -euo pipefail
313-
sync_plan_json="$(python scripts/build_cloud_run_env_sync_plan.py --json)"
312+
sync_plan_json="$(uv run --no-sync python scripts/build_cloud_run_env_sync_plan.py --json)"
314313
{
315314
echo "sync_plan_json<<__SYNC_PLAN_JSON__"
316315
printf '%s\n' "${sync_plan_json}"

Dockerfile

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ FROM python:3.12-slim-bookworm
22

33
ENV PYTHONUNBUFFERED=1 \
44
PIP_NO_CACHE_DIR=1 \
5+
UV_COMPILE_BYTECODE=1 \
6+
UV_NO_CACHE=1 \
7+
PATH="/app/.venv/bin:${PATH}" \
58
PORT=8080
69

710
WORKDIR /app
@@ -10,18 +13,16 @@ RUN apt-get update \
1013
&& apt-get install -y --no-install-recommends git \
1114
&& rm -rf /var/lib/apt/lists/*
1215

13-
COPY requirements.txt ./
14-
COPY constraints.txt ./
15-
RUN python -m pip install --upgrade pip \
16-
&& python -m pip install -r requirements.txt -c constraints.txt \
16+
COPY pyproject.toml uv.lock ./
17+
RUN python -m pip install --upgrade pip uv \
18+
&& uv sync --frozen --no-dev --no-install-project \
1719
&& apt-get purge -y git \
1820
&& apt-get autoremove -y --purge \
1921
&& rm -rf /var/lib/apt/lists/*
2022

21-
COPY . .
23+
RUN useradd --create-home --uid 1000 appuser
2224

23-
RUN useradd --create-home --uid 1000 appuser \
24-
&& chown -R appuser:appuser /app
25+
COPY --chown=appuser:appuser . .
2526
USER appuser
2627

2728
CMD ["gunicorn", "--bind", ":8080", "--workers", "1", "--threads", "1", "--timeout", "300", "main:app"]

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ Direct runtime profiles can usually run from market history or portfolio state.
4040
## Quick start
4141

4242
```bash
43-
python -m pip install -r requirements.txt
44-
python -m pytest -q
43+
uv sync --frozen --extra test --no-install-project
44+
uv run --no-sync ruff check --exclude external .
45+
uv run --no-sync python scripts/check_qpk_pin_consistency.py
4546
```
4647

4748
## Useful docs

README.zh-CN.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ InteractiveBrokersPlatform 是 QuantStrategyLab 的Interactive Brokers 多市场
4040
## 快速开始
4141

4242
```bash
43-
python -m pip install -r requirements.txt
44-
python -m pytest -q
43+
uv sync --frozen --extra test --no-install-project
44+
uv run --no-sync ruff check --exclude external .
45+
uv run --no-sync python scripts/check_qpk_pin_consistency.py
4546
```
4647

4748
## 延伸文档

pyproject.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@ name = "interactive-brokers-platform"
77
version = "0.1.0"
88
description = "QuantStrategyLab platform layer for Interactive Brokers."
99
requires-python = ">=3.11"
10+
dependencies = [
11+
"flask",
12+
"gunicorn",
13+
"pandas",
14+
"numpy",
15+
"requests",
16+
"pytz",
17+
"pandas-market-calendars",
18+
"ib-insync",
19+
"google-auth",
20+
"google-cloud-compute",
21+
"google-cloud-secret-manager",
22+
"google-cloud-storage",
23+
"yfinance",
24+
"quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@0063af3b4a974650ea58a7d3f26dd1b94f65d3e8",
25+
"us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@46887bc3f5454d5b59623b1f5efb7c65912c6b8b",
26+
"hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@61993bf261aeccf64b5a75428b9405f4e1d1d682",
27+
]
28+
29+
[project.optional-dependencies]
30+
test = [
31+
"pytest",
32+
"pytest-cov",
33+
"ruff",
34+
]
1035

1136
[tool.coverage.run]
1237
branch = true

tests/test_dependency_pin_guard.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,5 @@ def test_dependency_pin_guard_is_blocking_in_ci() -> None:
6161
next_step = workflow.find("\n - name:", step_start + 1)
6262
step = workflow[step_start : next_step if next_step != -1 else len(workflow)]
6363

64-
assert "python scripts/check_qpk_pin_consistency.py" in step
64+
assert "uv run --no-sync python scripts/check_qpk_pin_consistency.py" in step
6565
assert "continue-on-error" not in step

tests/test_sync_cloud_run_env_workflow.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ grep -Fq 'workload_identity_provider: ${{ env.GCP_WORKLOAD_IDENTITY_PROVIDER }}'
1313
grep -Fq 'service_account: ${{ env.GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT }}' "$workflow_file"
1414
grep -Fq 'uses: actions/checkout@v6' "$workflow_file"
1515
grep -Fq 'uses: actions/setup-python@v6' "$workflow_file"
16-
grep -Fq 'python -m pip install -r requirements.txt' "$workflow_file"
16+
grep -Fq 'uv sync --frozen --no-dev --no-install-project' "$workflow_file"
1717

1818
grep -Fq 'ENABLE_MAIN_PUSH_CLOUD_RUN_AUTOMATION: ${{ vars.ENABLE_MAIN_PUSH_CLOUD_RUN_AUTOMATION }}' "$workflow_file"
1919
grep -Fq 'target:' "$workflow_file"
@@ -69,6 +69,7 @@ grep -Fq 'STRATEGY_PLUGIN_ALERT_TELEGRAM_BOT_TOKEN: ${{ secrets.STRATEGY_PLUGIN_
6969

7070
grep -Fq 'Skipping Cloud Run automation because ENABLE_GITHUB_CLOUD_RUN_DEPLOY and ENABLE_GITHUB_ENV_SYNC are not true.' "$workflow_file"
7171
grep -Fq 'Skipping Cloud Run automation on push because ENABLE_MAIN_PUSH_CLOUD_RUN_AUTOMATION is not true.' "$workflow_file"
72+
grep -Fq 'uv run --no-sync python scripts/build_cloud_run_env_sync_plan.py --json' "$workflow_file"
7273
grep -Fq 'scripts/build_cloud_run_env_sync_plan.py --json' "$workflow_file"
7374
grep -Fq 'sync_plan_json<<__SYNC_PLAN_JSON__' "$workflow_file"
7475
grep -Fq 'SYNC_PLAN_JSON: ${{ steps.strategy_requirements.outputs.sync_plan_json }}' "$workflow_file"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from pathlib import Path
2+
3+
4+
def test_pyproject_declares_runtime_and_test_dependencies() -> None:
5+
pyproject = Path("pyproject.toml").read_text(encoding="utf-8")
6+
7+
assert "dependencies = [" in pyproject
8+
assert "quant-platform-kit @ git+https://github.com/QuantStrategyLab/" in pyproject
9+
assert "us-equity-strategies @ git+https://github.com/QuantStrategyLab/" in pyproject
10+
assert "hk-equity-strategies @ git+https://github.com/QuantStrategyLab/" in pyproject
11+
assert "[project.optional-dependencies]" in pyproject
12+
assert "test = [" in pyproject
13+
14+
15+
def test_ci_docker_and_env_sync_use_uv_lock() -> None:
16+
ci = Path(".github/workflows/ci.yml").read_text(encoding="utf-8")
17+
dockerfile = Path("Dockerfile").read_text(encoding="utf-8")
18+
env_sync = Path(".github/workflows/sync-cloud-run-env.yml").read_text(encoding="utf-8")
19+
lockfile = Path("uv.lock").read_text(encoding="utf-8")
20+
21+
assert lockfile.startswith("version = ")
22+
assert "uv sync --frozen --extra test --no-install-project" in ci
23+
assert "uv run --no-sync ruff check --exclude external ." in ci
24+
assert "uv run --no-sync python scripts/check_qpk_pin_consistency.py" in ci
25+
assert "uv sync --frozen --no-dev --no-install-project" in env_sync
26+
assert "uv run --no-sync python scripts/build_cloud_run_env_sync_plan.py --json" in env_sync
27+
assert "COPY pyproject.toml uv.lock ./" in dockerfile
28+
assert "uv sync --frozen --no-dev --no-install-project" in dockerfile
29+
assert "python -m pip install -r requirements.txt" not in dockerfile

0 commit comments

Comments
 (0)