From acec0deae6d8bd42c1da0a177ddf6f73557d067e Mon Sep 17 00:00:00 2001 From: Max Dymond Date: Fri, 7 Aug 2026 10:39:07 +0100 Subject: [PATCH] fix: restore get_env() template function tera 2 dropped the built-in get_env(), so floki.yaml files using it stopped rendering as of 2.4.4. Reimplement and register it, with tests so a future tera bump can't silently drop it again. Fixes #576 Signed-off-by: Max Dymond --- docs/content/intro/feature-overview.md | 2 ++ src/config.rs | 43 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/docs/content/intro/feature-overview.md b/docs/content/intro/feature-overview.md index 28a5fc2b..1a3686ca 100644 --- a/docs/content/intro/feature-overview.md +++ b/docs/content/intro/feature-overview.md @@ -232,4 +232,6 @@ Example uses include referencing environmental variables in the `floki` config, docker_switches: - -v {{ env.HOME }}/.vim:/home/build/.vim ``` +`get_env(name="HOME")` is also available, and takes an optional `default` for when the variable isn't set. + Note that extensive use may reduce the reproducibility and shareability of your `floki.yaml`. diff --git a/src/config.rs b/src/config.rs index 5d0921ed..cd848e07 100644 --- a/src/config.rs +++ b/src/config.rs @@ -195,6 +195,20 @@ fn makeloader( } } +// Reimplementation of tera 1's `get_env`, which was dropped in tera 2. +fn get_env(kwargs: tera::Kwargs, _: &tera::State) -> tera::TeraResult { + let name: String = kwargs.must_get("name")?; + match std::env::var(&name) { + Ok(value) => Ok(value.into()), + Err(_) => match kwargs.get::("default")? { + Some(default) => Ok(default), + None => Err(tera::Error::message(format!( + "Environment variable `{name}` not found" + ))), + }, + } +} + // Renders a template from a given string. pub fn render_template(template: &str, source_filename: &Path) -> Result { let template_path = source_filename.display().to_string(); @@ -216,6 +230,7 @@ pub fn render_template(template: &str, source_filename: &Path) -> Result Result<(), Box> { + // Uses PATH rather than setting a var, as set_var is unsound in a threaded + // test binary. + let template = r#"shell: {{ get_env(name="PATH") }}"#; + assert_eq!( + render_template(template, Path::new("floki.yaml"))?, + format!("shell: {}", std::env::var("PATH")?) + ); + Ok(()) + } + + #[test] + fn test_tera_get_env_default() -> Result<(), Box> { + let template = r#"shell: {{ get_env(name="FLOKI_TEST_UNSET", default="bar") }}"#; + assert_eq!( + render_template(template, Path::new("floki.yaml"))?, + "shell: bar" + ); + Ok(()) + } + + #[test] + fn test_tera_get_env_missing_errors() { + let template = r#"shell: {{ get_env(name="FLOKI_TEST_UNSET") }}"#; + assert!(render_template(template, Path::new("floki.yaml")).is_err()); + } + #[test] fn test_strip_yaml_tags_drops_reference_tag() { let yaml = "value: !reference [template, script]";