Skip to main content

Module environment

Module environment 

Source
Expand description

Environments: named files of variables, and the substitution pass that puts them into a request.

An environment is one flat YAML file of name-to-value pairs, living at .sendra/environments/<name>.yaml inside a project:

base_url: https://staging.api.example.com
api_key: ${API_KEY}

Request and collection files reference those values with {{name}} inside url, headers (names and values), body, and the values of an assertions block. A value written as ${VAR} is read from the OS environment when it is used, so a file that names a secret can still be committed — the secret itself never is.

One top-level key is reserved rather than a variable: auth. An environment may carry a default Auth block — exactly the same shape Request::auth is — applied to every request run against it that sets no auth: of its own:

base_url: https://staging.api.example.com
auth:
  bearer: ${API_TOKEN}

See Environment::auth for the full precedence rule (a request’s own auth: fully replaces the environment’s, never merges with it) and Environment::apply for where it is filled in.

Two references, two syntaxes, on purpose. {{name}} only ever means “a variable from the environment file” and is only looked for in request files; ${VAR} only ever means “a variable from the OS environment” and is only looked for in environment-file values. Neither can appear where the other is resolved, so there is never a question of which of the two a given placeholder is, or of what order the two run in.

§Why substitution is a pass over the parsed request

Substitution happens after the YAML is parsed, walking the string fields of a Request, rather than as a find-and-replace over the raw file text before parsing. Text-level substitution is easier to write and wrong in ways that only show up on someone else’s machine:

  • A value can change the shape of the document. A token containing : or #, a multi-line PEM key, a body starting with - — each of those turns a valid file into a different (or invalid) one once pasted in as raw text. Post-parse, a value is a string that was already a string, and nothing it contains can add a key, end a block or start a comment.
  • It would make deny_unknown_fields and the collection rules run against text the author never wrote, so a parse error could point at a line that exists in no file, with a column that means nothing.
  • It would let {{var}} appear anywhere at all — in method, in half of a key name — which is a far larger contract than substitution is meant to make, and not one that could be walked back later.

The cost is that only the fields listed above are templated. method is a closed enum with no useful placeholder, and name is deliberately excluded because it is the selector sendra run <file> <name> matches on: a label that changed with the environment could not be typed on the command line. Inside assertions, values are templated but the keys that select part of the response — header names, JSON paths — are not, for a related reason: see Environment::apply_assertions.

§EnvironmentFile vs. Environment

Config splits into a ConfigFile (every field optional, because that optionality is the merge information) and a resolved Config because several config sources — project file, global file, CLI flags — merge into one. EnvironmentFile splits from Environment for a much narrower reason: it is purely the on-disk shape serde deserializes, while Environment additionally carries source, the per-run captured store, and (in tests) a stand-in OS environment — none of which come from the file itself. There is still no merging or layering here: one environment file, read once, is the whole story. EnvironmentFile exists for schemars to derive a real schema from (see xtask), not because a second environment file could combine with a first.

Structs§

Environment
A set of variables a request can be sent against.
EnvironmentFile
The on-disk shape of one environment file: every top-level key is a variable, except auth, which is reserved for an optional default Auth block — see the module docs and Environment::auth.

Constants§

DEFAULT_ENVIRONMENT_NAME
The environment name sendra run falls back to when --env is omitted.

Functions§

environment_path
Where the environment called name lives for the project rooted at root.
find_environment
Walk up from start_dir looking for .sendra/environments/<name>.yaml, returning the first one found.