Port native configuration reports

This commit is contained in:
2026-10-11 01:39:23 +00:00
parent 809a36bc46
commit c0f3a21fc7
12 changed files with 671 additions and 288 deletions

View File

@@ -3,24 +3,13 @@ package ckconfig
import (
"bytes"
"fmt"
"io"
"strconv"
)
func newConfigSourcesCommand[C any](prepared *preparedConfigSuite[C]) (Command, error) {
spec := CommandSpec[configInput[C]]{
Name: string(ConfigSources),
Summary: "List configuration sources used by a scope.",
Flags: configInputFlags(prepared.suite, "text"),
CheckInput: func(input configInput[C]) error {
_, err := preflightConfig(prepared, input, ConfigSources)
return err
},
Run: func(invocation Invocation, input configInput[C]) Outcome {
return runConfigSources(invocation, prepared, input)
},
}
return NewCommand(spec)
}
commandkit "gitea.maximumdirect.net/eric/CommandKit"
configkit "gitea.maximumdirect.net/eric/ConfigKit"
"go.yaml.in/yaml/v4"
)
type sourceReport struct {
Scope string `yaml:"scope"`
@@ -43,35 +32,30 @@ type locationDTO struct {
Column int `yaml:"column"`
}
func runConfigSources[C any](invocation Invocation, prepared *preparedConfigSuite[C], input configInput[C]) Outcome {
func runConfigSources[I, S any](invocation commandkit.Invocation, plan *configOperationPlan[I, S], state S) commandkit.Outcome {
selected := plan.scopes[0]
name := selected.scope.scope.Name
if err := invocation.Context.Err(); err != nil {
return Failure(err)
return configOperationFailure(err, nil, false)
}
scopeNames, err := selectConfigScopes(prepared, input, ConfigSources)
if err != nil {
return Failure(err)
if selected.scope.scope.Acquire == nil {
return configOperationFailure(fmt.Errorf("configuration scope %q has no acquisition callback", name), nil, false)
}
contexts := contextsForScopes(prepared, input, scopeNames)
name := scopeNames[0]
scope, ok := findConfigScope(prepared, name)
if !ok || scope.Acquire == nil {
return sourceReportFailure(fmt.Errorf("configuration scope %q has no acquisition callback", name), nil, false)
}
if err := invocation.Context.Err(); err != nil {
return sourceReportFailure(err, nil, false)
}
acquired, acquireErr := scope.Acquire(invocation.Context, ConfigRequest{Operation: ConfigSources, Selection: input.Selection}, contexts[name])
diagnostics := append([]Diagnostic(nil), acquired.Diagnostics...)
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{
Operation: Sources,
Selection: plan.selection,
}, selected.input, state)
diagnostics := append([]commandkit.Diagnostic(nil), acquired.Diagnostics...)
if acquireErr != nil {
return sourceReportFailure(acquireErr, diagnostics, false)
return configOperationFailure(acquireErr, diagnostics, false)
}
if err := invocation.Context.Err(); err != nil {
return sourceReportFailure(err, diagnostics, false)
return configOperationFailure(err, diagnostics, false)
}
if acquired.Value.Sources == nil {
return configOperationFailure(fmt.Errorf("configuration scope %q did not provide a source reader", name), diagnostics, false)
}
if acquired.Value.Sources == nil {
return sourceReportFailure(fmt.Errorf("configuration scope %q did not provide a source reader", name), diagnostics, false)
}
sources := acquired.Value.Sources.Sources()
document := sourceReport{Scope: name, Sources: make([]sourceDTO, 0, len(sources))}
for _, source := range sources {
@@ -88,24 +72,21 @@ func runConfigSources[C any](invocation Invocation, prepared *preparedConfigSuit
}
document.Sources = append(document.Sources, item)
}
var report bytes.Buffer
if input.Format == "yaml" {
if plan.format == "yaml" {
if err := encodeYAML(&report, document); err != nil {
return sourceReportFailure(err, diagnostics, false)
return configOperationFailure(err, diagnostics, false)
}
} else {
writeSourceReportText(&report, document)
}
if err := invocation.Context.Err(); err != nil {
return sourceReportFailure(err, diagnostics, false)
return configOperationFailure(err, diagnostics, false)
}
if err := writeReport(invocation.Streams.Out, report.Bytes()); err != nil {
outcome := sourceReportFailure(err, diagnostics, true)
outcome.DeliveryError = err
return outcome
if err := writeConfigReport(invocation.Streams.Out, report.Bytes()); err != nil {
return configDeliveryFailure(err, diagnostics, true)
}
outcome := Success()
outcome := commandkit.Success()
outcome.Diagnostics = diagnostics
return outcome
}
@@ -133,9 +114,16 @@ func writeSourceReportText(writer *bytes.Buffer, document sourceReport) {
}
}
func sourceReportFailure(cause error, diagnostics []Diagnostic, reportStarted bool) Outcome {
outcome := Failure(cause)
outcome.Diagnostics = diagnostics
outcome.ReportIncomplete = reportStarted
return outcome
func encodeYAML(writer io.Writer, document any) error {
encoder := yaml.NewEncoder(writer)
encoder.SetIndent(2)
return encoder.Encode(document)
}
func locationReports(locations []configkit.Location) []locationDTO {
report := make([]locationDTO, 0, len(locations))
for _, location := range locations {
report = append(report, locationDTO{SourceID: location.SourceID, Line: location.Line, Column: location.Column})
}
return report
}