fix(runtime): resolve every interpolatable field before lowering (#276) - #309
fix(runtime): resolve every interpolatable field before lowering (#276)#309pierrick-fonquerne wants to merge 1 commit into
Conversation
Only environment values and the command were resolved at runtime, while
image references, entrypoint, working directory, volumes, healthcheck and
Dockerfile build inputs were advertised and scanned as interpolatable but
never substituted. A manifest such as `image: "app:${env.TAG}"` passed
validation and then ran the literal reference. `entrypoint` was omitted
from both scanning and substitution entirely.
A single canonical field walk on the manifest resource now drives both the
read-only scan (reference validation and implicit dependency discovery) and
the in-place substitution, so the two can never drift and `entrypoint` is
covered. Interpolation runs before the resource is lowered to a
ContainerSpec: the plan keeps resources in their raw form and lowers them at
start time, after substitution, so the image, volume and healthcheck parsers
only ever see fully resolved values. This is what makes it possible to
interpolate a volume mapping at all, since the canonical volume parser
rejects the braces of an unresolved reference.
Because lowering moved to start time, spec-build failures (an invalid image
reference, port or volume mapping) now surface when the resource starts
rather than when the plan is built; both happen during `lightshuttle up`.
The `secrets check` scope is unchanged: it still reports only references in
fields that become container environment variables or command arguments,
not image or volume references.
Export still emits unresolved environment references verbatim; rewriting
them as deployment placeholders is left to a follow-up.
Team ReviewVerdict: DISCUSS 💬 · 0 confirmed · 6 contested 🇬🇧 EnglishOverview Strengths
🇫🇷 FrançaisVue d'ensemble Points forts
Agents: Correctness, Security, Architecture, Performance |
Summary
Runtime part of #276. Export placeholder rewriting is split to #308.
Only environment values and the command were substituted at runtime, while image references,
entrypoint, working directory, volumes, healthcheck and Dockerfile build inputs were advertised and scanned as interpolatable but never resolved.image: "app:${env.TAG}"passedvalidateand then ran the literal reference;entrypointwas omitted from both scanning and substitution.Root cause
Two lists had drifted:
ResourceKind::interpolatable_strings(scanning, drives validation and implicit dependency discovery) advertised nine field groups, while the runtime substitution resolved only two. Substitution also ran after lowering, so the parsed image/volume/healthcheck fields could not carry a resolved value back.Fix
interpolatable_fields_mutis the single enumeration of every interpolatable string.interpolatable_strings(read-only scan) and the newinterpolate_in_place(substitution) both derive from it, so scanning and substitution cannot drift.entrypointis now covered.ContainerSpeconly at start time. The canonical image, volume and healthcheck parsers therefore only ever see fully resolved values, which is what allows a volume mapping to be interpolated at all.Behaviour changes
lightshuttle up.lifecycle_plantest updated accordingly.secrets checkscope is unchanged: it still reports only references in fields that become container env vars or command arguments (regression guard F3 preserved).${env.*}verbatim; placeholder rewriting is export: emit deployment placeholders for unresolved ${env.*} references #308.Tests
interpolation_before_lowering.rs: a resource with${env.*}in image, env, volume, entrypoint, command, working dir and healthcheck is started; the started spec contains only resolved values.resource.rs: canonical-walk scan covers every field incl.entrypoint;interpolate_in_placeresolves them; a Dockerfile drift guard covers build inputs.lifecycle_plan.rs: an invalid port spec now surfaces at start.cargo fmt --check,cargo clippy --workspace --all-targets --all-features -- -D warnings, andcargo test --workspace --all-featuresall green locally.