Documentation
¶
Overview ¶
Package envutil holds the small, shared environment-handling helpers the build, deploy, and host-launch paths all need: a minimal .env parser and two env-overlay merges whose precedence is encoded in the name. Factoring them here ends a duplication where the same operation name (mergeEnv) meant opposite precedence in different packages.
Index ¶
- func Lookup(env []string, key string) string
- func MergeBaseWins(base []string, extra map[string]string) []string
- func MergeExtraWins(base []string, extra map[string]string) []string
- func ParseDotEnv(path string) (map[string]string, error)
- func ParseShellWins(raw string) map[string]struct{}
- func ShellAlwaysWins(key string) bool
- type EnvConflict
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Lookup ¶ added in v0.1.45
Lookup returns the value of key in a KEY=VALUE slice, or "" when absent.
func MergeBaseWins ¶
MergeBaseWins layers extra KEY=VALUE pairs onto a base os.Environ() slice with base winning on key conflict (so a developer's shell override always wins). Non-conflicting extras are appended. Returns a fresh slice safe to assign to cmd.Env.
func MergeExtraWins ¶
MergeExtraWins layers extra KEY=VALUE pairs onto a base os.Environ() slice with extra winning on key conflict. Used where the overlay (env_file / BuildEnv) is meant to be authoritative for the variables it declares and the parent process's env is background context. Returns a fresh slice safe to assign to cmd.Env.
func ParseDotEnv ¶
ParseDotEnv parses a .env file (KEY=VALUE per line, # comments, trailing whitespace trimmed) into a map. Quoted values ("VALUE", 'VALUE') have their outer quotes stripped. An optional leading "export " is stripped. Missing file returns os.ErrNotExist (wrapped) so callers can treat absence as non-fatal.
Intentionally minimal — we don't expand $VARS or `${VAR:-default}` shell features. Projects needing those should use direnv or a wrapper script; this helper is just enough for the common "DATABASE_URL=postgres://..." case the host-mode loop and the External deploy env_file overlay need.
func ParseShellWins ¶ added in v0.1.45
ParseShellWins reads the opt-out list (a comma-separated set of variable names) that lets the parent shell keep winning for specific keys.
func ShellAlwaysWins ¶ added in v0.1.45
ShellAlwaysWins reports whether the parent environment keeps this key regardless of what the project declares.
Types ¶
type EnvConflict ¶ added in v0.1.45
type EnvConflict struct {
Key string
Declared string
Shell string
// ShellWon is true when the key was explicitly opted out of the
// declared-wins rule, so the parent's value was kept.
ShellWon bool
}
EnvConflict records a key whose DECLARED value differed from the value already present in the parent environment.
func MergeDeclaredWins ¶ added in v0.1.45
func MergeDeclaredWins(base []string, extra map[string]string, shellWins map[string]struct{}) ([]string, []EnvConflict)
MergeDeclaredWins layers extra KEY=VALUE pairs onto a base os.Environ() slice with the DECLARED value winning on conflict, and reports every conflict it resolved.
This is the inverse of MergeBaseWins, and it is the right default for a declarative tool: a value the project states in its own configuration is a deliberate statement about how the process must run, while a matching name in the developer's shell is usually ambient and unrelated. Letting the ambient value win makes the declaration advisory — the project renders one config and the process runs with another, with nothing printed either way. forge already reached that conclusion for bind ports (see forceHostBindPorts) after the same class of desync; the failure is simply less visible for other keys. A real case: a TLS-intercepting proxy exports SSL_CERT_FILE into the shell, which in Go REPLACES the trust store, so every host child silently loses the roots its declared bundle supplied and outbound TLS fails for anything the proxy is not decrypting.
shellWins names the keys that keep the old behaviour, for the deliberate ad-hoc override the previous default served by accident.