From e498626b5a502d8ad3da5a69e97c62ca222b3083 Mon Sep 17 00:00:00 2001 From: Michael Sauter Date: Mon, 6 Nov 2023 09:52:47 +0100 Subject: [PATCH] Add parameter to set template values directly Note this also changes the separator character from semicolon to comma for the `data-source` flag, as the comma is likely more common. Closes #4. --- build/docs/render.adoc | 2 +- build/tasks/render.yaml | 14 +++++++++++--- cmd/render/main.go | 4 +++- cmd/render/multiflag.go | 2 +- cmd/render/render.go | 10 +++++++++- cmd/render/render_test.go | 5 +++++ cmd/render/template_funcs.go | 2 +- docs/render.adoc | 11 ++++++++--- tasks/render.yaml | 14 +++++++++++--- test/e2e/render_test.go | 1 + test/testdata/fixtures/sample.adoc.tmpl | 5 ++++- test/testdata/golden/sample.adoc | 4 ++++ .../workspaces/sample-app/templates/one.adoc.tmpl | 2 +- .../workspaces/sample-app/templates/two.adoc.tmpl | 2 +- 14 files changed, 61 insertions(+), 17 deletions(-) diff --git a/build/docs/render.adoc b/build/docs/render.adoc index f5921ff..6c28725 100644 --- a/build/docs/render.adoc +++ b/build/docs/render.adoc @@ -1,6 +1,6 @@ The purpose of this task is to render a asciidoc template located in the repository into a PDF. In addition to just transforming the asciidoc file to PDF, the task is also able to render information gathered from YAML/JSON files (such as ODS Pipeline artifacts) into the asciidoc file before transforming it to PDF. -The task expects a glob pattern pointing to one or more Go template files (given by parameter `template`). It renders each found Go template with data gathered from files matching the `data-sources` parameter, which defaults to `.ods/\*;.ods/repos/*/.ods/\*;.ods/artifacts/*/\*.json;.ods/artifacts/*/*.yaml`. The asciidoc template can then access data parsed from these files. For example, if file `.ods/artifacts/org.foo/some.json` contains: +The task expects a glob pattern pointing to one or more Go template files (given by parameter `template`). It renders each found Go template with data gathered from files matching the `data-sources` parameter, which defaults to `.ods/\*,.ods/repos/*/.ods/\*,.ods/artifacts/*/\*.json,.ods/artifacts/*/*.yaml`. The asciidoc template can then access data parsed from these files. For example, if file `.ods/artifacts/org.foo/some.json` contains: ``` {"a":"b"} diff --git a/build/tasks/render.yaml b/build/tasks/render.yaml index b9e01ef..e2b9b48 100644 --- a/build/tasks/render.yaml +++ b/build/tasks/render.yaml @@ -26,9 +26,16 @@ spec: - name: data-sources description: >- Glob patterns from where to source data. - Multiple glob patterns are separated by semicolons. + Multiple glob patterns are separated by commas. type: string - default: ".ods/*;.ods/repos/*/.ods/*;.ods/artifacts/*/*.json;.ods/artifacts/*/*.yaml" + default: ".ods/*,.ods/repos/*/.ods/*,.ods/artifacts/*/*.json,.ods/artifacts/*/*.yaml" + - name: set + description: >- + Set template data values directly. + Multiple key=value pairs are separated by commas. Keys specified have + precedence over those discovered through `data-sources`. + type: string + default: "" - name: pdf-theme description: >- The name or file path of the Asciidoctor PDF theme to load. @@ -56,7 +63,8 @@ spec: render-template \ --template='$(params.template)' \ --output-dir=$(params.output-dir) \ - --data-source='$(params.data-sources)' + --data-source='$(params.data-sources)' \ + --set='$(params.set)' asciidoctor_pdf_flags='--failure-level ERROR' if [ "$(params.pdf-theme)" != "" ]; then diff --git a/cmd/render/main.go b/cmd/render/main.go index 71ab467..703a47a 100644 --- a/cmd/render/main.go +++ b/cmd/render/main.go @@ -20,12 +20,14 @@ func main() { outputDir := flag.String("output-dir", "", "Output directory where to place the rendered files") var dataSourceFlags multiFlag flag.Var(&dataSourceFlags, "data-source", "Glob pattern from where to source data (may be specified multiple times)") + var setFlags multiFlag + flag.Var(&setFlags, "set", "Set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") flag.Parse() wd, err := os.Getwd() if err != nil { log.Fatal(err) } - if err := render(wd, *templateGlob, *outputDir, dataSourceFlags); err != nil { + if err := render(wd, *templateGlob, *outputDir, dataSourceFlags, setFlags); err != nil { log.Fatal(err) } } diff --git a/cmd/render/multiflag.go b/cmd/render/multiflag.go index 05411d8..52fd468 100644 --- a/cmd/render/multiflag.go +++ b/cmd/render/multiflag.go @@ -12,6 +12,6 @@ func (i *multiFlag) String() string { } func (i *multiFlag) Set(value string) error { - *i = append(*i, strings.Split(value, ";")...) + *i = append(*i, strings.Split(value, ",")...) return nil } diff --git a/cmd/render/render.go b/cmd/render/render.go index e3868b0..742ea48 100644 --- a/cmd/render/render.go +++ b/cmd/render/render.go @@ -14,7 +14,7 @@ import ( var nonAlphanumericRegex = regexp.MustCompile(`[^a-zA-Z0-9]+`) -func render(baseDir, templateGlob, outputDir string, dataSourceGlobs []string) error { +func render(baseDir, templateGlob, outputDir string, dataSourceGlobs, setFlags []string) error { if !strings.HasSuffix(baseDir, "/") { baseDir = baseDir + "/" } @@ -30,6 +30,14 @@ func render(baseDir, templateGlob, outputDir string, dataSourceGlobs []string) e if err != nil { return err } + // Add key=value paris specified via --set. + for _, v := range setFlags { + key, value, found := strings.Cut(v, "=") + if !found { + return fmt.Errorf("%q is not a valid --set flag, must be of form key=value", v) + } + data[key] = value + } matches, err := filepath.Glob(filepath.Join(baseDir, templateGlob)) if err != nil { diff --git a/cmd/render/render_test.go b/cmd/render/render_test.go index ff9533a..3866536 100644 --- a/cmd/render/render_test.go +++ b/cmd/render/render_test.go @@ -67,6 +67,10 @@ func TestRender(t *testing.T) { ".ods/artifacts/*/*.txt", "*.yaml", }, + []string{ + "keyfoo=valbar", + "keybar=valbaz", + }, ); err != nil { t.Fatal(err) } @@ -89,6 +93,7 @@ func TestRenderFailsOnMissingKeys(t *testing.T) { ".ods/artifacts/*/*.txt", "*.yaml", }, + []string{}, ) if err == nil { t.Error("Fixture template error.adoc.tmpl includes non-existent reference") diff --git a/cmd/render/template_funcs.go b/cmd/render/template_funcs.go index bc15a8f..8733bf5 100644 --- a/cmd/render/template_funcs.go +++ b/cmd/render/template_funcs.go @@ -52,7 +52,7 @@ func toSentence(items []string) string { // keys returns a slice of all keys in map m. func keys(m map[string]any) (keys []string) { - for k, _ := range m { + for k := range m { keys = append(keys, k) } return diff --git a/docs/render.adoc b/docs/render.adoc index 01a5476..90e3006 100644 --- a/docs/render.adoc +++ b/docs/render.adoc @@ -4,7 +4,7 @@ The purpose of this task is to render a asciidoc template located in the repository into a PDF. In addition to just transforming the asciidoc file to PDF, the task is also able to render information gathered from YAML/JSON files (such as ODS Pipeline artifacts) into the asciidoc file before transforming it to PDF. -The task expects a glob pattern pointing to one or more Go template files (given by parameter `template`). It renders each found Go template with data gathered from files matching the `data-sources` parameter, which defaults to `.ods/\*;.ods/repos/*/.ods/\*;.ods/artifacts/*/\*.json;.ods/artifacts/*/*.yaml`. The asciidoc template can then access data parsed from these files. For example, if file `.ods/artifacts/org.foo/some.json` contains: +The task expects a glob pattern pointing to one or more Go template files (given by parameter `template`). It renders each found Go template with data gathered from files matching the `data-sources` parameter, which defaults to `.ods/\*,.ods/repos/*/.ods/\*,.ods/artifacts/*/\*.json,.ods/artifacts/*/*.yaml`. The asciidoc template can then access data parsed from these files. For example, if file `.ods/artifacts/org.foo/some.json` contains: ``` {"a":"b"} @@ -48,8 +48,13 @@ without leading `./` and trailing `/`. | data-sources -| .ods/*;.ods/repos/*/.ods/*;.ods/artifacts/*/*.json;.ods/artifacts/*/*.yaml -| Glob patterns from where to source data. Multiple glob patterns are separated by semicolons. +| .ods/*,.ods/repos/*/.ods/*,.ods/artifacts/*/*.json,.ods/artifacts/*/*.yaml +| Glob patterns from where to source data. Multiple glob patterns are separated by commas. + + +| set +| +| Set template data values directly. Multiple key=value pairs are separated by commas. Keys specified have precedence over those discovered through `data-sources`. | pdf-theme diff --git a/tasks/render.yaml b/tasks/render.yaml index e6b7f1a..c61555f 100644 --- a/tasks/render.yaml +++ b/tasks/render.yaml @@ -28,9 +28,16 @@ spec: - name: data-sources description: >- Glob patterns from where to source data. - Multiple glob patterns are separated by semicolons. + Multiple glob patterns are separated by commas. type: string - default: ".ods/*;.ods/repos/*/.ods/*;.ods/artifacts/*/*.json;.ods/artifacts/*/*.yaml" + default: ".ods/*,.ods/repos/*/.ods/*,.ods/artifacts/*/*.json,.ods/artifacts/*/*.yaml" + - name: set + description: >- + Set template data values directly. + Multiple key=value pairs are separated by commas. Keys specified have + precedence over those discovered through `data-sources`. + type: string + default: "" - name: pdf-theme description: >- The name or file path of the Asciidoctor PDF theme to load. @@ -58,7 +65,8 @@ spec: render-template \ --template='$(params.template)' \ --output-dir=$(params.output-dir) \ - --data-source='$(params.data-sources)' + --data-source='$(params.data-sources)' \ + --set='$(params.set)' asciidoctor_pdf_flags='--failure-level ERROR' if [ "$(params.pdf-theme)" != "" ]; then diff --git a/test/e2e/render_test.go b/test/e2e/render_test.go index e4bd335..d9de4fb 100644 --- a/test/e2e/render_test.go +++ b/test/e2e/render_test.go @@ -17,6 +17,7 @@ func TestRenderAdocTask(t *testing.T) { ttr.UsingTask("ods-pipeline-adoc-render"), ttr.WithStringParams(map[string]string{ "template": "templates/*.adoc.tmpl", + "set": "greeting=Hello,who=World", "output-dir": "rendered", "retain-rendered-adoc-files": "true", }), diff --git a/test/testdata/fixtures/sample.adoc.tmpl b/test/testdata/fixtures/sample.adoc.tmpl index 007e1a0..5a69fc1 100644 --- a/test/testdata/fixtures/sample.adoc.tmpl +++ b/test/testdata/fixtures/sample.adoc.tmpl @@ -23,4 +23,7 @@ Sprig template functions can be used: {{toDate "2006-01-02" "2017-12-31" | date "02/01/2006"}} And custom helper functions can be used: -{{toYAML .ods.artifacts.org_opendevstack_pipeline_go_foo.result -}} +{{toYAML .ods.artifacts.org_opendevstack_pipeline_go_foo.result}} + +It is also possible to use values set from the CLI: +{{.keyfoo}} and {{.keybar}} diff --git a/test/testdata/golden/sample.adoc b/test/testdata/golden/sample.adoc index 37b5c7f..23f30f8 100644 --- a/test/testdata/golden/sample.adoc +++ b/test/testdata/golden/sample.adoc @@ -25,3 +25,7 @@ Sprig template functions can be used: And custom helper functions can be used: bar: b foo: a + + +It is also possible to use values set from the CLI: +valbar and valbaz diff --git a/test/testdata/workspaces/sample-app/templates/one.adoc.tmpl b/test/testdata/workspaces/sample-app/templates/one.adoc.tmpl index 66359e4..d97afb3 100644 --- a/test/testdata/workspaces/sample-app/templates/one.adoc.tmpl +++ b/test/testdata/workspaces/sample-app/templates/one.adoc.tmpl @@ -1,4 +1,4 @@ -# Hello World +# {{.greeting}} {{.who}} This is a sample adoc file. diff --git a/test/testdata/workspaces/sample-app/templates/two.adoc.tmpl b/test/testdata/workspaces/sample-app/templates/two.adoc.tmpl index 76e930e..c2757a5 100644 --- a/test/testdata/workspaces/sample-app/templates/two.adoc.tmpl +++ b/test/testdata/workspaces/sample-app/templates/two.adoc.tmpl @@ -1,4 +1,4 @@ -# Hello World - 2nd file +# {{.greeting}} {{.who}} - 2nd file This is a second adoc file.