Exercise document-root controls through the public API

This commit is contained in:
2026-11-02 00:44:04 +00:00
parent eb87a10e1c
commit cf9e2fd677
24 changed files with 196 additions and 91 deletions

View File

@@ -230,6 +230,8 @@ stage for the complete repository check.
## Stage 7 — Update facade fixtures and public integration coverage
**Status:** Complete. The root package suite passes, including external public integration regressions.
**Scope:** root facade tests and executable package examples.
1. Migrate root-level test and example inputs that intentionally use controls,

View File

@@ -26,7 +26,7 @@ func ExampleLoad_sequenceDeclaration() {
type Config struct {
Items []Item `yaml:"items"`
}
result, err := configkit.Load[Config](configkit.Bytes("catalog.yml", []byte(`configkit:
result, err := configkit.Load[Config](configkit.Bytes("catalog.yml", []byte(`config:
sequences:
- destination: [items]
key: id

View File

@@ -0,0 +1,103 @@
package configkit_test
import (
"strings"
"testing"
"testing/fstest"
configkit "go.maximumdirect.net/configkit"
)
func TestDocumentRootControlsAndNestedApplicationConfig(t *testing.T) {
type settings struct {
Imports string `yaml:"imports"`
}
type app struct {
Service struct {
Config settings `yaml:"config"`
} `yaml:"service"`
}
result, err := configkit.Load[app](configkit.Bytes("main", []byte("config: {sequences: []}\nservice: {config: {imports: ordinary}}\n")))
if err != nil || result.Config.Service.Config.Imports != "ordinary" {
t.Fatalf("result = %#v, error = %v", result, err)
}
}
func TestMountedConfigDataKeepsControlEvidenceAndHiding(t *testing.T) {
type settings struct {
Imports string `yaml:"imports"`
Token string `yaml:"token" configkit:"secret"`
}
type app struct {
Config settings `yaml:"config"`
}
fs := configkit.NewFilesystem("bundle", fstest.MapFS{
"main.yml": {Data: []byte("config: {imports: [{path: missing.yml}, {path: data.yml, destination: [config]}]}\n")},
"data.yml": {Data: []byte("imports: ordinary\ntoken: disposable-canary\n")},
})
result, err := configkit.Load[app](fs.File("main.yml"), configkit.Options[app]{Imports: true})
if err != nil {
t.Fatal(err)
}
if result.Config.Config.Imports != "ordinary" {
t.Fatalf("config = %#v", result.Config)
}
sources := result.Sources()
if len(sources) != 2 || len(sources[0].EmptyImportSelections) != 1 || sources[0].EmptyImportSelections[0].Path.String() != "/config/imports/0" {
t.Fatalf("sources = %#v", sources)
}
if _, ok := result.Metadata().Lookup(configkit.Keys("config", "imports")); !ok {
t.Fatal("missing application value")
}
if _, ok := result.Explain(configkit.Keys("config", "imports")); !ok {
t.Fatal("missing explanation")
}
var output strings.Builder
if err := result.WriteEffective(&output); err != nil || strings.Contains(output.String(), "disposable-canary") || !strings.Contains(output.String(), "ordinary") {
t.Fatalf("effective output = %q, %v", output.String(), err)
}
}
func TestOldControlSpellingsAreOrdinaryData(t *testing.T) {
body := "configkit: {imports: [{path: nonexistent.yml}]}\n_configkit: ordinary\n"
result, err := configkit.Load[map[string]any](configkit.Bytes("old", []byte(body)))
if err != nil || result.Config["configkit"] == nil || result.Config["_configkit"] != "ordinary" {
t.Fatalf("result = %#v, error = %v", result, err)
}
if _, err := configkit.Load[struct{}](configkit.Bytes("strict", []byte(body))); err == nil {
t.Fatal("strict schema accepted unknown data")
}
}
func TestDefaultsOverridesAndResolutionAtConfigRoot(t *testing.T) {
type settings struct {
Enabled bool `yaml:"enabled"`
Count int `yaml:"count"`
}
type app struct {
Config settings `yaml:"config"`
}
entryExplicit := false
result, err := configkit.Load[app](configkit.NoSource(), configkit.Options[app]{
Definition: configkit.Definition[app]{
Defaults: func() app { return app{Config: settings{Enabled: true, Count: 2}} },
Resolve: func(value *app, r *configkit.Resolution) error {
info, ok := r.EntryInfo(configkit.Keys("config", "enabled"))
entryExplicit = ok && info.Explicit && info.Origin.Layer == configkit.LayerCLI
value.Config.Count = 7
r.RecordNormalization(configkit.Keys("config", "count"), "normalize count")
return nil
},
},
Overrides: []configkit.Override{{Path: configkit.Keys("config", "enabled"), Value: false, Flag: "--enabled"}},
})
if err != nil || result == nil || !entryExplicit || result.Config.Config.Enabled || result.Config.Config.Count != 7 {
t.Fatalf("result = %#v, entry explicit = %t, error = %v", result, entryExplicit, err)
}
if info, ok := result.Metadata().Lookup(configkit.Keys("config", "enabled")); !ok || !info.Explicit || info.Origin.Layer != configkit.LayerCLI {
t.Fatalf("final enabled info = %#v, %t", info, ok)
}
if _, ok := result.Explain(configkit.Keys("config", "count")); !ok {
t.Fatal("missing resolution explanation")
}
}

View File

@@ -109,7 +109,7 @@ func TestFacadeDestinationRootEmptyMappingNoSourceAndInvalidPaths(t *testing.T)
wantReads int
}{
{name: "index segment", source: configkit.Reader("unread", reader), destination: configkit.Keys("catalog").Index(0)},
{name: "reserved configkit key", source: configkit.NoSource(), destination: configkit.Keys("configkit")},
{name: "reserved extends key", source: configkit.NoSource(), destination: configkit.Keys("extends")},
{name: "reserved extends key", source: configkit.NoSource(), destination: configkit.Keys("catalog", "extends")},
} {
t.Run(test.name, func(t *testing.T) {
@@ -129,7 +129,7 @@ func TestFacadeImportedSourcesRetainInputDestination(t *testing.T) {
directory := t.TempDir()
mainPath := filepath.Join(directory, "main.yml")
fragmentPath := filepath.Join(directory, "fragment.yml")
if err := os.WriteFile(mainPath, []byte("configkit: {imports: [{path: fragment.yml}]}\nmain: present\n"), 0o600); err != nil {
if err := os.WriteFile(mainPath, []byte("config: {imports: [{path: fragment.yml}]}\nmain: present\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(fragmentPath, []byte("imported: present\n"), 0o600); err != nil {
@@ -169,7 +169,7 @@ func TestFacadeRelativeImportDestinationsForRootAndMountedLoads(t *testing.T) {
return filename
}
mainPath := write("main.yml", `configkit:
mainPath := write("main.yml", `config:
imports:
- path: metadata.yml
destination: [metadata]
@@ -184,7 +184,7 @@ root: main
write("metadata.yml", "name: imported\n")
write("prompts/a.yml", "a: {name: alpha}\n")
write("prompts/b.yml", "b: {name: beta}\n")
write("entries/main.yml", `configkit:
write("entries/main.yml", `config:
imports:
- path: nested/details.yml
destination: [details]
@@ -505,7 +505,7 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
}
t.Run("imported parse failure retains effective source destination", func(t *testing.T) {
mainPath := write("parse/main.yml", "configkit:\n imports:\n - path: child.yml\n destination: [tenant]\n")
mainPath := write("parse/main.yml", "config:\n imports:\n - path: child.yml\n destination: [tenant]\n")
childPath := write("parse/child.yml", "count: [unterminated\n")
_, err := configkit.LoadLayered[map[string]any](configkit.Input{
Source: configkit.File(mainPath), Imports: true, Destination: configkit.Keys("mount"),
@@ -525,8 +525,8 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
})
t.Run("directive failure stays source local", func(t *testing.T) {
mainPath := write("directive/main.yml", "configkit:\n imports:\n - path: parent.yml\n destination: [tenant]\n")
parentPath := write("directive/parent.yml", "configkit:\n imports:\n - path: details.yml\n destination: [3]\n")
mainPath := write("directive/main.yml", "config:\n imports:\n - path: parent.yml\n destination: [tenant]\n")
parentPath := write("directive/parent.yml", "config:\n imports:\n - path: details.yml\n destination: [3]\n")
_, err := configkit.LoadLayered[map[string]any](configkit.Input{
Source: configkit.File(mainPath), Imports: true, Destination: configkit.Keys("mount"),
})
@@ -535,7 +535,7 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
t.Fatalf("load error = %T %v", err, err)
}
diagnostics := loadError.Diagnostics()
wantPath := configkit.Keys("configkit", "imports").Index(0).Key("destination").Index(0)
wantPath := configkit.Keys("config", "imports").Index(0).Key("destination").Index(0)
if len(diagnostics) != 1 || diagnostics[0].Code != configkit.CodeImportInvalid || !reflect.DeepEqual(diagnostics[0].Path, wantPath) || diagnostics[0].Primary == nil || diagnostics[0].Primary.SourceID != "source-2" {
t.Fatalf("import directive diagnostic = %#v", diagnostics)
}
@@ -546,7 +546,7 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
})
t.Run("composition failure reports effective path and all sources", func(t *testing.T) {
mainPath := write("compose/main.yml", "configkit:\n imports:\n - path: left.yml\n destination: [tenant]\n - path: right.yml\n destination: [tenant]\n")
mainPath := write("compose/main.yml", "config:\n imports:\n - path: left.yml\n destination: [tenant]\n - path: right.yml\n destination: [tenant]\n")
write("compose/left.yml", "value: same\n")
write("compose/right.yml", "value: same\n")
_, err := configkit.LoadLayered[map[string]any](configkit.Input{
@@ -567,7 +567,7 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
})
t.Run("version failure reports effective path and imported source", func(t *testing.T) {
mainPath := write("version/main.yml", "configkit:\n imports:\n - path: child.yml\n destination: [tenant]\n")
mainPath := write("version/main.yml", "config:\n imports:\n - path: child.yml\n destination: [tenant]\n")
childPath := write("version/child.yml", "version: forbidden\n")
_, err := configkit.LoadLayered[map[string]any](configkit.Input{
Source: configkit.File(mainPath), Imports: true, Destination: configkit.Keys("mount"),
@@ -599,7 +599,7 @@ func TestFacadeRelativeImportFailuresRetainSourceRecordsAndCoordinates(t *testin
} `yaml:"tenant"`
} `yaml:"mount"`
}
mainPath := write("typed/main.yml", "configkit:\n imports:\n - path: child.yml\n destination: [tenant]\n")
mainPath := write("typed/main.yml", "config:\n imports:\n - path: child.yml\n destination: [tenant]\n")
childPath := write("typed/child.yml", "count: invalid\n")
_, err := configkit.LoadLayered[configuration](configkit.Input{
Source: configkit.File(mainPath), Imports: true, Destination: configkit.Keys("mount"),

View File

@@ -12,7 +12,7 @@ import (
func TestFacadeCompositionConflictKeepsClaimantOrder(t *testing.T) {
filesystem := configkit.NewFilesystem("bundle", fstest.MapFS{
"a.yml": &fstest.MapFile{Data: []byte(`configkit:
"a.yml": &fstest.MapFile{Data: []byte(`config:
imports:
- path: z.yml
`)},
@@ -21,7 +21,7 @@ func TestFacadeCompositionConflictKeepsClaimantOrder(t *testing.T) {
"z.yml": &fstest.MapFile{Data: []byte("x: z\n")},
})
main := configkit.Mapping("main", map[string]any{
"configkit": map[string]any{"imports": []any{
"config": map[string]any{"imports": []any{
map[string]any{"path": "a.yml"},
map[string]any{"path": "b.yml"},
map[string]any{"path": "c.yml"},

View File

@@ -87,8 +87,8 @@ func TestEquivalentSourceFormsPreserveInputSemantics(t *testing.T) {
func TestRepeatedImportsAcrossTiersAndReaderConsumption(t *testing.T) {
namespace := configkit.NewFilesystem("bundle", fstest.MapFS{
"left.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: shared.yml}]}\n")},
"right.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: shared.yml}]}\n")},
"left.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: shared.yml}]}\n")},
"right.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: shared.yml}]}\n")},
"shared.yml": &fstest.MapFile{Data: []byte("name: retained\n")},
})
type config struct {

View File

@@ -57,7 +57,7 @@ func TestFacadeFilesystemSourceImportsOverlayAndReuse(t *testing.T) {
func TestFacadeFilesystemContextsAndIdentity(t *testing.T) {
first := configkit.NewFilesystem("same", fstest.MapFS{
"root/config/main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: ../shared.yml}]}\n")},
"root/config/main.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: ../shared.yml}]}\n")},
"root/shared.yml": &fstest.MapFile{Data: []byte("items: {value: first}\n")},
"root/overlays/testing.yml": &fstest.MapFile{Data: []byte("items: {overlay: first}\n")},
})
@@ -82,8 +82,8 @@ func TestFacadeFilesystemContextsAndIdentity(t *testing.T) {
source configkit.Source
kind configkit.SourceKind
}{
{"bytes", configkit.Bytes("memory", []byte("configkit: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindBytes},
{"reader", configkit.Reader("stream", strings.NewReader("configkit: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindReader},
{"bytes", configkit.Bytes("memory", []byte("config: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindBytes},
{"reader", configkit.Reader("stream", strings.NewReader("config: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindReader},
} {
t.Run(input.name, func(t *testing.T) {
result, err := configkit.Load(input.source, configkit.Options[filesystemFacadeConfig]{Imports: true, Filesystem: &configkit.FilesystemContext{Root: "root", BaseDir: "root", FS: &first}})

View File

@@ -14,7 +14,7 @@ import (
func TestFacadeNativeDiscoveryPreservesAliasIdentity(t *testing.T) {
root := t.TempDir()
for name, contents := range map[string]string{
"data/item.yml": "configkit:\n imports:\n - path: helper.yml\nvalue: item\n",
"data/item.yml": "config:\n imports:\n - path: helper.yml\nvalue: item\n",
"data/helper.yml": "owner: target\nresource: resource.txt\n",
"aliases/helper.yml": "owner: alias\nresource: resource.txt\n",
"data/resource.txt": "target resource",
@@ -50,7 +50,7 @@ func TestFacadeNativeDiscoveryPreservesAliasIdentity(t *testing.T) {
{"directory/glob", "glob: 'lin*/ite*.yml'", "linked/item.yml", "linked/helper.yml", "target", "target resource"},
} {
t.Run(test.name, func(t *testing.T) {
result, err := configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+test.declaration+"\n")), configkit.Options[configuration]{
result, err := configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+test.declaration+"\n")), configkit.Options[configuration]{
Imports: true, Filesystem: &configkit.FilesystemContext{FS: &filesystem, Root: ".", BaseDir: "."},
})
if err != nil {
@@ -82,14 +82,14 @@ func TestFacadeNativeDiscoveryPreservesAliasIdentity(t *testing.T) {
// The same native path is still a repeat when separately included. An alias
// to a leaf file remains a different native namespace path, as for path imports.
for _, selector := range []string{"path: aliases/item.yml", "dir: aliases\n pattern: item.yml", "glob: 'aliases/ite*.yml'"} {
_, err := configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+selector+"\n - path: aliases/item.yml\n")), configkit.Options[configuration]{
_, err := configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+selector+"\n - path: aliases/item.yml\n")), configkit.Options[configuration]{
Imports: true, Filesystem: &configkit.FilesystemContext{FS: &filesystem, Root: ".", BaseDir: "."},
})
var loadError *configkit.LoadError
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 || loadError.Diagnostics()[0].Code != configkit.CodeImportRepeated {
t.Fatalf("repeated source: %v", err)
}
_, err = configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+selector+"\n - path: data/item.yml\n")), configkit.Options[configuration]{
_, err = configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+selector+"\n - path: data/item.yml\n")), configkit.Options[configuration]{
Imports: true, Filesystem: &configkit.FilesystemContext{FS: &filesystem, Root: ".", BaseDir: "."},
})
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) == 0 || loadError.Diagnostics()[0].Code != configkit.CodeComposeConflict {

View File

@@ -19,7 +19,7 @@ func TestImportDepthChecksSuffixAfterSaturation(t *testing.T) {
{"-0", true},
} {
t.Run(test.depth, func(t *testing.T) {
main := writeFacadeImportFile(t, t.TempDir(), "main.yml", "value: true\nconfigkit:\n imports:\n - dir: absent\n recursive: true\n depth: "+test.depth+"\n")
main := writeFacadeImportFile(t, t.TempDir(), "main.yml", "value: true\nconfig:\n imports:\n - dir: absent\n recursive: true\n depth: "+test.depth+"\n")
result, err := Load[map[string]any](File(main), Options[map[string]any]{Imports: true})
if test.valid {
if err != nil || result.Config["value"] != true {
@@ -31,7 +31,7 @@ func TestImportDepthChecksSuffixAfterSaturation(t *testing.T) {
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 {
t.Fatalf("invalid depth accepted: %v", err)
}
if diagnostic := loadError.Diagnostics()[0]; diagnostic.Code != CodeImportInvalid || diagnostic.Path.String() != "/configkit/imports/0/depth" {
if diagnostic := loadError.Diagnostics()[0]; diagnostic.Code != CodeImportInvalid || diagnostic.Path.String() != "/config/imports/0/depth" {
t.Fatalf("invalid depth diagnostic = %#v", diagnostic)
}
})
@@ -47,12 +47,12 @@ func TestImportDefaultsApplyToTransitiveAndUnderlayImports(t *testing.T) {
IgnoredDeep string `yaml:"ignored_deep"`
}
directory := t.TempDir()
mainPath := writeFacadeImportFile(t, directory, "main.yml", `configkit:
mainPath := writeFacadeImportFile(t, directory, "main.yml", `config:
imports:
- path: parent/parent.yml
main: main
`)
writeFacadeImportFile(t, directory, "parent/parent.yml", `configkit:
writeFacadeImportFile(t, directory, "parent/parent.yml", `config:
imports:
- dir: generated
- dir: explicit
@@ -64,7 +64,7 @@ main: main
explicitPath := writeFacadeImportFile(t, directory, "parent/explicit/exception.yaml", "exception: declaration\n")
writeFacadeImportFile(t, directory, "parent/explicit/deep/ignored.yaml", "ignored_deep: wrong-depth\n")
writeFacadeImportFile(t, directory, "parent/explicit/ignored.cfg", "ignored_deep: wrong-explicit-pattern\n")
underlayPath := writeFacadeImportFile(t, directory, "underlay.yml", `configkit:
underlayPath := writeFacadeImportFile(t, directory, "underlay.yml", `config:
imports:
- dir: underlay-files
`)
@@ -97,7 +97,7 @@ func TestImportDefaultsPreserveEmptyPatternAndRequiredness(t *testing.T) {
Hidden string `yaml:"hidden"`
}
directory := t.TempDir()
mainPath := writeFacadeImportFile(t, directory, "main.yml", `configkit:
mainPath := writeFacadeImportFile(t, directory, "main.yml", `config:
imports:
- dir: snippets
`)
@@ -118,7 +118,7 @@ func TestImportDefaultsPreserveEmptyPatternAndRequiredness(t *testing.T) {
t.Fatalf("empty pattern = %#v, %v", empty, err)
}
emptySources := empty.Sources()
if len(emptySources) != 1 || len(emptySources[0].EmptyImportSelections) != 1 || emptySources[0].EmptyImportSelections[0].Path.String() != "/configkit/imports/0" || emptySources[0].EmptyImportSelections[0].Selector != ImportSelectorDirectory {
if len(emptySources) != 1 || len(emptySources[0].EmptyImportSelections) != 1 || emptySources[0].EmptyImportSelections[0].Path.String() != "/config/imports/0" || emptySources[0].EmptyImportSelections[0].Selector != ImportSelectorDirectory {
t.Fatalf("empty-pattern evidence = %#v", emptySources)
}
required := true
@@ -141,7 +141,7 @@ func TestImportDefaultsAreSnapshottedBeforeOrdinaryAndLayeredCallbacks(t *testin
t.Run(map[bool]string{false: "ordinary", true: "layered"}[layered], func(t *testing.T) {
directory := t.TempDir()
mainPath := writeFacadeImportFile(t, directory, "main.yml", `version: v1
configkit:
config:
imports:
- dir: parts
`)
@@ -229,7 +229,7 @@ func TestPublicImportSelectionSnapshotsAreDetachedAcrossResultErrorAndResolution
Value string `yaml:"value"`
}
directory := t.TempDir()
mainPath := writeFacadeImportFile(t, directory, "main.yml", `configkit:
mainPath := writeFacadeImportFile(t, directory, "main.yml", `config:
imports:
- dir: absent
value: loaded
@@ -242,7 +242,7 @@ value: loaded
}
first.EmptyImportSelections[0].Path = Keys("callback mutation")
second, ok := resolution.Source("source-1")
if !ok || second.EmptyImportSelections[0].Path.String() != "/configkit/imports/0" {
if !ok || second.EmptyImportSelections[0].Path.String() != "/config/imports/0" {
t.Fatalf("resolution snapshot changed after mutation: %#v", second)
}
callbackPath = second.EmptyImportSelections[0].Path.String()
@@ -251,7 +251,7 @@ value: loaded
if err != nil {
t.Fatal(err)
}
if callbackPath != "/configkit/imports/0" {
if callbackPath != "/config/imports/0" {
t.Fatalf("callback path = %q", callbackPath)
}
sources := loaded.Sources()
@@ -259,11 +259,11 @@ value: loaded
t.Fatalf("result source evidence = %#v", sources)
}
sources[0].EmptyImportSelections[0].Path = Keys("result mutation")
if got := loaded.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/configkit/imports/0" {
if got := loaded.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/config/imports/0" {
t.Fatalf("result snapshot changed after mutation: %q", got)
}
failurePath := writeFacadeImportFile(t, directory, "failure.yml", `configkit:
failurePath := writeFacadeImportFile(t, directory, "failure.yml", `config:
imports:
- dir: absent
- path: required-missing.yml
@@ -275,11 +275,11 @@ value: loaded
t.Fatalf("failed load error = %T %v", err, err)
}
errorSources := loadError.Sources()
if len(errorSources) != 1 || len(errorSources[0].EmptyImportSelections) != 1 || errorSources[0].EmptyImportSelections[0].Path.String() != "/configkit/imports/0" {
if len(errorSources) != 1 || len(errorSources[0].EmptyImportSelections) != 1 || errorSources[0].EmptyImportSelections[0].Path.String() != "/config/imports/0" {
t.Fatalf("error source evidence = %#v", errorSources)
}
errorSources[0].EmptyImportSelections[0].Path = Keys("error mutation")
if got := loadError.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/configkit/imports/0" {
if got := loadError.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/config/imports/0" {
t.Fatalf("error snapshot changed after mutation: %q", got)
}
}

View File

@@ -12,7 +12,7 @@ import (
func TestDiscoveredItemHelpersPreserveNestedInheritedResourceEvidence(t *testing.T) {
const canary = "PRIVATE-CONSUMED-HEADER-CANARY"
filesystem := NewFilesystem("bundle", fstest.MapFS{
"bundle/config/main.yml": {Data: []byte(`configkit:
"bundle/config/main.yml": {Data: []byte(`config:
imports:
- dir: records
pattern: '*-item.yml'
@@ -23,7 +23,7 @@ services:
- id: authored
version: authored
`)},
"bundle/config/records/a-item.yml": {Data: []byte(`configkit:
"bundle/config/records/a-item.yml": {Data: []byte(`config:
imports:
- path: helper.yml
version: ` + canary + `

View File

@@ -29,7 +29,7 @@ func TestFacadeDirectoryRootBelowContainedAbsoluteSymlink(t *testing.T) {
for _, follow := range []bool{true, false} {
t.Run(fmt.Sprintf("follow=%t", follow), func(t *testing.T) {
mainPath := filepath.Join(root, "main.yml")
contents := fmt.Sprintf("configkit:\n imports:\n - dir: absolute/parts\n pattern: '*.yml'\n follow: %t\n", follow)
contents := fmt.Sprintf("config:\n imports:\n - dir: absolute/parts\n pattern: '*.yml'\n follow: %t\n", follow)
if err := os.WriteFile(mainPath, []byte(contents), 0o600); err != nil {
t.Fatal(err)
}
@@ -65,7 +65,7 @@ func TestFacadeNativeDiscoveryWithNestedRoot(t *testing.T) {
"dir: parts", "glob: 'parts/*.yml'", "dir: linked", "glob: 'lin*/*.yml'",
} {
t.Run(selector, func(t *testing.T) {
result, err := configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
result, err := configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
if err != nil {
t.Fatal(err)
}
@@ -81,7 +81,7 @@ func TestFacadeNativeDiscoveryWithNestedRoot(t *testing.T) {
t.Fatal(err)
}
for _, selector := range []string{"dir: parts", "glob: 'parts/*.yml'"} {
_, err := configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
_, err := configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
var loadError *configkit.LoadError
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 || loadError.Diagnostics()[0].Code != configkit.CodeImportOutsideRoot {
t.Fatalf("escaping %s: %v", selector, err)
@@ -107,7 +107,7 @@ func TestFacadeDiscoveryAllowsFiniteLinkReuse(t *testing.T) {
if native {
context = &configkit.FilesystemContext{FS: &filesystem, Root: ".", BaseDir: "."}
}
result, err := configkit.Load(configkit.Bytes("main", []byte("configkit:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
result, err := configkit.Load(configkit.Bytes("main", []byte("config:\n imports:\n - "+selector+"\n")), configkit.Options[map[string]any]{Imports: true, Filesystem: context})
if err != nil {
t.Fatalf("native=%v selector=%s: %v", native, selector, err)
}

View File

@@ -231,7 +231,7 @@ func TestFacadeIdentifiedInheritanceFailureDoesNotRevealSecretCanary(t *testing.
func TestFacadeLayeredIdentifiedInheritanceUsesSurvivingRecords(t *testing.T) {
policy := func(mode string) string {
return "configkit:\n sequences:\n - destination: [jobs]\n key: id\n mode: " + mode + "\n"
return "config:\n sequences:\n - destination: [jobs]\n key: id\n mode: " + mode + "\n"
}
tests := []struct {
name string
@@ -416,7 +416,7 @@ func TestFacadeInheritanceFailureStopsLaterCallbacks(t *testing.T) {
func TestFacadeCLIOverridesCannotChangeInheritanceRelationship(t *testing.T) {
filesystem := configkit.NewFilesystem("bundle", fstest.MapFS{
"main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: parent.yml}]}\nentries: {child: {extends: first}}\n")},
"main.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: parent.yml}]}\nentries: {child: {extends: first}}\n")},
"parent.yml": &fstest.MapFile{Data: []byte("entries: {first: {count: 1}, second: {count: 2}}\n")},
})
_, err := configkit.Load(filesystem.File("main.yml"), configkit.Options[inheritedConfiguration]{
@@ -427,7 +427,7 @@ func TestFacadeCLIOverridesCannotChangeInheritanceRelationship(t *testing.T) {
t.Fatalf("CLI inheritance relationship change = %v", err)
}
conflicting := configkit.NewFilesystem("bundle", fstest.MapFS{
"main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: parent.yml}]}\nentries: {child: {extends: first}, first: {count: 3}}\n")},
"main.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: parent.yml}]}\nentries: {child: {extends: first}, first: {count: 3}}\n")},
"parent.yml": &fstest.MapFile{Data: []byte("entries: {first: {count: 1}}\n")},
})
_, err = configkit.Load[inheritedConfiguration](conflicting.File("main.yml"), configkit.Options[inheritedConfiguration]{Imports: true})

View File

@@ -22,14 +22,14 @@ func TestFacadeItemScopesDoNotReinterpretGlobalRegistrations(t *testing.T) {
configkit.SequenceLiteralKey("catalog"), configkit.SequenceAnyMappingKey(), configkit.SequenceLiteralKey("prompts"),
}, "id")
}
item := "configkit: {imports: [{path: helper.yml}, {path: child.yml, destination: [children], placement: sequence-item}]}\n"
item := "config: {imports: [{path: helper.yml}, {path: child.yml, destination: [children], placement: sequence-item}]}\n"
if !missingOuterID {
item += "id: outer\n"
}
files := configkit.NewFilesystem("items", fstest.MapFS{
"main.yml": {Data: []byte("configkit: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
"main.yml": {Data: []byte("config: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
"item.yml": {Data: []byte(item)}, "helper.yml": {Data: []byte(payload)},
"child.yml": {Data: []byte("id: child\nconfigkit: {imports: [{path: child-helper.yml}]}\n")},
"child.yml": {Data: []byte("id: child\nconfig: {imports: [{path: child-helper.yml}]}\n")},
"child-helper.yml": {Data: []byte(payload)},
})
definition := configkit.Definition[map[string]any]{SequenceIdentities: []configkit.SequenceIdentity{

View File

@@ -13,18 +13,18 @@ func TestFacadeItemDomainVersionsKeepEffectiveScope(t *testing.T) {
underlay, mainItem bool
}{
{name: "item", item: "id: item\nversion: domain\n"},
{name: "helper", item: "id: item\nconfigkit: {imports: [{path: helper.yml}]}\n", helper: "version: domain\n"},
{name: "nested", item: "id: parent\nconfigkit: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\n", child: "id: child\nversion: domain\n"},
{name: "helper", item: "id: item\nconfig: {imports: [{path: helper.yml}]}\n", helper: "version: domain\n"},
{name: "nested", item: "id: parent\nconfig: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\n", child: "id: child\nversion: domain\n"},
{name: "underlay", item: "id: item\nversion: domain\n", underlay: true},
{name: "main-item", item: "id: parent\nconfigkit: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\n", child: "id: child\nversion: domain\n", mainItem: true},
{name: "main-item", item: "id: parent\nconfig: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\n", child: "id: child\nversion: domain\n", mainItem: true},
} {
t.Run(test.name, func(t *testing.T) {
files := fstest.MapFS{
"main.yml": {Data: []byte("version: 1\nconfigkit: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
"main.yml": {Data: []byte("version: 1\nconfig: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
"item.yml": {Data: []byte(test.item)},
"child.yml": {Data: []byte(test.child)},
"helper.yml": {Data: []byte(test.helper)},
"underlay.yml": {Data: []byte("configkit: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
"underlay.yml": {Data: []byte("config: {imports: [{path: item.yml, destination: [items], placement: sequence-item}]}\n")},
}
filesystem := configkit.NewFilesystem("items", files)
definition := configkit.Definition[map[string]any]{Version: &configkit.VersionRule{

View File

@@ -28,7 +28,7 @@ func TestFacadeLayeredMixedSourcesAndInspection(t *testing.T) {
t.Fatal(err)
}
lower := configkit.NewFilesystem("bundle", fstest.MapFS{
"main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: defaults.yml}]}\nsettings: {shared: lower, native: retained, secret: old-canary}\nlist: [lower]\n")},
"main.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: defaults.yml}]}\nsettings: {shared: lower, native: retained, secret: old-canary}\nlist: [lower]\n")},
"defaults.yml": &fstest.MapFile{Data: []byte("settings: {imported: retained}\n")},
"overlays/testing.yml": &fstest.MapFile{Data: []byte("settings: {from_lower_namespace: retained}\n")},
})

View File

@@ -80,7 +80,7 @@ func TestFacadeMappingImportsUseExplicitContext(t *testing.T) {
"root/shared.yml": &fstest.MapFile{Data: []byte("name: imported\n")},
})
source := configkit.Mapping("programmatic", map[string]any{
"configkit": map[string]any{"imports": []any{map[string]any{"path": "shared.yml"}}},
"config": map[string]any{"imports": []any{map[string]any{"path": "shared.yml"}}},
"enabled": true,
})
result, err := configkit.Load(source, configkit.Options[mappingFacadeConfig]{

View File

@@ -45,7 +45,7 @@ func TestFacadeSourceContextsFollowOriginsWithoutQueryIO(t *testing.T) {
t.Fatal(err)
}
borrowed := &observedResourceFS{files: fstest.MapFS{
"bundle/config/defaults.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: ../shared.yml}]}\nnative: icon.txt\n")},
"bundle/config/defaults.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: ../shared.yml}]}\nnative: icon.txt\n")},
"bundle/shared.yml": &fstest.MapFile{Data: []byte("shared: shared.txt\n")},
"bundle/overlays/test.yml": &fstest.MapFile{Data: []byte("selected: overlay.txt\n")},
"bundle/config/icon.txt": &fstest.MapFile{Data: []byte("icon-v1")},
@@ -224,8 +224,8 @@ func TestFacadeSyntheticSourceContextsAndContextlessSources(t *testing.T) {
func TestFacadeRelativeImportDestinationsPreserveNativeResourceContexts(t *testing.T) {
borrowed := &observedResourceFS{files: fstest.MapFS{
"bundle/config/main.yml": &fstest.MapFile{Data: []byte("configkit:\n imports:\n - path: entries/parent.yml\n destination: [logical]\n")},
"bundle/config/entries/parent.yml": &fstest.MapFile{Data: []byte("configkit:\n imports:\n - path: nested/details.yml\n destination: [details]\nresource: icon.txt\n")},
"bundle/config/main.yml": &fstest.MapFile{Data: []byte("config:\n imports:\n - path: entries/parent.yml\n destination: [logical]\n")},
"bundle/config/entries/parent.yml": &fstest.MapFile{Data: []byte("config:\n imports:\n - path: nested/details.yml\n destination: [details]\nresource: icon.txt\n")},
"bundle/config/entries/nested/details.yml": &fstest.MapFile{Data: []byte("resource: detail.txt\n")},
"bundle/config/entries/icon.txt": &fstest.MapFile{Data: []byte("parent-resource")},
"bundle/config/entries/nested/detail.txt": &fstest.MapFile{Data: []byte("nested-resource")},

View File

@@ -54,12 +54,12 @@ func TestFacadeNoSourcePreservesAbsenceWithSequencePolicy(t *testing.T) {
func TestFacadeItemHelperHistoryPreservesScheduledPlacement(t *testing.T) {
t.Parallel()
filesystem := configkit.NewFilesystem("history", fstest.MapFS{
"main.yml": {Data: []byte("records: [{id: authored}]\nconfigkit: {imports: [{path: one.yml, destination: [records], placement: sequence-item}, {path: two.yml, destination: [records], placement: sequence-item}]}\n")},
"one.yml": {Data: []byte("id: one\nconfigkit: {imports: [{path: helper-one.yml}, {path: child.yml, destination: [children], placement: sequence-item}]}\n")},
"two.yml": {Data: []byte("id: two\nconfigkit: {imports: [{path: helper-two.yml}]}\n")},
"main.yml": {Data: []byte("records: [{id: authored}]\nconfig: {imports: [{path: one.yml, destination: [records], placement: sequence-item}, {path: two.yml, destination: [records], placement: sequence-item}]}\n")},
"one.yml": {Data: []byte("id: one\nconfig: {imports: [{path: helper-one.yml}, {path: child.yml, destination: [children], placement: sequence-item}]}\n")},
"two.yml": {Data: []byte("id: two\nconfig: {imports: [{path: helper-two.yml}]}\n")},
"helper-one.yml": {Data: []byte("text: first helper\n")},
"helper-two.yml": {Data: []byte("text: second helper\n")},
"child.yml": {Data: []byte("id: child\nconfigkit: {imports: [{path: child-helper.yml}]}\n")},
"child.yml": {Data: []byte("id: child\nconfig: {imports: [{path: child-helper.yml}]}\n")},
"child-helper.yml": {Data: []byte("text: nested helper\n")},
})
result, err := configkit.Load(filesystem.File("main.yml"), configkit.Options[map[string]any]{
@@ -107,7 +107,7 @@ func TestFacadeRegisteredReplacementExplainsRemovedDescendants(t *testing.T) {
{"removed field", []any{map[string]any{"id": "main"}}, configkit.Keys("records").Index(0).Key("text")},
} {
t.Run(test.name, func(t *testing.T) {
mainYAML := "configkit:\n sequences:\n - destination: [records]\n key: id\n mode: replace\n"
mainYAML := "config:\n sequences:\n - destination: [records]\n key: id\n mode: replace\n"
if len(test.upper) == 0 {
mainYAML += "records: []\n"
} else {
@@ -135,12 +135,12 @@ func TestFacadeRegisteredReplacementExplainsRemovedDescendants(t *testing.T) {
func TestFacadeItemConflictDiagnosticsFollowEnclosingIndexes(t *testing.T) {
t.Parallel()
filesystem := configkit.NewFilesystem("conflicts", fstest.MapFS{
"main.yml": {Data: []byte("records: [{id: authored}]\nconfigkit: {imports: [{path: good.yml, destination: [records], placement: sequence-item}, {path: bad.yml, destination: [records], placement: sequence-item}]}\n")},
"group.yml": {Data: []byte("records: [{id: authored}]\nconfigkit: {imports: [{path: bad.yml, destination: [records], placement: sequence-item}]}\n")},
"nested.yml": {Data: []byte("records: [{id: authored}]\nconfigkit: {imports: [{path: parent.yml, destination: [records], placement: sequence-item}]}\n")},
"parent.yml": {Data: []byte("id: parent\nchildren: [{id: authored-child}]\nconfigkit: {imports: [{path: bad.yml, destination: [children], placement: sequence-item}]}\n")},
"main.yml": {Data: []byte("records: [{id: authored}]\nconfig: {imports: [{path: good.yml, destination: [records], placement: sequence-item}, {path: bad.yml, destination: [records], placement: sequence-item}]}\n")},
"group.yml": {Data: []byte("records: [{id: authored}]\nconfig: {imports: [{path: bad.yml, destination: [records], placement: sequence-item}]}\n")},
"nested.yml": {Data: []byte("records: [{id: authored}]\nconfig: {imports: [{path: parent.yml, destination: [records], placement: sequence-item}]}\n")},
"parent.yml": {Data: []byte("id: parent\nchildren: [{id: authored-child}]\nconfig: {imports: [{path: bad.yml, destination: [children], placement: sequence-item}]}\n")},
"good.yml": {Data: []byte("id: good\n")},
"bad.yml": {Data: []byte("id: bad\nconfigkit: {imports: [{path: helper.yml}]}\n")},
"bad.yml": {Data: []byte("id: bad\nconfig: {imports: [{path: helper.yml}]}\n")},
"helper.yml": {Data: []byte("id: duplicate-field\n")},
})
definition := configkit.Definition[map[string]any]{SequenceIdentities: []configkit.SequenceIdentity{configkit.SequenceIdentityAt(configkit.Keys("records"), "id")}}
@@ -277,7 +277,7 @@ func TestFacadeSequencePlacementControlsAcrossLoadEntryPoints(t *testing.T) {
func TestFacadeItemImportGlobComposesWithAuthoredSequence(t *testing.T) {
directory := t.TempDir()
mainPath := filepath.Join(directory, "main.yml")
if err := os.WriteFile(mainPath, []byte(`configkit:
if err := os.WriteFile(mainPath, []byte(`config:
imports:
- glob: records/*.yml
destination: [items]
@@ -358,7 +358,7 @@ func TestFacadeItemDestinationFallbackEvidenceSurvivesFailures(t *testing.T) {
directory := t.TempDir()
mainPath := filepath.Join(directory, "main.yml")
helperPath := filepath.Join(directory, "helper.yml")
if err := os.WriteFile(mainPath, []byte("configkit: {imports: [{path: helper.yml, destination: [metadata]}]}\nid: main\n"), 0o600); err != nil {
if err := os.WriteFile(mainPath, []byte("config: {imports: [{path: helper.yml, destination: [metadata]}]}\nid: main\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(helperPath, []byte("value: [unterminated\n"), 0o600); err != nil {
@@ -430,10 +430,10 @@ func TestFacadeNestedItemFallbackUsesNearestResolvedContainer(t *testing.T) {
mainPath := filepath.Join(directory, "main.yml")
childPath := filepath.Join(directory, "child.yml")
helperPath := filepath.Join(directory, "helper.yml")
if err := os.WriteFile(mainPath, []byte("configkit: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\nid: parent\n"), 0o600); err != nil {
if err := os.WriteFile(mainPath, []byte("config: {imports: [{path: child.yml, destination: [children], placement: sequence-item}]}\nid: parent\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(childPath, []byte("configkit: {imports: [{path: helper.yml, destination: [metadata]}]}\nid: child\n"), 0o600); err != nil {
if err := os.WriteFile(childPath, []byte("config: {imports: [{path: helper.yml, destination: [metadata]}]}\nid: child\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(helperPath, []byte("value: [unterminated\n"), 0o600); err != nil {
@@ -556,7 +556,7 @@ func TestFacadeSequenceReplacementKeepsTypedAndHistoricalEvidenceAligned(t *test
directory := t.TempDir()
mainPath := filepath.Join(directory, "main.yml")
underlayPath := filepath.Join(directory, "underlay.yml")
if err := os.WriteFile(mainPath, []byte(`configkit:
if err := os.WriteFile(mainPath, []byte(`config:
sequences:
- destination: [entries]
key: id
@@ -571,7 +571,7 @@ entries:
`), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(underlayPath, []byte(`configkit:
if err := os.WriteFile(underlayPath, []byte(`config:
imports:
- glob: records/*.yml
destination: [entries]

View File

@@ -131,7 +131,7 @@ func TestUnderlayVersionProtectionUsesMainRecordPosition(t *testing.T) {
want := configkit.CodeUnderlayVersion
if imported {
files := configkit.NewFilesystem("lower", fstest.MapFS{
"main.yml": {Data: []byte("configkit: {imports: [{path: fragment.yml}]}\n")},
"main.yml": {Data: []byte("config: {imports: [{path: fragment.yml}]}\n")},
"fragment.yml": {Data: []byte(payload)},
})
lower.Source, lower.Imports = files.File("main.yml"), true

View File

@@ -40,7 +40,7 @@ func TestFacadeSourceVersionEvidenceFollowsAssembledSequenceRanges(t *testing.T)
})
} else {
filesystem := configkit.NewFilesystem("versions", fstest.MapFS{
"main.yml": {Data: []byte("configkit: {imports: [{path: child.yml}]}\n" + first)},
"main.yml": {Data: []byte("config: {imports: [{path: child.yml}]}\n" + first)},
"child.yml": {Data: []byte(child)},
})
result, err = configkit.Load(filesystem.File("main.yml"), configkit.Options[map[string]any]{
@@ -98,7 +98,7 @@ func TestFacadeSourceVersionOwnershipAcceptsContextualIndexes(t *testing.T) {
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Bytes("lower", []byte(child))}}}},
})
} else {
filesystem := configkit.NewFilesystem("versions", fstest.MapFS{"main.yml": {Data: []byte("configkit: {imports: [{path: child.yml}]}\n" + first)}, "child.yml": {Data: []byte(child)}})
filesystem := configkit.NewFilesystem("versions", fstest.MapFS{"main.yml": {Data: []byte("config: {imports: [{path: child.yml}]}\n" + first)}, "child.yml": {Data: []byte(child)}})
result, err = configkit.Load(filesystem.File("main.yml"), configkit.Options[map[string]any]{Definition: definition, SourceVersionMode: configkit.SourceVersionModeRequired, Imports: true})
}
if err != nil || result == nil {
@@ -121,7 +121,7 @@ func TestFacadeItemMainKeepsDefaultVersionOwnership(t *testing.T) {
helper = "other: {version: permitted}\n"
}
filesystem := configkit.NewFilesystem("item-main", fstest.MapFS{
"main.yml": {Data: []byte(body + "configkit: {imports: [{path: helper.yml}]}\n")}, "helper.yml": {Data: []byte(helper)},
"main.yml": {Data: []byte(body + "config: {imports: [{path: helper.yml}]}\n")}, "helper.yml": {Data: []byte(helper)},
})
checks := 0
definition := configkit.Definition[map[string]any]{Version: &configkit.VersionRule{
@@ -223,7 +223,7 @@ func TestFacadeSourceVersionModesPreserveImportOptIn(t *testing.T) {
t.Parallel()
for _, mode := range []configkit.SourceVersionMode{configkit.SourceVersionModeIfPresent, configkit.SourceVersionModeRequired} {
for _, underlay := range []bool{false, true} {
bad := configkit.Bytes("disabled-imports", []byte("version: accepted\nconfigkit: {imports: [{path: missing.yml}]}\nvalue: visible\n"))
bad := configkit.Bytes("disabled-imports", []byte("version: accepted\nconfig: {imports: [{path: missing.yml}]}\nvalue: visible\n"))
definition := configkit.Definition[map[string]any]{Version: &configkit.VersionRule{
Path: configkit.Keys("version"), Check: func(configkit.Version, *configkit.Validation) error { return nil },
}}
@@ -246,7 +246,7 @@ func TestFacadeSourceVersionModesPreserveImportOptIn(t *testing.T) {
continue
}
diagnostics := failure.Diagnostics()
if len(diagnostics) != 1 || diagnostics[0].Code != configkit.CodeImportDisabled || diagnostics[0].Path.String() != "/configkit" ||
if len(diagnostics) != 1 || diagnostics[0].Code != configkit.CodeImportDisabled || diagnostics[0].Path.String() != "/config" ||
diagnostics[0].Primary == nil || diagnostics[0].Primary.SourceID != wantSource {
t.Errorf("mode=%v underlay=%v: diagnostics=%#v", mode, underlay, diagnostics)
}
@@ -636,7 +636,7 @@ func TestFacadeSourceVersionEvidenceOnFailedLoadsAndSyntheticSources(t *testing.
Path: configkit.Keys("version"), Check: func(configkit.Version, *configkit.Validation) error { checked++; return nil },
}}
path := filepath.Join(t.TempDir(), "main.yml")
contents := "version: " + canary + "\nconfigkit:\n imports:\n - path: missing.yml\n required: true\n"
contents := "version: " + canary + "\nconfig:\n imports:\n - path: missing.yml\n required: true\n"
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
t.Fatal(err)
}

View File

@@ -16,7 +16,7 @@ func TestUnderlaySequenceDescendantOrigins(t *testing.T) {
}
t.Run(name, func(t *testing.T) {
bundle := configkit.NewFilesystem("bundle", fstest.MapFS{
"main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: items.yml}]}\n")},
"main.yml": &fstest.MapFile{Data: []byte("config: {imports: [{path: items.yml}]}\n")},
"items.yml": &fstest.MapFile{Data: []byte("items: [{name: first, nested: [false]}]\n")},
})
tiers := []configkit.Underlay{}

View File

@@ -74,10 +74,10 @@ func TestSourceVersionEvidenceConversion(t *testing.T) {
}
func TestImportSelectionConversion(t *testing.T) {
file := writeRecordConfig(t, "configkit:\n imports:\n - glob: absent/*.yml\nvalue: main\n")
file := writeRecordConfig(t, "config:\n imports:\n - glob: absent/*.yml\nvalue: main\n")
internal := engineSourceInfoFromLoad(t, file, "source-1", engine.Options[recordConfig]{Imports: true})
converted := fromEngineSourceInfo(internal)
if len(converted.EmptyImportSelections) != 1 || converted.EmptyImportSelections[0].Path.String() != "/configkit/imports/0" ||
if len(converted.EmptyImportSelections) != 1 || converted.EmptyImportSelections[0].Path.String() != "/config/imports/0" ||
converted.EmptyImportSelections[0].Location.SourceID != internal.ID || converted.EmptyImportSelections[0].Location.Line != 3 ||
converted.EmptyImportSelections[0].Selector != ImportSelectorGlob {
t.Fatalf("converted selection evidence = %#v", converted.EmptyImportSelections)

View File

@@ -17,7 +17,7 @@ func TestResultSourceLookup(t *testing.T) {
t.Fatal(err)
}
mainPath := writeSourceLookupFile(t, directory, "main.yml", `version: MAIN-SOURCE-CANARY
configkit:
config:
imports:
- path: imported.yml
- dir: absent
@@ -122,20 +122,20 @@ imported_value: imported
func TestLoadErrorSourceLookup(t *testing.T) {
directory := t.TempDir()
mainPath := writeSourceLookupFile(t, directory, "main.yml", `configkit:
mainPath := writeSourceLookupFile(t, directory, "main.yml", `config:
imports:
- path: item.yml
destination: [items]
placement: sequence-item
`)
writeSourceLookupFile(t, directory, "item.yml", `configkit:
writeSourceLookupFile(t, directory, "item.yml", `config:
imports:
- path: helper.yml
destination: [metadata]
`)
const canary = "FAILED-SOURCE-LOOKUP-CANARY"
helperPath := writeSourceLookupFile(t, directory, "helper.yml", `version: `+canary+`
configkit:
config:
imports:
- dir: absent
- path: missing.yml

View File

@@ -1,4 +1,4 @@
configkit:
config:
imports:
- path: ../shared.yml
items: