From a63b71e9022d33d85107cce2c0a7de7923d3b8dc Mon Sep 17 00:00:00 2001 From: Chandrasekharan M Date: Wed, 18 Mar 2026 17:28:52 +0530 Subject: [PATCH 1/3] [FIX] Remove VERSION arg from Dockerfile base stages to fix CI cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ARG VERSION + LABEL version="${VERSION}" in the base stage caused every Docker layer's cache key to depend on the version tag. Since the tag changes every build (rc.245, rc.246, ...), BuildKit could never match cached layers — resulting in 0% cache hit rate for all Python services in CI. The frontend (55% cached) was unaffected because its Dockerfile has no ARG VERSION in any stage. Removed from: backend, prompt-service, platform-service, runner, x2text-service, worker-unified, tool-sidecar. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker/dockerfiles/backend.Dockerfile | 4 +--- docker/dockerfiles/platform.Dockerfile | 4 +--- docker/dockerfiles/prompt.Dockerfile | 4 +--- docker/dockerfiles/runner.Dockerfile | 4 +--- docker/dockerfiles/tool-sidecar.Dockerfile | 4 +--- docker/dockerfiles/worker-unified.Dockerfile | 4 +--- docker/dockerfiles/x2text.Dockerfile | 4 +--- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/docker/dockerfiles/backend.Dockerfile b/docker/dockerfiles/backend.Dockerfile index 122edd6ffe..6795fb0d50 100644 --- a/docker/dockerfiles/backend.Dockerfile +++ b/docker/dockerfiles/backend.Dockerfile @@ -1,10 +1,8 @@ # Use a specific version of Python slim image FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Backend Service Container" \ - version="${VERSION}" + description="Backend Service Container" # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 \ diff --git a/docker/dockerfiles/platform.Dockerfile b/docker/dockerfiles/platform.Dockerfile index 8e5cd9bacc..b500f1131c 100644 --- a/docker/dockerfiles/platform.Dockerfile +++ b/docker/dockerfiles/platform.Dockerfile @@ -1,10 +1,8 @@ # Use a specific version of Python slim image FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Platform Service Container" \ - version="${VERSION}" + description="Platform Service Container" ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ diff --git a/docker/dockerfiles/prompt.Dockerfile b/docker/dockerfiles/prompt.Dockerfile index f15a2fb054..bff43e538e 100644 --- a/docker/dockerfiles/prompt.Dockerfile +++ b/docker/dockerfiles/prompt.Dockerfile @@ -1,10 +1,8 @@ # Use a specific version of Python slim image FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Prompt Service Container" \ - version="${VERSION}" + description="Prompt Service Container" ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ diff --git a/docker/dockerfiles/runner.Dockerfile b/docker/dockerfiles/runner.Dockerfile index d2065c72b4..919072fa40 100644 --- a/docker/dockerfiles/runner.Dockerfile +++ b/docker/dockerfiles/runner.Dockerfile @@ -1,10 +1,8 @@ # Use a specific version of Python slim image FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Runner Service Container" \ - version="${VERSION}" + description="Runner Service Container" # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 \ diff --git a/docker/dockerfiles/tool-sidecar.Dockerfile b/docker/dockerfiles/tool-sidecar.Dockerfile index 7da04806d6..679e98b583 100644 --- a/docker/dockerfiles/tool-sidecar.Dockerfile +++ b/docker/dockerfiles/tool-sidecar.Dockerfile @@ -1,10 +1,8 @@ # Use Python 3.12.9-slim for minimal size FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Tool Sidecar Container" \ - version="${VERSION}" + description="Tool Sidecar Container" ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ diff --git a/docker/dockerfiles/worker-unified.Dockerfile b/docker/dockerfiles/worker-unified.Dockerfile index 202f71b699..5209f57783 100644 --- a/docker/dockerfiles/worker-unified.Dockerfile +++ b/docker/dockerfiles/worker-unified.Dockerfile @@ -1,10 +1,8 @@ # Unified Worker Dockerfile - Optimized for fast builds FROM python:3.12.9-slim AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="Unified Worker Container for All Worker Types" \ - version="${VERSION}" + description="Unified Worker Container for All Worker Types" # Set environment variables (CRITICAL: PYTHONPATH makes paths work!) ENV PYTHONDONTWRITEBYTECODE=1 \ diff --git a/docker/dockerfiles/x2text.Dockerfile b/docker/dockerfiles/x2text.Dockerfile index 4ef060dc2b..a3cdf96fcc 100644 --- a/docker/dockerfiles/x2text.Dockerfile +++ b/docker/dockerfiles/x2text.Dockerfile @@ -1,10 +1,8 @@ # Use a specific version of Python slim image FROM python:3.12-slim-trixie AS base -ARG VERSION=dev LABEL maintainer="Zipstack Inc." \ - description="X2Text Service Container" \ - version="${VERSION}" + description="X2Text Service Container" # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 \ From c71bd40f925cffbd5283ff12210dbb0e96b83852 Mon Sep 17 00:00:00 2001 From: Chandrasekharan M Date: Wed, 18 Mar 2026 19:03:49 +0530 Subject: [PATCH 2/3] [MISC] Trivial log message cleanup for cache testing Fix double period in backend health check log and remove ellipsis from prompt-service init log. Used to test Docker layer cache reuse after app code changes (ext-dependencies and nuitka-compile stages should remain cached). Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/health/views.py | 2 +- prompt-service/src/unstract/prompt_service/config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/health/views.py b/backend/health/views.py index 715b17902d..3fe441a8a5 100644 --- a/backend/health/views.py +++ b/backend/health/views.py @@ -11,5 +11,5 @@ @api_view(["GET"]) @require_http_methods(["GET"]) def health_check(request: Request) -> Response: - logger.debug("Verifying backend health..") + logger.debug("Verifying backend health") return Response(status=200) diff --git a/prompt-service/src/unstract/prompt_service/config.py b/prompt-service/src/unstract/prompt_service/config.py index 5edfb829ed..0930c76041 100644 --- a/prompt-service/src/unstract/prompt_service/config.py +++ b/prompt-service/src/unstract/prompt_service/config.py @@ -38,7 +38,7 @@ def create_app() -> Flask: log_level = getattr(logging, log_level, logging.INFO) app = Flask("prompt-service") app.logger.setLevel(log_level) - app.logger.info("Initializing Flask application...") + app.logger.info("Initializing Flask application") # Load plugins plugins_dir = Path(__file__).parent / "plugins" From 5b86f7e721b5349f705e0ea3f13ded91e96d358b Mon Sep 17 00:00:00 2001 From: Chandrasekharan M Date: Thu, 19 Mar 2026 20:38:48 +0530 Subject: [PATCH 3/3] [FEAT] Expose build version as UNSTRACT_APPS_VERSION env var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ARG VERSION + ENV UNSTRACT_APPS_VERSION at the end of the production stage in all Python Dockerfiles. This makes the build version available at runtime (os.environ["UNSTRACT_APPS_VERSION"]) without affecting layer caching — ARG is scoped to the production stage and placed after all expensive build steps. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker/dockerfiles/backend.Dockerfile | 4 ++++ docker/dockerfiles/platform.Dockerfile | 3 +++ docker/dockerfiles/prompt.Dockerfile | 3 +++ docker/dockerfiles/runner.Dockerfile | 3 +++ docker/dockerfiles/tool-sidecar.Dockerfile | 3 +++ docker/dockerfiles/worker-unified.Dockerfile | 4 ++++ docker/dockerfiles/x2text.Dockerfile | 3 +++ 7 files changed, 23 insertions(+) diff --git a/docker/dockerfiles/backend.Dockerfile b/docker/dockerfiles/backend.Dockerfile index 6795fb0d50..59cd98399f 100644 --- a/docker/dockerfiles/backend.Dockerfile +++ b/docker/dockerfiles/backend.Dockerfile @@ -78,4 +78,8 @@ RUN if [ -f requirements.txt ]; then \ EXPOSE 8000 +# Capture build version at the very end so it doesn't affect layer caching +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + ENTRYPOINT [ "./entrypoint.sh" ] diff --git a/docker/dockerfiles/platform.Dockerfile b/docker/dockerfiles/platform.Dockerfile index b500f1131c..31b66ce081 100644 --- a/docker/dockerfiles/platform.Dockerfile +++ b/docker/dockerfiles/platform.Dockerfile @@ -80,5 +80,8 @@ RUN uv sync --group deploy --locked && \ EXPOSE 3001 +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + # During debugging, this entry point will be overridden CMD [".venv/bin/gunicorn", "--bind", "0.0.0.0:3001", "--timeout", "300", "unstract.platform_service.run:app"] diff --git a/docker/dockerfiles/prompt.Dockerfile b/docker/dockerfiles/prompt.Dockerfile index bff43e538e..cca9161d81 100644 --- a/docker/dockerfiles/prompt.Dockerfile +++ b/docker/dockerfiles/prompt.Dockerfile @@ -95,4 +95,7 @@ RUN mkdir -p prompt-studio-data EXPOSE 3003 +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + CMD ["./entrypoint.sh"] diff --git a/docker/dockerfiles/runner.Dockerfile b/docker/dockerfiles/runner.Dockerfile index 919072fa40..520637d503 100644 --- a/docker/dockerfiles/runner.Dockerfile +++ b/docker/dockerfiles/runner.Dockerfile @@ -81,4 +81,7 @@ RUN if [ -f cloud_requirements.txt ]; then \ EXPOSE 5002 +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + CMD [ "./entrypoint.sh" ] diff --git a/docker/dockerfiles/tool-sidecar.Dockerfile b/docker/dockerfiles/tool-sidecar.Dockerfile index 679e98b583..08c22fdd5d 100644 --- a/docker/dockerfiles/tool-sidecar.Dockerfile +++ b/docker/dockerfiles/tool-sidecar.Dockerfile @@ -79,4 +79,7 @@ RUN uv sync --group deploy --locked && \ uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement - && \ chmod +x ./entrypoint.sh +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + CMD ["./entrypoint.sh"] diff --git a/docker/dockerfiles/worker-unified.Dockerfile b/docker/dockerfiles/worker-unified.Dockerfile index 5209f57783..05fa32063b 100644 --- a/docker/dockerfiles/worker-unified.Dockerfile +++ b/docker/dockerfiles/worker-unified.Dockerfile @@ -85,6 +85,10 @@ RUN uv sync --group deploy --locked && \ USER worker +# Capture build version at the very end so it doesn't affect layer caching +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + # Default command - runs the Docker-optimized worker script ENTRYPOINT ["/app/run-worker-docker.sh"] CMD ["general"] diff --git a/docker/dockerfiles/x2text.Dockerfile b/docker/dockerfiles/x2text.Dockerfile index a3cdf96fcc..abdc9d52b0 100644 --- a/docker/dockerfiles/x2text.Dockerfile +++ b/docker/dockerfiles/x2text.Dockerfile @@ -68,5 +68,8 @@ RUN uv sync --group deploy --locked && \ EXPOSE 3004 +ARG VERSION=dev +ENV UNSTRACT_APPS_VERSION=${VERSION} + # During debugging, this entry point will be overridden. CMD [".venv/bin/gunicorn", "--bind", "0.0.0.0:3004", "--timeout", "300", "run:app"]