Jinja expressions are allowed in renderable string fields, including variables,
target fields, and rule recipes. Structural Jinja blocks cannot reshape the
YAML document. Use the dedicated foreach and when keys for manifest-time
expansion.
Generate targets with `foreach` and `when`
The next complete manifest creates two targets and excludes the disabled item:
netsuke_version: "1.0.0"
vars:
reports:
- daily
- weekly
- disabled
targets:
- foreach: reports
when: item != 'disabled'
name: "{{ item }}.txt"
command: "echo {{ index }} > {{ outs }}"
defaults:
- daily.txt
- weekly.txt
Each expansion receives item and a zero-based index. Target-local variables
take precedence over global variables, and iteration values take precedence
over both.
when is evaluated while Netsuke loads the manifest. It does not create a
runtime branch. Runtime decisions belong in a command or script.
Top-level actions support the same foreach and when keys.
Discover files with `glob`
glob(pattern) expands a shell-style pattern to the sorted list of matching
files while Netsuke loads the manifest, so the results become part of the
static build graph. It pairs naturally with foreach to generate one target
per matched file; a target list such as foreach: glob('src/*.c') produces one
expansion per matching source.
Matching is case-sensitive. * and ? do not cross directory separators; use
** to descend into subdirectories. Directories are excluded, so only files
are returned. The quick-start guide shows a complete runnable
example.
Define reusable macros
Macros return rendered text and can accept default arguments:
netsuke_version: "1.0.0"
vars:
greeting: Hello
macros:
- signature: "say(name, punctuation='!')"
body: |
{{ greeting }}, {{ name }}{{ punctuation }}
targets:
- name: greeting.txt
command: "echo '{{ say('Netsuke') }}' > {{ outs }}"
defaults:
- greeting.txt
Select optional tools
which(name, **kwargs) returns an executable path and fails when the command
is absent. The same helper is also available as a filter.
command_available(name, **kwargs) returns a boolean and is better for
complementary branches:
netsuke_version: "1.0.0"
actions:
- name: test-fast
command: "cargo nextest run"
when: command_available("cargo-nextest")
- name: test-fast
command: "cargo test"
when: not command_available("cargo-nextest")
targets: []
defaults:
- test-fast
Both helpers accept:
all=true: return allwhichmatches. It does not change the boolean result fromcommand_available.canonical=true: canonicalize matching paths.fresh=true: bypass the resolver cache for this lookup.cwd_mode="auto"|"always"|"never": control bounded project-directory fallback searching.
The env(name) function reads one required environment variable. v0.1.0-beta1
does not accept a default argument; an absent or non-Unicode value is an error.
Inject the environment reader for tests and embedding
env() does not read std::env::var directly. Manifest parsing goes through
an injectable EnvReader seam, so callers that need deterministic env()
results — test suites and programs embedding Netsuke as a library — can supply
their own reader instead of mutating the process environment.
netsuke::manifest::from_strparses a manifest using the live process environment.netsuke::manifest::from_str_with_envtakes an explicitEnvReader, letting the caller control every valueenv()returns.netsuke::manifest::process_env_readerbuilds the process-backed reader thatfrom_struses by default.
A missing variable still fails the parse with a Jinja "undefined" error, and a non-Unicode value still fails with an "invalid operation" error; only the source of the values changes.
use netsuke::manifest::{EnvReader, from_str_with_env};
use std::sync::Arc;
let reader: EnvReader = Arc::new(|_| Ok(String::from("release")));
let yaml = concat!(
"netsuke_version: \"1.0.0\"\n",
"targets:\n",
" - name: \"{{ env('PROFILE') }}\"\n",
" command: echo hi\n",
);
let manifest = from_str_with_env(yaml, &reader).expect("parse");
assert!(format!("{:?}", manifest.targets[0].name).contains("release"));
This snippet mirrors the executable doctest on from_str_with_env in the API
documentation, rather than the YAML-only examples elsewhere in this guide.