Variables Demo

VERSION a9b38ce
Variables Demo

Every meshfox:var setting, side by side — see SPEC.md's "Variables" section for the full writeup. All ten are declared once here, in the root node's own body:

A declaration on its own does nothing — only a block that opts in via its own env= attribute ever resolves or prompts for one, and only for whatever it actually references. Each node below demonstrates one setting in isolation by referencing just its own variable(s).

Plain default

GREETING has a default and no other flags — it's used silently, never prompted for, unless something overrides it (--set, the process environment, or an answer already sitting in the cache from a previous run).

echo "$GREETING, world"
exit code: 0

Hello, world
Required confirmation

INSTALL_PATH also has a default, but it's required — nothing but an explicit override/the environment/an already-cached answer is allowed to resolve it silently. The very first time this block runs, it's prompted for interactively, with /usr/local/bin offered as the prompt's own pre-filled suggestion (confirm with a bare Enter, or type something else). Whatever's answered is then cached, so every later run resolves straight from there — this is a one-time confirmation, not a standing "ask every run".

echo "installing to $INSTALL_PATH"
exit code: 0

installing to /usr/local/bin
Select, not required

LOG_LEVEL is type="select" with a default and no required — type only changes how a prompt is shown if one ever happens (a menu of choices instead of free text); it doesn't affect whether one happens. With a default present and no required, it resolves silently exactly like GREETING above.

echo "log level: $LOG_LEVEL"
exit code: 0

log level: info
Select, required

REGION combines type="select" with required — the two are independent axes (type is about how to ask, required is about whether a default gets to skip asking). First run shows a menu with us-east-1 pre-selected as the suggested answer; any confirmed choice is cached from then on.

echo "deploying to $REGION"
exit code: 0

deploying to us-east-1
Bool

VERBOSE is type="bool" with a default — a plain (non-required) boolean, so it resolves silently too; a prompt for it (had it been required, or had nothing else supplied a value) would ask y/n rather than free text.

echo "verbose: $VERBOSE"
exit code: 0

verbose: false
Int

RETRY_COUNT is type="int" with a default — same "resolves silently, type only shapes how a prompt would look" story as LOG_LEVEL/ VERBOSE above, except an int prompt/form field is validated: only something that actually parses as a whole number is ever accepted (a terminal prompt keeps re-asking, the web form blocks submit, the TUI's own field only lets you type digits and a leading +/- in the first place) — see meshfox_core::vars::validate_value. Unlike type's other values, this is real enforcement, not just a hint for how to ask.

echo "retrying up to $RETRY_COUNT time(s)"
exit code: 0

retrying up to 3 time(s)
Secret

API_TOKEN is secret — no default, never read from or written to the on-disk cache, never pre-filled anywhere. The only way to supply one without an interactive prompt is --set/the process environment; asked for fresh every single time some block's env= needs it, masked as it's typed. secret and required are independent flags, but in practice a secret variable is already "confirmed fresh" on every run regardless — it can never be silently reused from a cache the way a plain required variable's second run can.

Deliberately without cache here — caching would freeze a secret's value into this very file, defeating the point of it never being persisted anywhere.

echo "calling the API with a token ${#API_TOKEN} characters long"
Computed

RESOURCE_ID has from="computed/create" instead of a default — its value comes from actually running the create block below and reading back what it wrote to $MESHFOX_VARS_OUT (a NAME=value-per-line file meshfox hands every from= source block a fresh path to), not from any override/environment/cache/prompt. Running use-it automatically runs create first — from= is an implicit dependency, the same as an explicit deps= entry — and fails the whole run if create exits nonzero or never writes RESOURCE_ID.

echo "RESOURCE_ID=resource-42" >> "$MESHFOX_VARS_OUT"
echo "using $RESOURCE_ID"
exit code: 0

using resource-42
Session

DEPLOY_CONFIG is type="select" with required session — unlike a plain required variable (whose confirmation is cached and reused forever after), session means the answer is never written to the on-disk cache at all, so every separate meshfox run invocation asks again. Referenced by more than one block in the same invocation, it's still only ever prompted for once — session only skips the cache, not the same once-per-invocation reuse every other variable already gets. Deliberately without cache here, same reason secret-token above has none: this needs a fresh interactive answer (or --set) every run, so there's no single "settled" output to freeze into the file.

echo "deploying to $DEPLOY_CONFIG"
Dynamic choices

REGION_DYNAMIC has choices_var="REGIONS_LIST" instead of a literal choices= — and REGIONS_LIST is itself from=-computed by list-regions below, so REGION_DYNAMIC's own options ultimately come from actually running a script, not a hardcoded list. Running use-region automatically runs list-regions first (the same implicit-dependency mechanism from= always gets, followed transitively through choices_var) — REGION_DYNAMIC itself still needs an interactive answer (or --set) once its choices are known, so this is also without cache.

Two things to know when the list comes from a script (a font list from fc-list, a branch list from git branch):

  • The source block runs before the form is shown, with an empty environment: it sees no env= variable of this canvas (only what its own deps= chain published, such as an interpreter="$PYTHON" built by a setup block). So the list cannot depend on another variable's answer (a language chosen in the same form, say) — print every option and let the user filter: typing in the picker narrows it, in the web UI, the TUI and the terminal prompt alike.
  • If the source fails (non-zero exit, a missing tool), the field has no choices and says why — which variable they wait for and the end of the block's output (choicesPending) — instead of showing an empty list. A run cannot go on past it, and configure leaves it unsaved.
echo "REGIONS_LIST=us-east-1,eu-west-1,ap-southeast-1" >> "$MESHFOX_VARS_OUT"
echo "using $REGION_DYNAMIC"
Combined

env= takes a comma-separated list — a single block can reference several declared variables at once, mixing plain, required, select, bool, and int ones freely. Each is still resolved independently (its own override/environment/cache/default, required skipping that last step, int validated on the way in, same as anywhere else) — env= just collects whichever of them this one block actually needs into its process environment together.

echo "$GREETING! installing to $INSTALL_PATH (log level $LOG_LEVEL, verbose=$VERBOSE, retries=$RETRY_COUNT)"
exit code: 0

Hello! installing to /usr/local/bin (log level info, verbose=false, retries=3)