Working on clarifying docs

This commit is contained in:
Mike Farah 2025-07-22 11:51:33 +10:00
parent db2a4550e5
commit d5757fc82b
3 changed files with 51 additions and 130 deletions

View File

@ -8,9 +8,13 @@ Use the `alias` and `anchor` operators to read and write yaml aliases and anchor
## NOTE --yaml-fix-merge-anchor-to-spec flag ## NOTE --yaml-fix-merge-anchor-to-spec flag
`yq` doesn't merge anchors `<<:` to spec, in some circumstances it incorrectly overrides existing keys when the spec documents not to do that. `yq` doesn't merge anchors `<<:` to spec, in some circumstances it incorrectly overrides existing keys when the spec documents not to do that.
To minimise disruption while still fixing the issue, a flag has been added to toggle this behaviour. This will first default to false; and log warnings to users. Then it will default to true (and still allow users to specify false if needed) To minimise disruption while still fixing the issue, a flag has been added to toggle this behaviour. This will first default to false; and log warnings to users. Then it will default to true (and still allow users to specify false if needed).
See examples of the flag difference below. This flag also enables advanced merging, like inline maps, as well as fixes to ensure when exploding a particular path, neighbours are not affect ed.
Long story short, you should be setting this flag to true.
See examples of the flag differences below.
## Merge one map ## Merge one map
@ -279,8 +283,8 @@ foobar:
thing: foobar_thing thing: foobar_thing
``` ```
## Merge multiple maps ## LEGACY: Merge multiple maps
see https://yaml.org/type/merge.html see https://yaml.org/type/merge.html. This has the correct data, but the wrong key order; set --yaml-fix-merge-anchor-to-spec=true to fix the key order.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
@ -309,8 +313,8 @@ x: 1
y: 2 y: 2
``` ```
## Override ## LEGACY: Override
see https://yaml.org/type/merge.html see https://yaml.org/type/merge.html. This has the correct data, but the wrong key order; set --yaml-fix-merge-anchor-to-spec=true to fix the key order.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
@ -342,7 +346,8 @@ y: 2
``` ```
## FIXED: Explode with merge anchors ## FIXED: Explode with merge anchors
See the foobarList.b property is still foobarList_b. Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour. Flag will default to true in late 2025 Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour (flag will default to true in late 2025).
Observe that foobarList.b property is still foobarList_b.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
@ -390,8 +395,9 @@ foobar:
thing: foobar_thing thing: foobar_thing
``` ```
## Merge multiple maps ## FIXED: Merge multiple maps
see https://yaml.org/type/merge.html Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour (flag will default to true in late 2025).
Taken from https://yaml.org/type/merge.html. Same values as legacy, but with the correct key order.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
@ -420,8 +426,9 @@ y: 2
r: 10 r: 10
``` ```
## Override ## FIXED: Override
see https://yaml.org/type/merge.html Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour (flag will default to true in late 2025).
Taken from https://yaml.org/type/merge.html. Same values as legacy, but with the correct key order.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
@ -452,114 +459,25 @@ y: 2
x: 1 x: 1
``` ```
## FIXED: Explode with merge anchors ## Exploding inline merge anchor
See the foobarList.b property is still foobarList_b. Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour. Flag will default to true in late 2025 Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour (flag will default to true in late 2025).
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
foo: &foo a:
a: foo_a b: &b 42
thing: foo_thing !!merge <<:
c: foo_c c: *b
bar: &bar
b: bar_b
thing: bar_thing
c: bar_c
foobarList:
b: foobarList_b
!!merge <<:
- *foo
- *bar
c: foobarList_c
foobar:
c: foobar_c
!!merge <<: *foo
thing: foobar_thing
``` ```
then then
```bash ```bash
yq 'explode(.)' sample.yml yq 'explode(.) | sort_keys(.)' sample.yml
``` ```
will output will output
```yaml ```yaml
foo: a:
a: foo_a b: 42
thing: foo_thing c: 42
c: foo_c
bar:
b: bar_b
thing: bar_thing
c: bar_c
foobarList:
b: foobarList_b
a: foo_a
thing: foo_thing
c: foobarList_c
foobar:
c: foobar_c
a: foo_a
thing: foobar_thing
```
## Merge multiple maps
see https://yaml.org/type/merge.html
Given a sample.yml file of:
```yaml
- &CENTER
x: 1
y: 2
- &LEFT
x: 0
y: 2
- &BIG
r: 10
- &SMALL
r: 1
- !!merge <<:
- *CENTER
- *BIG
```
then
```bash
yq '.[4] | explode(.)' sample.yml
```
will output
```yaml
x: 1
y: 2
r: 10
```
## Override
see https://yaml.org/type/merge.html
Given a sample.yml file of:
```yaml
- &CENTER
x: 1
y: 2
- &LEFT
x: 0
y: 2
- &BIG
r: 10
- &SMALL
r: 1
- !!merge <<:
- *BIG
- *LEFT
- *SMALL
x: 1
```
then
```bash
yq '.[4] | explode(.)' sample.yml
```
will output
```yaml
r: 10
y: 2
x: 1
``` ```

View File

