Update the simple configuration consumer
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Shared reporting and PromptKit v0.20.0 implementation plan
|
||||
|
||||
Status: implementation in progress; Stages 1–20 complete.
|
||||
Status: implementation in progress; Stages 1–21 complete.
|
||||
|
||||
## Scope, authority, and execution
|
||||
|
||||
@@ -756,6 +756,11 @@ snapshots and upstream validation-rule tests.
|
||||
|
||||
## Stage 21: Simple consumer and core/configuration API exercise
|
||||
|
||||
**Complete.** The simple consumer opts into native overrides and demonstrates
|
||||
the new inspection and failure workflows. The core consumer's structured report
|
||||
and template remain exercised. Core example and ckconfig workspace tests passed
|
||||
with Go 1.27.0.
|
||||
|
||||
Update the maintained [simple ckconfig consumer](../../integrations/ckconfig/examples/simple)
|
||||
to install an explicitly configured FromConfigKit scope with Overrides enabled,
|
||||
replacing AppCommand convenience wiring there. Append the selected native CLI
|
||||
|
||||
@@ -11,7 +11,12 @@ Run the maintained example with:
|
||||
go run . config show
|
||||
go run . config show --config fixtures/before.yml --verbose
|
||||
go run . config show --config fixtures/before.yml --quiet
|
||||
go run . config explain --list --under /schema
|
||||
go run . config show --path /greeting --set '/greeting="Hi"'
|
||||
go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml
|
||||
go run . config diff --set '/greeting="Hi"' --details --check
|
||||
go run . config validate --config fixtures/invalid.yml --details --severity error
|
||||
go run . config sources --config fixtures/invalid.yml --source-id source-1
|
||||
go run . greet
|
||||
go run . greet --count=0 --tag=first --tag second
|
||||
```
|
||||
@@ -25,3 +30,8 @@ command loads the two local fixtures and reports `changes.greeting: Goodbye`.
|
||||
The before fixture uses schema version 1, which ConfigKit reports as a provider
|
||||
warning in verbose mode. Ordinary mode hides the warning while preserving the
|
||||
effective YAML report; quiet mode suppresses that report.
|
||||
The invalid fixture demonstrates a failed-load report and captured source
|
||||
inventory; `source-1` is the ID from that fixture's acquisition. The scope opts
|
||||
in to transient overrides and passes them into its normal ConfigKit load. The
|
||||
diff example compares an overridden left side with ordinary configuration on
|
||||
the right and returns status 3 because the values differ.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
schema:
|
||||
version: 2
|
||||
greeting: [invalid]
|
||||
@@ -49,10 +49,15 @@ func loadAppConfiguration(_ context.Context, selection ckconfig.Selection) (*con
|
||||
options.Overlay = selection.Overlay.Value
|
||||
options.Filesystem = &configkit.FilesystemContext{Root: ".", BaseDir: "."}
|
||||
}
|
||||
options.Overrides = append(options.Overrides, selection.Overrides...)
|
||||
return configkit.Load(source, options)
|
||||
}
|
||||
|
||||
func newApp() (*commandkit.App, error) {
|
||||
return newAppWithLoader(loadAppConfiguration)
|
||||
}
|
||||
|
||||
func newAppWithLoader(load func(context.Context, ckconfig.Selection) (*configkit.Result[appConfiguration], error)) (*commandkit.App, error) {
|
||||
countDefault := 1
|
||||
tagDefaults := []string{"example"}
|
||||
greet := commandkit.NewCommand(commandkit.CommandSpec[greetInput]{
|
||||
@@ -68,7 +73,7 @@ func newApp() (*commandkit.App, error) {
|
||||
},
|
||||
Run: func(invocation commandkit.Invocation, input greetInput) commandkit.Outcome {
|
||||
reporter := invocation.Reporter()
|
||||
configuration, err := loadAppConfiguration(invocation.Context, ckconfig.Selection{})
|
||||
configuration, err := load(invocation.Context, ckconfig.Selection{})
|
||||
if err != nil {
|
||||
return commandkit.Failure("Could not load application configuration.").WithCause(err)
|
||||
}
|
||||
@@ -87,9 +92,13 @@ func newApp() (*commandkit.App, error) {
|
||||
return commandkit.Success()
|
||||
},
|
||||
})
|
||||
scope := ckconfig.FromConfigKit("app", "Application configuration.", func(ctx context.Context, selection ckconfig.Selection, _, _ struct{}) (*configkit.Result[appConfiguration], error) {
|
||||
return load(ctx, selection)
|
||||
})
|
||||
scope.Features.Overrides = true
|
||||
return commandkit.New(
|
||||
commandkit.Identity{Name: "simple-example", Version: "1.0"},
|
||||
ckconfig.AppCommand(loadAppConfiguration),
|
||||
ckconfig.Command(ckconfig.Suite[struct{}, struct{}]{Scopes: []ckconfig.Scope[struct{}, struct{}]{scope}}),
|
||||
greet,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.maximumdirect.net/ckconfig"
|
||||
commandkit "go.maximumdirect.net/commandkit"
|
||||
configkit "go.maximumdirect.net/configkit"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
@@ -147,3 +149,55 @@ func decodeReport(data []byte) (*yaml.Node, error) {
|
||||
}
|
||||
return document.Content[0], nil
|
||||
}
|
||||
|
||||
func TestSimpleInspectionAndIndependentOverrides(t *testing.T) {
|
||||
outcome, output, _ := executeSimple(t, "config", "explain", "--list", "--under=/schema", "--format=json")
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output, `"path": "/schema/version"`) {
|
||||
t.Fatalf("discovery = %#v %q", outcome, output)
|
||||
}
|
||||
outcome, output, _ = executeSimple(t, "config", "show", "--path=/greeting", "--set=/greeting=\"Hi\"")
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || output != "Hi\n" {
|
||||
t.Fatalf("focused override = %#v %q", outcome, output)
|
||||
}
|
||||
outcome, output, _ = executeSimple(t, "config", "diff", "--set=/greeting=\"Hi\"", "--details", "--check", "--format=json")
|
||||
if outcome.Kind != commandkit.OutcomeDomain || outcome.Status != 3 || !strings.Contains(output, `"before"`) || !strings.Contains(output, `"after"`) {
|
||||
t.Fatalf("independent diff = %#v %q", outcome, output)
|
||||
}
|
||||
outcome, output, _ = executeSimple(t, "config", "diff", "--set=/greeting=\"Hi\"", "--against-set=/greeting=\"Hi\"", "--details", "--check", "--format=json")
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output, `"differences": []`) {
|
||||
t.Fatalf("equal overrides = %#v %q", outcome, output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleFailedLoadReportsEvidence(t *testing.T) {
|
||||
_, failure := loadAppConfiguration(context.Background(), ckconfig.Selection{Config: commandkit.Supplied[string]{Value: "fixtures/invalid.yml", Set: true}})
|
||||
var native *configkit.LoadError
|
||||
if !errors.As(failure, &native) || len(native.Sources()) == 0 {
|
||||
t.Fatalf("fixture failure = %v", failure)
|
||||
}
|
||||
outcome, output, _ := executeSimple(t, "config", "validate", "--config=fixtures/invalid.yml", "--details", "--severity=error", "--format=json")
|
||||
if outcome.Kind != commandkit.OutcomeOperational || !strings.Contains(output, `"state": "present"`) || !strings.Contains(output, `"severity": "error"`) {
|
||||
t.Fatalf("detailed failure = %#v %q", outcome, output)
|
||||
}
|
||||
outcome, output, _ = executeSimple(t, "config", "sources", "--config=fixtures/invalid.yml", "--source-id="+native.Sources()[0].ID, "--format=json")
|
||||
if outcome.Kind != commandkit.OutcomeOperational || !strings.Contains(output, `"id":`) || !strings.Contains(output, "invalid.yml") {
|
||||
t.Fatalf("source failure = %#v %q", outcome, output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleMetadataCommandsDoNotLoadConfiguration(t *testing.T) {
|
||||
loads := 0
|
||||
app, err := newAppWithLoader(func(context.Context, ckconfig.Selection) (*configkit.Result[appConfiguration], error) {
|
||||
loads++
|
||||
return nil, errors.New("unexpected load")
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, args := range [][]string{{"version"}, {"config", "scopes"}, {"config", "explain"}, {"config", "show", "--help"}} {
|
||||
result := app.Execute(context.Background(), args, commandkit.Streams{Out: io.Discard, Err: io.Discard})
|
||||
if result.Kind != commandkit.OutcomeSuccess || loads != 0 {
|
||||
t.Fatalf("%v: %#v loads=%d", args, result, loads)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user