Skip to content

feat(render): port service-local env interpolation to Deno #5

Description

@wax911

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:
    1. shell environment
    2. service env_file entries
    3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions