Skip to content

Merge an optional .eph.local override into each workspace #62

Description

@jssblck

Problem

Some workspace configuration is specific to one developer or checkout: local paths, ports, credentials, or an extra service used for debugging. Putting those values in the shared .eph file makes the committed configuration machine-specific. Copying the whole file into an ignored variant causes the copies to drift.

Load an optional .eph.local beside the workspace's base .eph and merge it into the base before validation, interpolation, or service planning.

Example

Committed .eph:

[postgres]
image=postgres:16-alpine
port=auto

[env]
LOG_LEVEL=info

Ignored .eph.local:

[postgres]
port=5432
volume=./local-seed:/docker-entrypoint-initdb.d

[mailpit]
image=axllent/mailpit:latest
port=8025

[env]
LOG_LEVEL=debug

The effective configuration keeps postgres.image, replaces postgres.port, adds postgres.volume, adds the mailpit section, and replaces LOG_LEVEL.

Merge semantics

  • A base .eph remains required for workspace discovery. .eph.local alone does not define a workspace.
  • Load .eph.local only from the directory containing the discovered base file.
  • Merge the files structurally before semantic validation and interpolation.
  • Match service sections by section name. Match properties within a service by property key, including named forms such as port.http and env.DEBUG.
  • Treat top-level variables and variables in [env] as one environment namespace, matching them by variable name.
  • When the override contains a key already present in the base section, replace the base value. When it contains a new key, add it. Add sections that exist only in the override.
  • For repeatable keys such as hooks and volume=, any occurrences in the override replace all occurrences of that key from the base. If the override omits the key, keep the base list.
  • Replaced items retain their base ordering. Append new keys and sections in override declaration order so service execution and eph env output remain deterministic.
  • Validate the effective merged configuration with the existing rules. An override may replace a base value, but it may not leave duplicate sources, invalid dependencies, or other illegal states in the result.
  • Preserve source file and line information through the merge so diagnostics identify whether an invalid value came from .eph or .eph.local.

If platform-specific overrides are also present, use this layer order:

  1. .eph
  2. matching platform override
  3. .eph.local

The local layer therefore has final precedence.

Acceptance criteria

  • Every command that loads workspace configuration uses the same effective merged file, including check, info, up, down, env, run, and dev.
  • eph check validates the merged result and reports both source paths when an error involves values from different layers.
  • eph info lists the configuration layers that were loaded, in precedence order.
  • Tests cover missing and present local files, replacement, new keys, new sections, environment variables, named properties, repeatable properties, deterministic ordering, invalid merged results, and source-aware diagnostics.
  • The user guide documents .eph.local, recommends adding it to .gitignore, explains that it may contain secrets, and defines the merge and precedence rules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    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