diff --git a/cmd/render/render.go b/cmd/render/render.go index b150fba..5f0862f 100644 --- a/cmd/render/render.go +++ b/cmd/render/render.go @@ -49,6 +49,11 @@ func render(baseDir, templateGlob, outputDir string, dataSourceGlobs []string) e } err = renderTemplate(outputDir, templateBase, tmpl, data) if err != nil { + if strings.Contains(err.Error(), "map has no entry for key") { + res := []string{} + walkMap(data, &res, []string{}, assembleRef) + return fmt.Errorf("render template %q: %s.\nValid references are:\n%s", templateBase, err, strings.Join(res, "\n")) + } return fmt.Errorf("render template %q: %s", templateBase, err) } } @@ -128,3 +133,21 @@ func collectDataFromMatchingFiles(baseDir, glob string, data map[string]interfac } return err } + +type visitFunc func(path []string, key any, value any) string + +func assembleRef(path []string, key, value any) string { + return fmt.Sprintf(".%s.%s", strings.Join(path, "."), key) +} + +func walkMap(data map[string]any, paths *[]string, path []string, visit visitFunc) { + for key, value := range data { + if child, isMap := value.(map[string]any); isMap { + path = append(path, key) + walkMap(child, paths, path, visit) + path = path[:len(path)-1] + } else { + *paths = append(*paths, visit(path, key, child)) + } + } +} diff --git a/cmd/render/render_test.go b/cmd/render/render_test.go index 17a0279..ff9533a 100644 --- a/cmd/render/render_test.go +++ b/cmd/render/render_test.go @@ -79,12 +79,20 @@ func TestRender(t *testing.T) { func TestRenderFailsOnMissingKeys(t *testing.T) { tempDir := testhelper.MkdirTempDir(t) defer testhelper.RmTempDir(tempDir) - if err := render( + err := render( "../../test/testdata/fixtures", - "sample.adoc.tmpl", + "error.adoc.tmpl", tempDir, - []string{}, - ); err == nil { - t.Fatal("Fixture template sample.adoc.tmpl requires data to be present") + []string{ + ".ods/artifacts/*/*.json", + ".ods/artifacts/*/*.yaml", + ".ods/artifacts/*/*.txt", + "*.yaml", + }, + ) + if err == nil { + t.Error("Fixture template error.adoc.tmpl includes non-existent reference") + } else if !strings.Contains(err.Error(), ".ods.artifacts.org_opendevstack_pipeline_go_foo.result.foo") { + t.Errorf("Error must list valid references, got:\n%s", err) } } diff --git a/test/testdata/fixtures/error.adoc.tmpl b/test/testdata/fixtures/error.adoc.tmpl new file mode 100644 index 0000000..bd2d40b --- /dev/null +++ b/test/testdata/fixtures/error.adoc.tmpl @@ -0,0 +1 @@ +{{.no.such.key}}