Skip to content

v6.1.0

Latest

Choose a tag to compare

@windischb windischb released this 02 Jun 22:52
6c79b28

Minor, fully additive release — no breaking changes, drop-in over 6.0.0. Four new configuration file formats, Kubernetes ConfigMap / Secret support, and a provider hardening pass.

✨ New file-format providers

All four sit on a shared, reusable FileBackedProvider base, so they get the same reactive file-watching, path-traversal protection, and per-file debounce as the JSON file provider.

YAML — new opt-in package Cocoar.Configuration.Yaml (YamlDotNet). Plain scalars map to their JSON types (true→bool, 42→number, null/~→null); quoted/block scalars stay strings.

rules.For<AppSettings>().FromYamlFile("appsettings.yaml")

TOML — new opt-in package Cocoar.Configuration.Toml (Tomlyn). TOML is strongly typed, so values map unambiguously to JSON (incl. arrays-of-tables → arrays of objects; dates → ISO-8601 strings).

rules.For<AppSettings>().FromTomlFile("appsettings.toml")

dotenv and INI — built into the core package, no extra dependency:

rules.For<AppSettings>().FromDotEnv()            // .env: KEY=value, # comments, export, quotes, :/__ nesting
rules.For<AppSettings>().FromIniFile("app.ini")  // [section] headers, ;/# comments, ./: nesting

INI keeps inline ;/# inside values intact (only whole-line comments are stripped), so connection strings survive.

☸️ Kubernetes ConfigMap / Secret support

A ConfigMap/Secret-mounted file is a symlink whose content is updated by an atomic swap of a sibling ..data symlink — not by rewriting the file. Opt in with followSymlinks (default off) on any file provider:

rules.For<AppSettings>().FromFile("/etc/config/appsettings.json", followSymlinks: true)
// also on FromYamlFile / FromTomlFile / FromDotEnv / FromIniFile
  • Reads the symlinked file — the resolved final target must still resolve within the configured directory, so an escaping symlink is rejected (the path-traversal protection holds).
  • Hot-reloads on the atomic ..data swap (via Cocoar.FileSystem 2.3.0 symlink-target tracking), even though the watched file's name and timestamp never change. Detection rides on the directory watcher's periodic re-scan — expect propagation within roughly a minute, in line with how Kubernetes itself rolls ConfigMap updates.

Default behaviour is unchanged: symlinks remain rejected as defense in depth.

🛠️ Provider hardening & internals

  • Observable provider: fetch no longer hangs on a cold / complete-without-emit source, and no longer leaks its one-shot subscription.
  • HTTP provider: the HttpResponseMessage is disposed after fetch; opt-in SseReadIdleTimeout reconnects a half-open SSE stream.
  • Extracted the reusable FileBackedProvider base (watch / path+symlink security / debounce / dispose) shared by all file formats; FileSourceProvider is now a thin subclass.
  • Documented the provider-contract invariants; parameterless FromCommandLine(); FileSourceProvider.Dispose made race-safe; removed dead MicrosoftConfigurationSource* code (the FromMicrosoftSource API was dropped in 6.0.0).

📦 Packages

All packages release as 6.1.0.

  • New: Cocoar.Configuration.Yaml (YamlDotNet), Cocoar.Configuration.Toml (Tomlyn).
  • dotenv and INI ship inside the core Cocoar.Configuration package (no new dependency).
  • Cocoar.FileSystem dependency bumped 2.2.0 → 2.3.0 (adds opt-in symlink-target tracking).