@ -111,7 +111,7 @@ var fixedAnchorOperatorScenarios = []expressionScenario{
}, },
{ {
description: "FIXED: Explode with merge anchors", description: "FIXED: Explode with merge anchors",
subdescription: "See the foobarList.b property is still foobarList_b. Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour. Flag will default to true in late 2025 ", subdescription: "Observe that foobarList.b property is still foobarList_b.",
document: mergeDocSample, document: mergeDocSample,
expression: `explode(.)`, expression: `explode(.)`,
expected: []string{explodeMergeAnchorsFixedExpected}, expected: []string{explodeMergeAnchorsFixedExpected},
@ -137,25 +137,24 @@ var fixedAnchorOperatorScenarios = []expressionScenario{
}, },
}, },
{ {
description: "Merge multiple maps", description: "FIXED: Merge multiple maps",
subdescription: "see https://yaml.org/type/merge.html", subdescription: "Taken from https://yaml.org/type/merge.html. Same values as legacy, but with the correct key order.",
document: specDocument + "- << : [ *CENTER, *BIG ]\n", document: specDocument + "- << : [ *CENTER, *BIG ]\n",
expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
expected: []string{"D0, P[4], (!!map)::x: 1\ny: 2\nr: 10\n"}, expected: []string{"D0, P[4], (!!map)::x: 1\ny: 2\nr: 10\n"},
}, },
{ {
description: "Override", description: "FIXED: Override",
subdescription: "see https://yaml.org/type/merge.html", subdescription: "Taken from https://yaml.org/type/merge.html. Same values as legacy, but with the correct key order.",
document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n", document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
expected: []string{"D0, P[4], (!!map)::r: 10\ny: 2\nx: 1\n"}, expected: []string{"D0, P[4], (!!map)::r: 10\ny: 2\nx: 1\n"},
}, },
{ {
skipDoc: true, description: "Exploding inline merge anchor",
description: "Exploding inline merge anchor", // subdescription: "`<<` map must be exploded, otherwise `c: *b` will become invalid",
subdescription: "`<<` map must be exploded, otherwise `c: *b` will become invalid", document: `{a: {b: &b 42}, <<: {c: *b}}`,
document: `{a: {b: &b 42}, <<: {c: *b}}`, expression: `explode(.) | sort_keys(.)`,
expression: `explode(.) | sort_keys(.)`,
expected: []string{ expected: []string{
"D0, P[], (!!map)::{a: {b: 42}, c: 42}\n", "D0, P[], (!!map)::{a: {b: 42}, c: 42}\n",
}, },
@ -255,18 +254,19 @@ var badAnchorOperatorScenarios = []expressionScenario{
}, },
}, },
{ {
description: "Merge multiple maps", description: "LEGACY: Merge multiple maps",
subdescription: "see https://yaml.org/type/merge.html", subdescription: "see https://yaml.org/type/merge.html. This has the correct data, but the wrong key order; set --yaml-fix-merge-anchor-to-spec=true to fix the key order.",
document: specDocument + "- << : [ *CENTER, *BIG ]\n", document: specDocument + "- << : [ *CENTER, *BIG ]\n",
expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"}, // correct data, but wrong key order expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
}, },
{ {
description: "Override", description: "LEGACY: Override",
subdescription: "see https://yaml.org/type/merge.html", subdescription: "see https://yaml.org/type/merge.html. This has the correct data, but the wrong key order; set --yaml-fix-merge-anchor-to-spec=true to fix the key order.",
document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
expression: ".[4] | explode(.)", document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"}, expression: ".[4] | explode(.)",
expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
}, },
} }
@ -501,7 +501,10 @@ func TestAnchorAliasOperatorAlignedToSpecScenarios(t *testing.T) {
ConfiguredYamlPreferences.FixMergeAnchorToSpec = true ConfiguredYamlPreferences.FixMergeAnchorToSpec = true
for _, tt := range append(fixedAnchorOperatorScenarios, anchorOperatorScenarios...) { for _, tt := range append(fixedAnchorOperatorScenarios, anchorOperatorScenarios...) {
testScenario(t, &tt) testScenario(t, &tt)
}
for i, tt := range fixedAnchorOperatorScenarios {
fixedAnchorOperatorScenarios[i].subdescription = "Set `--yaml-fix-merge-anchor-to-spec=true` to get this correct merge behaviour (flag will default to true in late 2025).\n" + tt.subdescription
} }
appendOperatorDocumentScenario(t, "anchor-and-alias-operators", fixedAnchorOperatorScenarios) appendOperatorDocumentScenario(t, "anchor-and-alias-operators", fixedAnchorOperatorScenarios)
ConfiguredYamlPreferences.FixMergeAnchorToSpec = false ConfiguredYamlPreferences.FixMergeAnchorToSpec = false

View File

@ -255,7 +255,7 @@ func documentScenarios(t *testing.T, folder string, title string, scenarios []in
func appendOperatorDocumentScenario(t *testing.T, title string, scenarios []expressionScenario) { func appendOperatorDocumentScenario(t *testing.T, title string, scenarios []expressionScenario) {
filename := fmt.Sprintf("doc/%v/%v.md", "operators", title) filename := fmt.Sprintf("doc/%v/%v.md", "operators", title)
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND, fs.ModeAppend) f, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_APPEND, fs.ModeAppend)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return