fix(ci+docker): install from uv.lock — stop resolving dependencies at build time #81

Merged
bvandeusen merged 4 commits from dev into main 2026-07-28 13:04:24 -04:00
2 changed files with 70 additions and 59 deletions
Showing only changes of commit a47e1b9c4e - Show all commits
+11 -11
View File
@@ -40,6 +40,9 @@ on:
- "frontend/**"
- "tests/**"
- "pyproject.toml"
# The lock now determines what gets installed, so a lock-only change has
# to trigger a run — otherwise a dependency bump lands untested.
- "uv.lock"
- "alembic/**"
- "alembic.ini"
- "Dockerfile"
@@ -140,19 +143,16 @@ jobs:
# red with no repo change (issue #2194). Green CI has to mean "these exact
# versions passed", or it isn't evidence of anything.
#
# `--frozen`, not `--locked`, and that difference is a known gap: --locked
# additionally fails when the lock is STALE against pyproject, which is the
# guard that would catch someone editing a dependency without re-locking.
# It can't be turned on until uv.lock is regenerated with `uv lock` — the
# mcp cap edited pyproject, so the lock no longer matches, and this
# workstation has no uv (or pip) to regenerate it with. --frozen still
# delivers the reproducibility this fix is for; a forgotten re-lock shows
# up as a loud ImportError rather than a silent version drift. Flip to
# --locked in the same change that regenerates the lock.
# `--locked` also FAILS when uv.lock is stale against pyproject, so a
# dependency edit has to go through a deliberate `uv lock` — it can't
# arrive on its own. That check earned its place immediately: it caught
# that the lock had been missing `pgvector` entirely (added to pyproject,
# never re-locked), which the old install path had been silently papering
# over by resolving from pyproject instead.
- name: Install locked dependencies
env:
UV_PROJECT_ENVIRONMENT: /opt/venv
run: uv sync --frozen --extra dev
run: uv sync --locked --extra dev
- name: Run tests
# Integration tests (real Postgres) run in the `integration` job below.
@@ -197,7 +197,7 @@ jobs:
- name: Install locked dependencies
env:
UV_PROJECT_ENVIRONMENT: /opt/venv
run: uv sync --frozen --extra dev
run: uv sync --locked --extra dev
- name: Integration suite (resolve service IP, migrate, test)
run: |
set -eux
Generated
+59 -48
View File
@@ -354,54 +354,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
]
[[package]]
name = "scribe"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "aiosmtplib" },
{ name = "alembic" },
{ name = "apscheduler" },
{ name = "asyncpg" },
{ name = "bcrypt" },
{ name = "caldav" },
{ name = "fastembed" },
{ name = "httpx" },
{ name = "hypercorn" },
{ name = "icalendar" },
{ name = "mcp", extra = ["cli"] },
{ name = "quart" },
{ name = "sqlalchemy", extra = ["asyncio"] },
]
[package.optional-dependencies]
dev = [
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "ruff" },
]
[package.metadata]
requires-dist = [
{ name = "aiosmtplib", specifier = ">=3.0" },
{ name = "alembic", specifier = ">=1.13" },
{ name = "apscheduler", specifier = ">=3.10,<4.0" },
{ name = "asyncpg", specifier = ">=0.29" },
{ name = "bcrypt", specifier = ">=4.0" },
{ name = "caldav", specifier = ">=1.3" },
{ name = "fastembed", specifier = ">=0.4" },
{ name = "httpx", specifier = ">=0.27" },
{ name = "hypercorn", specifier = ">=0.17" },
{ name = "icalendar", specifier = ">=5.0" },
{ name = "mcp", extras = ["cli"], specifier = ">=1.0,<2" },
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" },
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.23" },
{ name = "quart", specifier = ">=0.19" },
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.6" },
{ name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0" },
]
provides-extras = ["dev"]
[[package]]
name = "fastembed"
version = "0.8.0"
@@ -1038,6 +990,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
]
[[package]]
name = "pgvector"
version = "0.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a7/ec/6eb80aebc728200f95229219882994c1b0585b956ca47da5edb9d062627a/pgvector-0.5.0.tar.gz", hash = "sha256:07a9dcf735696879406983afc6eba9a787cef7c0cf6c367ca1a5779f036dee74", size = 35170, upload-time = "2026-07-06T18:27:27.767Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/e4/a5573f2c579ca9ad133293bfb624148ba0893674ca4a6eeec85ced9a6a09/pgvector-0.5.0-py3-none-any.whl", hash = "sha256:fedc9800894e6da2be51358d7b7c574bf34f247ca741a5a09513622135f5964f", size = 30958, upload-time = "2026-07-06T18:27:26.797Z" },
]
[[package]]
name = "pillow"
version = "12.2.0"
@@ -1496,6 +1457,56 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/58/ed/dea90a65b7d9e69888890fb14c90d7f51bf0c1e82ad800aeb0160e4bacfd/ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188", size = 11035607, upload-time = "2026-04-09T14:05:47.593Z" },
]
[[package]]
name = "scribe"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "aiosmtplib" },
{ name = "alembic" },
{ name = "apscheduler" },
{ name = "asyncpg" },
{ name = "bcrypt" },
{ name = "caldav" },
{ name = "fastembed" },
{ name = "httpx" },
{ name = "hypercorn" },
{ name = "icalendar" },
{ name = "mcp", extra = ["cli"] },
{ name = "pgvector" },
{ name = "quart" },
{ name = "sqlalchemy", extra = ["asyncio"] },
]
[package.optional-dependencies]
dev = [
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "ruff" },
]
[package.metadata]
requires-dist = [
{ name = "aiosmtplib", specifier = ">=3.0" },
{ name = "alembic", specifier = ">=1.13" },
{ name = "apscheduler", specifier = ">=3.10,<4.0" },
{ name = "asyncpg", specifier = ">=0.29" },
{ name = "bcrypt", specifier = ">=4.0" },
{ name = "caldav", specifier = ">=1.3" },
{ name = "fastembed", specifier = ">=0.4" },
{ name = "httpx", specifier = ">=0.27" },
{ name = "hypercorn", specifier = ">=0.17" },
{ name = "icalendar", specifier = ">=5.0" },
{ name = "mcp", extras = ["cli"], specifier = ">=1.0,<2" },
{ name = "pgvector", specifier = ">=0.3" },
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" },
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.23" },
{ name = "quart", specifier = ">=0.19" },
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.6" },
{ name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0" },
]
provides-extras = ["dev"]
[[package]]
name = "shellingham"
version = "1.5.4"