diff --git a/act/schema/schema.go b/act/schema/schema.go index cbb51283..e1d41e96 100644 --- a/act/schema/schema.go +++ b/act/schema/schema.go @@ -237,6 +237,9 @@ func (s *Node) UnmarshalYAML(node *yaml.Node) error { if node != nil && node.Kind == yaml.DocumentNode { return s.UnmarshalYAML(node.Content[0]) } + if node != nil && node.Kind == yaml.AliasNode { + return s.UnmarshalYAML(node.Alias) + } def := s.Schema.GetDefinition(s.Definition) if s.Context == nil { s.Context = def.Context @@ -360,6 +363,15 @@ func (s *Node) checkMapping(node *yaml.Node, def Definition) error { if node.Kind != yaml.MappingNode { return fmt.Errorf("%sExpected a mapping got %v", formatLocation(node), getStringKind(node.Kind)) } + // merges cannot be conveniently validated and are skipped + // https://yaml.org/type/merge.html + for i, n := range node.Content { + if i%2 == 0 { + if n.Kind == yaml.ScalarNode && n.Value == "<<" && (n.Tag == "" || n.ShortTag() == "!!merge") { + return nil + } + } + } insertDirective := regexp.MustCompile(`\${{\s*insert\s*}}`) var allErrors error for i, k := range node.Content { diff --git a/act/schema/schema_test.go b/act/schema/schema_test.go index dc54834e..2e77f3b7 100644 --- a/act/schema/schema_test.go +++ b/act/schema/schema_test.go @@ -243,3 +243,39 @@ runs: }) } } + +// https://yaml.org/spec/1.2.1/#id2785586 +// An anchor is denoted by the “&” indicator. It marks a node for future reference. +// https://yaml.org/type/merge.html +// Specify one or more mappings to be merged with the current one. +func TestSchema_AnchorAndReference(t *testing.T) { + var node yaml.Node + err := yaml.Unmarshal([]byte(` +on: [push] +jobs: + test1: + runs-on: docker + steps: + - &step + run: echo All good! + - *step + test2: + runs-on: docker + steps: + - << : *step + name: other name + test3: + runs-on: docker + steps: + - !!merge << : *step + name: other name +`), &node) + if !assert.NoError(t, err) { + return + } + err = (&Node{ + Definition: "workflow-root", + Schema: GetWorkflowSchema(), + }).UnmarshalYAML(&node) + assert.NoError(t, err) +}