From dee5fbee85e8aaa707fbe5fd4b5b0a93e899d4e0 Mon Sep 17 00:00:00 2001 From: YehoshuaSagron Date: Wed, 7 Oct 2026 09:45:35 +0300 Subject: [PATCH 1/2] Fix: Make the shim's guards expressions, not asserts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A RUN inherits the base image's ENV, and PYTHONOPTIMIZE strips asserts. With it set, the 1.34 floor that #1311 added vanished: a core from 1.31 to 1.33 was pinned to itself, uv landed on a starlette instrumentor for starlette<0.15, and the bake and attestation passed with instrumentation off at runtime. The floor is now `… or sys.exit(1)`; the attestation's three asserts go the same way, since they run under the image's ENV too. The install refusal no longer blames a missing contrib pairing when the pin is the default distro, where no pairing is involved; the RECIPE row says what each case means and what to do next. Follow-up to #1311, from its review. Assisted-By: Claude (Anthropic AI) Signed-off-by: YehoshuaSagron --- deploy/lineage-attach/Dockerfile.otel-shim | 8 +++++--- deploy/lineage-attach/RECIPE.md | 4 ++-- deploy/lineage-attach/build-otel-shim.sh | 10 ++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/deploy/lineage-attach/Dockerfile.otel-shim b/deploy/lineage-attach/Dockerfile.otel-shim index d8a084097..4ff60b452 100644 --- a/deploy/lineage-attach/Dockerfile.otel-shim +++ b/deploy/lineage-attach/Dockerfile.otel-shim @@ -67,8 +67,10 @@ COPY --from=ghcr.io/astral-sh/uv:0.9.24@sha256:816fdce3387ed2142e37d2e56e1b1b97c # `--system --break-system-packages` lets the install land in a non-venv # python too; both flags are inert when --python is a venv. ARG OTEL_CONTRIB_VERSION=0.65b0 -RUN pin="$("${VENV_PYTHON}" -c 'from importlib.metadata import version; v = version("opentelemetry-api"); \ - assert tuple(map(int, v.split(".")[:2])) >= (1, 34); print("opentelemetry-api==" + v)' 2>/dev/null)" \ +# The floor is an expression, not an `assert`: RUN inherits the base image's +# ENV, and PYTHONOPTIMIZE strips asserts. +RUN pin="$("${VENV_PYTHON}" -c 'from importlib.metadata import version; import sys; v = version("opentelemetry-api"); \ + tuple(map(int, v.split(".")[:2])) >= (1, 34) or sys.exit(1); print("opentelemetry-api==" + v)' 2>/dev/null)" \ || pin="opentelemetry-distro==${OTEL_CONTRIB_VERSION}"; \ echo "the bake is pinned to ${pin}"; \ uv pip install --no-cache --python "${VENV_PYTHON}" --system --break-system-packages "${pin}" \ @@ -81,7 +83,7 @@ RUN pin="$("${VENV_PYTHON}" -c 'from importlib.metadata import version; v = vers opentelemetry-instrumentation-aiohttp-client \ opentelemetry-instrumentation-urllib3 \ opentelemetry-instrumentation-threading \ - || { echo "REFUSING: the shim could not be installed alongside ${pin} (uv's error is above; if it found no solution, no contrib release is paired with that version)" >&2; exit 1; } + || { echo "REFUSING: the shim could not be installed alongside ${pin} (uv's error is above; RECIPE step 2 reads it)" >&2; exit 1; } # The install resolves into the app's OWN environment, so it may move a package # an app dependency pins (wrapt, deprecated, typing-extensions are the usual # suspects) — and the attestations import only OpenTelemetry, never the app. diff --git a/deploy/lineage-attach/RECIPE.md b/deploy/lineage-attach/RECIPE.md index aba8b0dce..f3e1d7b8a 100644 --- a/deploy/lineage-attach/RECIPE.md +++ b/deploy/lineage-attach/RECIPE.md @@ -55,8 +55,8 @@ attestation runs before the load and prints nothing when it passes). Fail `REFUSING to bake … already instruments …` (exit 3): the app instruments itself — go to step 3 **without** `APP_CONTAINER`/`APP_IMAGE` (capture only). Fail `REFUSING to bake … no runnable Python found` (exit 3): outside the shim's envelope (DESIGN "The envelope") — same, capture only; or pass the interpreter as arg 3 if you know it. Fail `REFUSING to bake … is not present locally` (exit 3): wrong `IMAGE` — see Inputs; nothing was built. -Fail `REFUSING: the shim could not be installed alongside …` (the build fails): no contrib release is paired with the app's `opentelemetry-api` (a core newer than its contrib release, or a package index that lags) — uv's own error is above the line. -Fail `ATTESTATION FAILED` (exit 4): the bake itself is broken (the image was not loaded) — read the assertion it prints; not an app property. +Fail `REFUSING: the shim could not be installed alongside …` (the build fails): uv's own error is above the line. Alongside `opentelemetry-api==…`: no contrib release is paired with the app's core yet (a core newer than its contrib release, or a package index that lags) — go to step 3 **without** `APP_CONTAINER`/`APP_IMAGE` (capture only) until the paired release reaches the index, then re-bake. Alongside `opentelemetry-distro==…` (the default, when the app carries no `opentelemetry-api` or one older than 1.34.0): the app's environment cannot take that release at all (uv says why, e.g. `depends on Python>=3.10`) — outside the envelope, capture only. +Fail `ATTESTATION FAILED` (exit 4): the bake itself is broken (the image was not loaded) — read the line it prints; not an app property. ## 3. Attach (once per Deployment) diff --git a/deploy/lineage-attach/build-otel-shim.sh b/deploy/lineage-attach/build-otel-shim.sh index d5e0b46ad..e19b97e00 100755 --- a/deploy/lineage-attach/build-otel-shim.sh +++ b/deploy/lineage-attach/build-otel-shim.sh @@ -249,7 +249,9 @@ build_image() { # Attestation: the bake proves itself before anything is loaded. Gate off, not # one opentelemetry module may load; gate on, the hook ran, the exporter -# selection is explicit, and the propagator injects a traceparent. +# selection is explicit, and the propagator injects a traceparent. No `assert` +# here: the interpreter runs under the image's own ENV, and PYTHONOPTIMIZE +# strips asserts. verify_inert() { if ! "$CONTAINER_TOOL" run --rm --network=none --entrypoint "$VENV_PYTHON" "$WRAPPER_TAG" -c ' import sys @@ -263,14 +265,14 @@ raise SystemExit("gate off, yet otel loaded: %s" % loaded if loaded else 0)'; th verify_propagates() { if ! "$CONTAINER_TOOL" run --rm --network=none -e LINEAGE_PROPAGATE=1 --entrypoint "$VENV_PYTHON" "$WRAPPER_TAG" -c ' import os, sys -assert "opentelemetry.instrumentation.auto_instrumentation" in sys.modules, "hook did not run" -assert os.environ.get("OTEL_TRACES_EXPORTER") is not None, "exporter selection not pinned" +"opentelemetry.instrumentation.auto_instrumentation" in sys.modules or sys.exit("hook did not run") +os.environ.get("OTEL_TRACES_EXPORTER") is not None or sys.exit("exporter selection not pinned") from opentelemetry import trace from opentelemetry.propagate import inject with trace.get_tracer("attest").start_as_current_span("attest"): carrier = {} inject(carrier) -assert "traceparent" in carrier, "propagator injects nothing: %r" % carrier'; then +"traceparent" in carrier or sys.exit("propagator injects nothing: %r" % carrier)'; then echo "ATTESTATION FAILED for ${WRAPPER_TAG}: gate on, but the hook did not come up." >&2 exit 4 fi From b4921b602829bc923587ca0ed8da229e2db8e74e Mon Sep 17 00:00:00 2001 From: YehoshuaSagron Date: Wed, 7 Oct 2026 16:02:14 +0300 Subject: [PATCH 2/2] docs: Say that uv's error names the install blocker The RECIPE row for the install refusal presented the missing paired release as the cause; it is the usual one, but uv's error is what identifies it. Assisted-By: Claude (Anthropic AI) Signed-off-by: YehoshuaSagron --- deploy/lineage-attach/RECIPE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/lineage-attach/RECIPE.md b/deploy/lineage-attach/RECIPE.md index f3e1d7b8a..83273323f 100644 --- a/deploy/lineage-attach/RECIPE.md +++ b/deploy/lineage-attach/RECIPE.md @@ -55,7 +55,7 @@ attestation runs before the load and prints nothing when it passes). Fail `REFUSING to bake … already instruments …` (exit 3): the app instruments itself — go to step 3 **without** `APP_CONTAINER`/`APP_IMAGE` (capture only). Fail `REFUSING to bake … no runnable Python found` (exit 3): outside the shim's envelope (DESIGN "The envelope") — same, capture only; or pass the interpreter as arg 3 if you know it. Fail `REFUSING to bake … is not present locally` (exit 3): wrong `IMAGE` — see Inputs; nothing was built. -Fail `REFUSING: the shim could not be installed alongside …` (the build fails): uv's own error is above the line. Alongside `opentelemetry-api==…`: no contrib release is paired with the app's core yet (a core newer than its contrib release, or a package index that lags) — go to step 3 **without** `APP_CONTAINER`/`APP_IMAGE` (capture only) until the paired release reaches the index, then re-bake. Alongside `opentelemetry-distro==…` (the default, when the app carries no `opentelemetry-api` or one older than 1.34.0): the app's environment cannot take that release at all (uv says why, e.g. `depends on Python>=3.10`) — outside the envelope, capture only. +Fail `REFUSING: the shim could not be installed alongside …` (the build fails): uv's own error is above the line and names the blocker; the two usual cases follow. Alongside `opentelemetry-api==…`: no contrib release is paired with the app's core yet (a core newer than its contrib release, or a package index that lags) — go to step 3 **without** `APP_CONTAINER`/`APP_IMAGE` (capture only) until the paired release reaches the index, then re-bake. Alongside `opentelemetry-distro==…` (the default, when the app carries no `opentelemetry-api` or one older than 1.34.0): the app's environment cannot take that release at all (uv says why, e.g. `depends on Python>=3.10`) — outside the envelope, capture only. Fail `ATTESTATION FAILED` (exit 4): the bake itself is broken (the image was not loaded) — read the line it prints; not an app property. ## 3. Attach (once per Deployment)