From 35b420ae208f42d3f07b0401ae38f67e19d11156 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Thu, 5 Sep 2024 11:37:28 +1000 Subject: [PATCH] Canonicalise empty plugin configs to nil --- plugin.go | 20 +++++++++++++++++--- plugin_test.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/plugin.go b/plugin.go index 218e7b5..01eb964 100644 --- a/plugin.go +++ b/plugin.go @@ -35,13 +35,27 @@ func (p *Plugin) MarshalJSON() ([]byte, error) { return json.Marshal(o) } -// MarshalYAML returns the plugin in either "one-item map" form. Plugin sources +// MarshalYAML returns the plugin in "one-item map" form. Plugin sources // are marshalled into "full" form. Plugins originally specified as a single // string (no config, only source) are canonicalised into "one-item map" with -// config nil. +// config nil. Configs that are zero-length maps are canonicalised to nil. func (p *Plugin) MarshalYAML() (any, error) { + cfg := p.Config + switch x := cfg.(type) { + case map[string]any: + if len(x) == 0 { + cfg = nil + } + + case []any: + // Should be invalid, but a different part of the process should be + // responsible for checking and complaining. + if len(x) == 0 { + cfg = nil + } + } return map[string]any{ - p.FullSource(): p.Config, + p.FullSource(): cfg, }, nil } diff --git a/plugin_test.go b/plugin_test.go index c365725..cb848ed 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -1,6 +1,7 @@ package pipeline import ( + "encoding/json" "testing" "github.com/google/go-cmp/cmp" @@ -87,6 +88,53 @@ func TestPluginFullSource(t *testing.T) { } } +func TestPluginMarshalJSON_Canonicalisation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + p *Plugin + }{ + { + name: "nil interface", + p: &Plugin{Source: "docker#v1.2.3", Config: nil}, + }, + { + name: "nil map", + p: &Plugin{Source: "docker#v1.2.3", Config: map[string]any(nil)}, + }, + { + name: "empty map", + p: &Plugin{Source: "docker#v1.2.3", Config: map[string]any{}}, + }, + { + name: "nil slice??", + p: &Plugin{Source: "docker#v1.2.3", Config: []any(nil)}, + }, + { + name: "empty slice??", + p: &Plugin{Source: "docker#v1.2.3", Config: []any{}}, + }, + } + + const want = `{"github.com/buildkite-plugins/docker-buildkite-plugin#v1.2.3":null}` + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + got, err := json.Marshal(test.p) + if err != nil { + t.Errorf("json.Marshal(%+v) error = %v", test.p, err) + } + + if diff := cmp.Diff(string(got), want); diff != "" { + t.Errorf("JSON marshalled plugin diff (-got +want):\n%s", diff) + } + }) + } +} + func TestPluginMatrixInterpolate(t *testing.T) { t.Parallel() @@ -151,5 +199,4 @@ func TestPluginMatrixInterpolate(t *testing.T) { } }) } - }