Use !include and other YAML functions in scaffold templates
Two fields in the same scaffold template often need the exact same list of choices — a license
picker and a region list are both really just "options sourced from some small reference table."
Until now, that table had nowhere to live but inside scaffold.yaml itself, copied into every
field that needed it. And a value as simple as the current git branch, an environment variable, or
a random suffix had no path into a template at all, short of prompting the user for it by hand.
The Problem
Small pieces of reference data — license choices, region codes, a naming convention lookup — show
up constantly in real scaffold templates, and they rarely stay confined to one field. A select
field needs them as {label, value} options; a file elsewhere in the same template needs the raw
table to look values up by key. Duplicating that table by hand, once per field that needs it, means
every future edit has to find and update every copy — and a missed one quietly drifts out of sync
with the rest. Beyond reference data, templates also commonly need small dynamic values — the
user's git branch or commit SHA, an environment variable, a random suffix for a resource name —
with no way to derive any of them automatically.
The Fix
scaffold.yaml now resolves a set of Atmos YAML functions — the same
explicit-tag mechanism stack manifests already use — anywhere it currently accepts a literal
value: options:, a type: computed field's value:, or a matrix: axis.
!include/!include.rawpulls in a local or remote file, optionally reshaped with a YQ filter.!envreads an environment variable,!randomgenerates a random number, and!cwdreads the current working directory.- The
!git.*/!repo-rootfamily exposes the current git branch, commit SHA, repository name, and more. !literalpreserves a value exactly as written, bypassing scaffold's own template evaluation — useful when a value legitimately contains{{ }}and shouldn't be treated as a template expression.
spec:
fields:
- name: license
type: select
options: !include "./lib/licenses.yaml '. | to_entries | map({\"label\": .value.full_name, \"value\": .key})'"
- name: license_lookup
type: computed
value: !include ./lib/licenses.yaml
- name: branch
type: computed
value: !git.branch
A locally-included file that exists solely to be included is automatically excluded from generated
output, the same way scaffold.yaml itself is. atmos scaffold validate resolves everything too,
not just generate, so a missing file, a bad filter, or a malformed value is caught up front.
Not every YAML function is available here: anything that needs real stack, component, or backend
context (!terraform.state, !store, !secret, and similar) is rejected with a clear error
instead. A template's scaffold.yaml is often resolved just to show its name and description in
atmos scaffold list or the interactive picker — before a user has chosen or generated anything —
so only functions that are safe to run in that situation are supported.
The !exec function is excluded for a different reason: it needs no stack
context at all, but scaffold.yaml is resolved for every template configured in atmos.yaml just
to populate the list and picker, not only the one a user actually generates — so allowing shell
execution there would let any configured template, including a shared or vendored one, run
arbitrary code merely by being listed.
How to Use It
Add any of the functions above anywhere options:, a computed field's
value: (see Computed Fields), or a matrix axis
currently accepts a literal value. See the full
examples/scaffolding-yaml-functions
example, or the
Loading External Data with !include and Other YAML Functions
section of the atmos scaffold generate docs.
Get Involved
See the
atmos scaffold generate
docs for the full reference, or open an issue with
feedback.
