Repository: yokecd/yoke
Pull request #136 (2025-05-12 14:24:15)

develop
- **deps: update davidmdm/xerr**
- **internal/unmarshalling: parsing of stages creates pre-stages for namespaces and crds**



Patch:
diff --git a/go.mod b/go.mod
index a5f654a..5c61dfd 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/davidmdm/ansi v0.0.6
 	github.com/davidmdm/conf v0.0.8
 	github.com/davidmdm/x/xcontext v0.0.3
-	github.com/davidmdm/x/xerr v0.0.3
+	github.com/davidmdm/x/xerr v0.0.4
 	github.com/davidmdm/x/xruntime v0.0.5
 	github.com/go-git/go-git/v5 v5.16.0
 	github.com/google/go-containerregistry v0.20.3
diff --git a/go.sum b/go.sum
index 8bad886..9e7375d 100644
--- a/go.sum
+++ b/go.sum
@@ -70,8 +70,8 @@ github.com/davidmdm/conf v0.0.8 h1:Ioiv9/xBJZWALwNW5XGygSwN+GVvSvkapoZnA2f0j7o=
 github.com/davidmdm/conf v0.0.8/go.mod h1:xcNNsALh9qR2toeuYnXfyMuOPMVuEAfWN0Nb4lqugzw=
 github.com/davidmdm/x/xcontext v0.0.3 h1:PuqBczX15qx/4128vRVyK+xbLi2ffCWG6JT8rCKJY+U=
 github.com/davidmdm/x/xcontext v0.0.3/go.mod h1:ER3jrDtsl/eNmxrGpbO0/7Ep+0waYnohBR1vKznub1U=
-github.com/davidmdm/x/xerr v0.0.3 h1:WwHvo6qzR+eRmHq69Ftgb7PL9832iwy313XpQyJRGtM=
-github.com/davidmdm/x/xerr v0.0.3/go.mod h1:nEfdhUc3O/FmGUGLiJp2hHRhBeANkon7PJexIQ1DlAE=
+github.com/davidmdm/x/xerr v0.0.4 h1:F0/eoMvc8Yzp/pzSO22vuWs1yZ1yxYuF5z8ot3jZSnM=
+github.com/davidmdm/x/xerr v0.0.4/go.mod h1:hc6jkeZgOLVV46vf3JPTSSLtOSsx4S4reDbTNz7CjwQ=
 github.com/davidmdm/x/xruntime v0.0.5 h1:qIL9l5vHae7IDbSRTAAmjb1Tsldespr0uMMYqxpproI=
 github.com/davidmdm/x/xruntime v0.0.5/go.mod h1:kWVLaIS0EKxZ5NkeSytIDmKBlZjDrAnqbClPhdmUDu4=
 github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
diff --git a/internal/unmarshalling.go b/internal/unmarshalling.go
index 7040eb6..b64bc3b 100644
--- a/internal/unmarshalling.go
+++ b/internal/unmarshalling.go
@@ -32,7 +32,34 @@ type (
 	Stages []Stage
 )
 
-func ParseStages(data []byte) (Stages, error) {
+const (
+	gkNamespace = "Namespace"
+	gkCRD       = "CustomResourceDefinition.apiextensions.k8s.io"
+)
+
+func ParseStages(data []byte) (stages Stages, err error) {
+	defer func() {
+		var withPreStages []Stage
+		for _, stage := range stages {
+			var preStage Stage
+			var regular Stage
+			for _, resource := range stage {
+				if gk := resource.GroupVersionKind().GroupKind().String(); gk == gkNamespace || gk == gkCRD {
+					preStage = append(preStage, resource)
+				} else {
+					regular = append(regular, resource)
+				}
+			}
+			if len(preStage) > 0 {
+				withPreStages = append(withPreStages, preStage)
+			}
+			if len(regular) > 0 {
+				withPreStages = append(withPreStages, regular)
+			}
+		}
+		stages = Stages(withPreStages)
+	}()
+
 	decoder := yaml.NewYAMLToJSONDecoder(bytes.NewReader(data))
 
 	var singleStage Stage


Test patch:
diff --git a/internal/unmarshalling_test.go b/internal/unmarshalling_test.go
index 295d723..837174b 100644
--- a/internal/unmarshalling_test.go
+++ b/internal/unmarshalling_test.go
@@ -80,6 +80,50 @@ func TestParseStaging(t *testing.T) {
 			Input: "hello",
 			Err:   "input must be resource, list of resources, or list of list of resources",
 		},
+		{
+			Name: "namespace and crd in stage with resource",
+			Input: `[
+				{
+					kind: Namespace,
+					apiVersion: v1,
+				},
+				{
+					kind: CustomResourceDefinition,
+					apiVersion: apiextensions.k8s.io/v1,
+				},
+				{
+					kind: Deployment,
+			  },
+			]`,
+			Output: Stages{
+				{
+					&unstructured.Unstructured{Object: map[string]any{"kind": "Namespace", "apiVersion": "v1"}},
+					&unstructured.Unstructured{Object: map[string]any{"kind": "CustomResourceDefinition", "apiVersion": "apiextensions.k8s.io/v1"}},
+				},
+				{
+					&unstructured.Unstructured{Object: map[string]any{"kind": "Deployment"}},
+				},
+			},
+		},
+		{
+			Name: "only namespace and crd in stage",
+			Input: `[
+				{
+					kind: Namespace,
+					apiVersion: v1,
+				},
+				{
+					kind: CustomResourceDefinition,
+					apiVersion: apiextensions.k8s.io/v1,
+				},
+			]`,
+			Output: Stages{
+				{
+					&unstructured.Unstructured{Object: map[string]any{"kind": "Namespace", "apiVersion": "v1"}},
+					&unstructured.Unstructured{Object: map[string]any{"kind": "CustomResourceDefinition", "apiVersion": "apiextensions.k8s.io/v1"}},
+				},
+			},
+		},
 	}
 
 	for _, tc := range cases {