From 7f06033ee4a3fd4de9986f3faff1240514448a8c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 23:06:54 +0000 Subject: [PATCH 1/2] Fix Docker prod build: copy LICENSE before uv sync hatchling reads the LICENSE file declared in pyproject.toml (`license = { file = "LICENSE" }`) at build time. The builder stage only had pyproject.toml and uv.lock, causing: OSError: License file does not exist: LICENSE https://claude.ai/code/session_01TiXyp1vCmxNP2ewP4s1TGH --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bd03738..8d2808b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ CMD ["uv", "run", "pytest"] # ─── Builder: production deps only ──────────────────────────────────────────── FROM base AS builder -COPY pyproject.toml uv.lock* ./ +COPY pyproject.toml uv.lock* LICENSE ./ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --no-dev From 5fd12df665d0f9fe8db511ac3ba634b871a60167 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 6 Jun 2026 15:38:51 +0000 Subject: [PATCH 2/2] Fix Docker builder: use two-layer uv pattern for correct builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hatchling reads both README.md and LICENSE at package build time (declared in pyproject.toml as readme and license fields). Split the builder stage into two steps following uv's recommended Docker pattern: 1. uv sync --no-dev --no-install-project → external deps only (cached layer; invalidated only when pyproject.toml/uv.lock change) 2. Copy README.md + LICENSE + src/, then uv sync --no-dev → builds and installs the project with all required files present This also gives better layer caching: adding a dependency rebuilds step 1, changing source only rebuilds step 2. https://claude.ai/code/session_01TiXyp1vCmxNP2ewP4s1TGH --- Dockerfile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8d2808b..50f9da0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,11 +29,16 @@ CMD ["uv", "run", "pytest"] # ─── Builder: production deps only ──────────────────────────────────────────── FROM base AS builder -COPY pyproject.toml uv.lock* LICENSE ./ +# Install external deps first (cached when only src/ changes) +COPY pyproject.toml uv.lock* ./ RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --no-dev + uv sync --no-dev --no-install-project +# Install the project itself (hatchling reads README.md + LICENSE at build time) +COPY README.md LICENSE ./ COPY src/ ./src/ +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --no-dev # ─── Production: minimal runtime image ──────────────────────────────────────── FROM python:${PYTHON_VERSION}-slim-bookworm AS prod