Background
local-stack cannot deploy committed stacks/*.yml directly because stack files intentionally keep ${VAR} placeholders unresolved. Docker Swarm does not load service-level env_file values for Compose-style interpolation, so stackctl must render service-local env values into .rendered/*.rendered.yml before deployment.
This issue ports the current Python render behavior into Deno.
Goals
Implement stackctl render and the underlying render engine.
Required behavior
- Load a stack YAML file.
- For each service, build an interpolation scope from:
- shell environment
- service
env_file entries
- service
environment
- Parse dotenv files.
- Recursively interpolate string values in service definitions.
- Preserve unresolved variables by default.
- Support strict mode that fails when unresolved placeholders remain.
- Write rendered output to the configured rendered directory.
- Preserve source stack files unchanged.
- Absolutize
env_file and bind mount paths so rendered files can safely live under .rendered/.
Interpolation forms
Must support current local-stack behavior:
${VAR}
${VAR-default}
${VAR:-default}
- plain
$VAR
Optional future-compatible support may include:
${VAR?error}
${VAR:?error}
${VAR+replacement}
${VAR:+replacement}
Do not block this issue on optional forms unless they are cheap and well tested.
CLI shape
stackctl render
stackctl render --stacks infrastructure
stackctl render --profile dev
stackctl render --strict
stackctl render --output-dir .rendered
stackctl render --override .stackctl/overrides/dev/infrastructure.yml
Acceptance criteria
- Rendering creates
.rendered/<stack>.rendered.yml.
- Source
stacks/<stack>.yml is never modified.
- Unresolved variables remain unchanged by default.
--strict exits non-zero and reports unresolved variable names.
env_file values are used for labels, commands, healthchecks, and nested service structures.
service.environment overrides matching env_file values.
- Unit tests cover dotenv parsing, variable substitution, default forms, plain
$VAR, unresolved preservation, strict failure, and path absolutization.
Non-goals
- Do not deploy from this command.
- Do not encrypt/decrypt secrets from this command.
- Do not mutate
.env files.
Validation
Run:
deno task test -- --filter render
stackctl render --config fixtures/local-stack-minimal/.stackctl --strict
Background
local-stackcannot deploy committedstacks/*.ymldirectly because stack files intentionally keep${VAR}placeholders unresolved. Docker Swarm does not load service-levelenv_filevalues for Compose-style interpolation, sostackctlmust render service-local env values into.rendered/*.rendered.ymlbefore deployment.This issue ports the current Python render behavior into Deno.
Goals
Implement
stackctl renderand the underlying render engine.Required behavior
env_fileentriesenvironmentenv_fileand bind mount paths so rendered files can safely live under.rendered/.Interpolation forms
Must support current local-stack behavior:
${VAR}${VAR-default}${VAR:-default}$VAROptional future-compatible support may include:
${VAR?error}${VAR:?error}${VAR+replacement}${VAR:+replacement}Do not block this issue on optional forms unless they are cheap and well tested.
CLI shape
Acceptance criteria
.rendered/<stack>.rendered.yml.stacks/<stack>.ymlis never modified.--strictexits non-zero and reports unresolved variable names.env_filevalues are used for labels, commands, healthchecks, and nested service structures.service.environmentoverrides matchingenv_filevalues.$VAR, unresolved preservation, strict failure, and path absolutization.Non-goals
.envfiles.Validation
Run:
deno task test -- --filter render stackctl render --config fixtures/local-stack-minimal/.stackctl --strict