From e9da3c135cd91c56a9df2f889893b662f02c4203 Mon Sep 17 00:00:00 2001 From: Kamsi Ibeziako Date: Sat, 6 May 2023 07:58:25 -0400 Subject: [PATCH] Add option to load style config from file (#92) --- printer/opts.go | 43 +++++++++++++ printer/pretty.go | 11 ++-- printer/printer_test.go | 63 +++++++++++++++++++ .../Print_custom_layout.golden.txt | 7 +++ .../Print_default_layout.golden.txt | 10 +++ .../customStyle.json | 28 +++++++++ .../customStyle.yaml | 31 +++++++++ .../invalidStyle.json | 10 +++ .../invalidStyle.yaml | 6 ++ ...rStyleFromEnvOptionsUseDefaults.golden.txt | 10 +++ 10 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 printer/testdata/TestPrinterStyleFileOptions/Print_custom_layout.golden.txt create mode 100644 printer/testdata/TestPrinterStyleFileOptions/Print_default_layout.golden.txt create mode 100644 printer/testdata/TestPrinterStyleFileOptions/customStyle.json create mode 100644 printer/testdata/TestPrinterStyleFileOptions/customStyle.yaml create mode 100644 printer/testdata/TestPrinterStyleFileOptions/invalidStyle.json create mode 100644 printer/testdata/TestPrinterStyleFileOptions/invalidStyle.yaml create mode 100644 printer/testdata/TestPrinterStyleFromEnvOptionsUseDefaults.golden.txt diff --git a/printer/opts.go b/printer/opts.go index 7c578c1..6f981c1 100644 --- a/printer/opts.go +++ b/printer/opts.go @@ -1,8 +1,13 @@ package printer import ( + "encoding/json" + "os" + "path/filepath" + "go.szostok.io/version/style" "go.szostok.io/version/upgrade" + "gopkg.in/yaml.v3" ) // Inspired by https://github.com/kubernetes-sigs/controller-runtime/blob/v0.12.3/pkg/client/options.go @@ -195,3 +200,41 @@ func WithUpgradeNotice(owner, repo string, opts ...upgrade.Options) *EnableUpgra func (c *EnableUpgradeNotice) ApplyToContainerOption(cfg *ContainerOptions) { cfg.UpgradeNotice = upgrade.NewGitHubDetector(c.owner, c.repo, c.upgradeOpts...) } + +// WithPrettyStyleFromEnv Load a custom style from environment variable +func WithPrettyStyleFromEnv(envVariable string) (*CustomPrettyStyle, error) { + path := os.Getenv(envVariable) + options, err := parseConfigFile(path) + + return options, err +} + +// WithPrettyStyleFile Load a custom style from file +func WithPrettyStyleFile(path string) (*CustomPrettyStyle, error) { + options, err := parseConfigFile(path) + + return options, err +} + +func parseConfigFile(fileName string) (*CustomPrettyStyle, error) { + options := &CustomPrettyStyle{cfg: PrettyDefaultRenderConfig()} + if fileName == "" { + return options, nil + } + + fileName = filepath.Clean(fileName) + body, err := os.ReadFile(fileName) + if err != nil { + return options, err + } + + extension := filepath.Ext(fileName) + switch extension { + case ".yml", ".yaml": + err = yaml.Unmarshal(body, &options.cfg) + case ".json": + err = json.Unmarshal(body, &options.cfg) + } + + return options, err +} diff --git a/printer/pretty.go b/printer/pretty.go index 7e84cc3..35d2b9f 100644 --- a/printer/pretty.go +++ b/printer/pretty.go @@ -18,9 +18,8 @@ type ( PrettyPostRenderFunc func(body string, isSmartTerminal bool) (string, error) ) -var ( - // PrettyLayoutGoTpl prints all version data in a 'key value' manner. - PrettyLayoutGoTpl = `{{ AdjustKeyWidth .ExtraFields }} +// PrettyLayoutGoTpl prints all version data in a 'key value' manner. +var PrettyLayoutGoTpl = `{{ AdjustKeyWidth .ExtraFields }} {{ Header .Meta.CLIName }} {{ Key "Version" }} {{ .Version | Val }} @@ -35,7 +34,6 @@ var ( {{ $item.Key | Key }} {{ $item.Value | Val }} {{- end}} ` -) // Pretty prints human-readable version printing. type Pretty struct { @@ -91,3 +89,8 @@ func (p *Pretty) execute(in *version.Info, isSmartTerminal bool) (string, error) return p.customRenderFn(in, isSmartTerminal) } + +// PrettyDefaultRenderConfig returns the default render configuration when no customizations are provided. +func PrettyDefaultRenderConfig() *style.Config { + return style.DefaultConfig(PrettyLayoutGoTpl) +} diff --git a/printer/printer_test.go b/printer/printer_test.go index 6073422..c149ec6 100644 --- a/printer/printer_test.go +++ b/printer/printer_test.go @@ -187,6 +187,69 @@ func TestPrinterPrint(t *testing.T) { assertGoldenFile(t, normalized) } +// It uses the golden files, to update them run: +// +// go test -v -run=TestPrinterStyleFileOptions ./printer/... -update +func TestPrinterStyleFileOptions(t *testing.T) { + tests := []struct { + testName string + fileName string + }{ + { + testName: "Print custom layout", + fileName: "testdata/TestPrinterStyleFileOptions/customStyle", + }, + { + testName: "Print default layout", + fileName: "testdata/TestPrinterStyleFileOptions/invalidStyle", + }, + } + + for _, tc := range tests { + t.Run(tc.testName, func(t *testing.T) { + yamlStyle, err := printer.WithPrettyStyleFile(tc.fileName + ".yaml") + require.NoError(t, err) + + jsonStyle, err := printer.WithPrettyStyleFile(tc.fileName + ".json") + require.NoError(t, err) + + t.Setenv("config-file", tc.fileName+".yaml") + + envStyle, err := printer.WithPrettyStyleFromEnv("config-file") + require.NoError(t, err) + + validateStyle(yamlStyle, t) + validateStyle(jsonStyle, t) + validateStyle(envStyle, t) + }) + } +} + +// It uses the golden files, to update them run: +// +// go test -v -run=TestPrinterStyleFromEnvOptionsUseDefaults ./printer/... -update +func TestPrinterStyleFromEnvOptionsUseDefaults(t *testing.T) { + emptyStyle, err := printer.WithPrettyStyleFromEnv("empty-variable") + require.NoError(t, err) + + validateStyle(emptyStyle, t) +} + +func validateStyle(customStyle *printer.CustomPrettyStyle, t *testing.T) { + t.Helper() + + p := printer.New(customStyle) + var buff strings.Builder + + err := p.Print(&buff) + + require.NoError(t, err) + + stripped := strings.TrimSpace(buff.String()) + normalized := normalizeOutput(stripped) + assertGoldenFile(t, normalized) +} + // normalizeOutput normalize dynamic fields such as platform and binary name. func normalizeOutput(data string) string { data = strings.ReplaceAll(data, os.Args[0], "fixed-name") diff --git a/printer/testdata/TestPrinterStyleFileOptions/Print_custom_layout.golden.txt b/printer/testdata/TestPrinterStyleFileOptions/Print_custom_layout.golden.txt new file mode 100644 index 0000000..2bf99b1 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/Print_custom_layout.golden.txt @@ -0,0 +1,7 @@ +-> fixed-name + + Version (devel) + Dirty Build no + Go version 1.19.4 + Compiler gc + Platform fixed-platform \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFileOptions/Print_default_layout.golden.txt b/printer/testdata/TestPrinterStyleFileOptions/Print_default_layout.golden.txt new file mode 100644 index 0000000..4441966 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/Print_default_layout.golden.txt @@ -0,0 +1,10 @@ +▓▓▓ fixed-name + + Version (devel) + Git Commit N/A + Build Date N/A + Commit Date N/A + Dirty Build no + Go version 1.19.4 + Compiler gc + Platform fixed-platform \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFileOptions/customStyle.json b/printer/testdata/TestPrinterStyleFileOptions/customStyle.json new file mode 100644 index 0000000..85d7530 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/customStyle.json @@ -0,0 +1,28 @@ +{ + "formatting": { + "header": { + "prefix": "-> ", + "color": "Magenta", + "background": "", + "options": null + }, + "key": { + "color": "Yellow", + "background": "", + "options": [ + "Bold" + ] + }, + "val": { + "color": "Green", + "background": "", + "options": null + }, + "date": { + "enableHumanizedSuffix": false + } + }, + "layout": { + "goTemplate": "{{ AdjustKeyWidth .ExtraFields }}\n{{ Header .Meta.CLIName }}\n\n {{ Key \"Version\" }} {{ .Version | Val }}\n {{ Key \"Dirty Build\" }} {{ .DirtyBuild | FmtBool | Val }}\n {{ Key \"Go version\" }} {{ .GoVersion | trimPrefix \"go\"| Val }}\n {{ Key \"Compiler\" }} {{ .Compiler | Val }}\n {{ Key \"Platform\" }} {{ .Platform | Val }}\n {{- range $item := (.ExtraFields | Extra) }}\n {{ $item.Key | Key }} {{ $item.Value | Val }}\n {{- end}}\n" + } +} \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFileOptions/customStyle.yaml b/printer/testdata/TestPrinterStyleFileOptions/customStyle.yaml new file mode 100644 index 0000000..448063c --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/customStyle.yaml @@ -0,0 +1,31 @@ +formatting: + header: + prefix: '-> ' + color: Magenta + background: "" + options: [] + key: + color: Yellow + background: "" + options: + - Bold + val: + color: Green + background: "" + options: [] + date: + enableHumanizedSuffix: true + +layout: + goTemplate: | + {{ AdjustKeyWidth .ExtraFields }} + {{ Header .Meta.CLIName }} + + {{ Key "Version" }} {{ .Version | Val }} + {{ Key "Dirty Build" }} {{ .DirtyBuild | FmtBool | Val }} + {{ Key "Go version" }} {{ .GoVersion | trimPrefix "go"| Val }} + {{ Key "Compiler" }} {{ .Compiler | Val }} + {{ Key "Platform" }} {{ .Platform | Val }} + {{- range $item := (.ExtraFields | Extra) }} + {{ $item.Key | Key }} {{ $item.Value | Val }} + {{- end}} \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.json b/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.json new file mode 100644 index 0000000..7dfaad8 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.json @@ -0,0 +1,10 @@ +{ + "format": { + "header": { + "prefix": "-> ", + "color": "Magenta", + "background": "", + "options": null + } + } +} \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.yaml b/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.yaml new file mode 100644 index 0000000..6c19cd1 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFileOptions/invalidStyle.yaml @@ -0,0 +1,6 @@ +format: + header: + prefix: '-> ' + color: Magenta + background: "" + options: [] \ No newline at end of file diff --git a/printer/testdata/TestPrinterStyleFromEnvOptionsUseDefaults.golden.txt b/printer/testdata/TestPrinterStyleFromEnvOptionsUseDefaults.golden.txt new file mode 100644 index 0000000..4441966 --- /dev/null +++ b/printer/testdata/TestPrinterStyleFromEnvOptionsUseDefaults.golden.txt @@ -0,0 +1,10 @@ +▓▓▓ fixed-name + + Version (devel) + Git Commit N/A + Build Date N/A + Commit Date N/A + Dirty Build no + Go version 1.19.4 + Compiler gc + Platform fixed-platform \ No newline at end of file