Skip to content

v0.x: the config stack a tool declares is its precedence

Spec 0204 makes the layer list a tool declares the order its configuration resolves in. Before it, the list said which layers a tool wired, and the order it gave was documentation: the store always appended the layers in the framework's order.

What changed

  • props.Tool.Config.Layers is the stack, lowest precedence first. The store appends each layer in exactly that order, so moving an entry moves its precedence. Unstated, it resolves to the framework default: defaults, files, project, env, flags.
  • Three orders are refused, by props.New, by the store and by the generator, because each makes a tool quietly unsafe:
    • defaults must be the lowest layer when present. A layer below the compiled-in defaults can never be read.
    • flags must be the highest layer when present. A layer above it means a flag the user passed does not take.
    • project must sit below env. The trust filter assumes a repository's file cannot outrank the environment.
  • props.Tool.ConfigLayers is deprecated. A tool still setting it resolves exactly as before: its layers, in the framework's order, whatever order it lists them in.
  • The manifest field moves. properties.config_layers becomes properties.config.layers. The first regenerate moves an existing list into the new field in the framework's order, logs the move with the other derived values, and renders the root as props.Tool{Config: props.ConfigSpec{Layers: ...}}. What the tool resolves does not change.
  • --config-layers and gtb set config.layers take an ordered list, lowest precedence first, and refuse the three orders above.

Config files in other formats

A config file's format now comes from its extension (spec 0204 D2), and every format except YAML is a link: pkg/config/formats/<format>, blank-imported from main, for toml, json, hcl, ini, xml, dotenv (.env) and properties.

  • A --config file with one of those extensions is refused unless the tool links the format. A .json file used to be read as YAML, which mostly worked because JSON is nearly a subset of YAML; it is now refused with a hint naming the link. Link pkg/config/formats/json, or rename the file to .yaml.
  • Any other extension is read as YAML, as before. ~/.mytool.conf keeps working.
  • An embedded ConfigPaths asset in another format is now decoded as that format. props.Assets merged a .toml asset and re-emitted it as TOML, which the store then read as YAML. The tool must link the format for the asset to be read.

Migrating a hand-written tool

Replace the deprecated field with the spec, in the order you want the layers to resolve:

// Before
props.Tool{ConfigLayers: []props.ConfigLayer{props.LayerFlags, props.LayerEnv, props.LayerFiles, props.LayerDefaults}}

// After
props.Tool{Config: props.ConfigSpec{Layers: []props.ConfigLayer{props.LayerDefaults, props.LayerFiles, props.LayerEnv, props.LayerFlags}}}

A list written highest-first, as in the example, has to be reversed. Written as it was, props.New refuses it because defaults is not the lowest layer.

Migrating a generated project

Run gtb regenerate project. Nothing else is needed.