Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Install (locked deps + dev extras)
run: uv sync --extra dev --python ${{ matrix.python-version }}
run: uv sync --locked --extra dev --python ${{ matrix.python-version }}

- name: Lint (ruff)
run: uv run ruff check src tests
Expand Down
18 changes: 12 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ ENV PYTHONUNBUFFERED=1 \

WORKDIR /app

# uv for fast, reproducible installs.
RUN pip install --no-cache-dir uv

# Install dependencies + the package (bundled idc-index-data Parquet comes along).
COPY pyproject.toml README.md ./
# uv for fast, reproducible installs. Pinned so the lock export below behaves the same every build.
RUN pip install --no-cache-dir uv==0.12.24

# Install dependencies + the package (bundled idc-index-data Parquet comes along). Dependencies come
# from uv.lock, not pyproject.toml's lower bounds, so the image ships exactly the versions CI tested
# and pip-audit scanned, and rebuilding a commit is deterministic. --frozen fails rather than
# re-resolving; CI's `uv sync --locked` already guarantees the lock matches pyproject.toml.
COPY pyproject.toml uv.lock README.md ./
COPY src ./src
RUN uv pip install --system .
RUN uv export --frozen --no-dev --no-emit-project --format requirements-txt > /tmp/requirements.txt \
&& uv pip install --system -r /tmp/requirements.txt \
&& uv pip install --system --no-deps . \
&& rm /tmp/requirements.txt

# Bake the read-only DuckDB file at build time so cold starts are instant. With no argument,
# build_database_file includes ALL specialized indices (seg/ann/sm/ct/mr/pt, clinical, …),
Expand Down
14 changes: 8 additions & 6 deletions dev/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,13 @@ python3 dev/smoke_openapi_examples.py "$URL"

## 5. Updating for a new IDC release

The image bakes whatever `idc-index-data` resolves at build time. To publish a new IDC version,
**rebuild and redeploy** (steps 2–3). For reproducibility, pin the version in
The image installs dependencies from [uv.lock](../uv.lock) (see [Dockerfile](../Dockerfile)), so
it bakes exactly the `idc-index-data` the lock records and a rebuild of the same commit is
deterministic. To move IDC versions, bump the exact `idc-index` pin in
[pyproject.toml](../pyproject.toml) (e.g. `idc-index==0.13.1`, which pulls a specific
`idc-index-data`) so a rebuild is deterministic; bump the pin to move IDC versions. The running
version is always reported at `/v3/version`.
`idc-index-data`), run `uv lock` and commit both files — CI's `uv sync --locked` fails if the lock
is stale — then **rebuild and redeploy** (steps 2–3). The running version is always reported at
`/v3/version`.

## Optional: remote MCP service (HTTP)

Expand Down Expand Up @@ -246,8 +248,8 @@ boundary and never cross it the wrong way:
- **dev** is *outside* the boundary and self-contained: it builds its own image into the **dev**
project's registry and deploys it. Nothing dev produces is ever promoted onward.
- **test** builds the **canonical** image into the **test** project's registry and deploys it
(test doubles as UAT). Pinning `idc-index` in [pyproject.toml](../pyproject.toml) keeps that
build deterministic.
(test doubles as UAT). Installing from [uv.lock](../uv.lock) keeps that build
deterministic.
- **prod** deploys **test's exact image by immutable `@sha256:` digest**, referencing test's
registry directly — no rebuild, no copy — so prod runs the bytes test validated. prod's deployer
SA and Cloud Run service agent are granted read on test's Artifact Registry (the only
Expand Down
3 changes: 2 additions & 1 deletion dev/developer_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ Fixtures live in [tests/conftest.py](../tests/conftest.py): `ctx` (the core

[`.github/workflows/ci.yml`](../.github/workflows/ci.yml) runs on pushes to `main`
(and manual dispatch) and on PRs that touch `src/idc_api/**`, `tests/**`, `pyproject.toml`,
or `uv.lock`. It installs locked deps with `uv sync --extra dev`, then lints, scans, and tests on
or `uv.lock`. It installs locked deps with `uv sync --locked --extra dev` — failing if `uv.lock`
is stale, so run `uv lock` after editing dependencies — then lints, scans, and tests on
Python 3.11 and 3.12. CI needs no secrets or GCP; its first test run
downloads the specialized indices (`IDC_API_INCLUDE_INDICES=all` by default — set `none` to run
from bundled data only). Before pushing, run the same checks locally:
Expand Down
9 changes: 4 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ dependencies = [
# Query engine + data.
# idc-index is pinned EXACTLY, unlike every other dependency here, because it transitively
# pins idc-index-data (0.13.1 -> 25.0.1) — which *is* the IDC data release this server
# advertises at /v3/version and documents in the changelog. The production image installs
# from this file alone (the Dockerfile copies pyproject.toml and src, never uv.lock), so a
# lower bound would let a rebuild of this very commit bake a later IDC release than the one
# it claims to serve. Bump this pin to move IDC versions — see dev/deployment.md
# § Updating for a new IDC release.
# advertises at /v3/version and documents in the changelog. The image installs from uv.lock,
# so the lock alone already fixes it; the exact pin keeps the served IDC release explicit
# here and stops a routine `uv lock --upgrade` from silently moving it. Bump this pin (then
# `uv lock`) to move IDC versions — see dev/deployment.md § Updating for a new IDC release.
"idc-index==0.13.1",
"duckdb>=1.5.5",
"pyarrow>=25.0.0",
Expand Down
Loading