Add shared report format flag

This commit is contained in:
2026-11-07 03:45:12 +00:00
parent 3a6c66f550
commit 924692b541
18 changed files with 206 additions and 101 deletions

View File

@@ -4,10 +4,10 @@ import (
"fmt"
"io"
"runtime/debug"
"text/template"
internalcobra "go.maximumdirect.net/commandkit/internal/cobra"
commandmeta "go.maximumdirect.net/commandkit/internal/commandmeta"
yaml "go.yaml.in/yaml/v4"
)
const commandKitModulePath = "go.maximumdirect.net/commandkit"
@@ -17,16 +17,17 @@ type helpInput struct {
}
type versionInput struct {
Scope string
Format string
Scope string
}
type versionDocument struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Revision string `yaml:"revision"`
Name string `json:"name"`
Version string `json:"version"`
Revision string `json:"revision"`
}
var versionTextTemplate = template.Must(ParseTextTemplate("version", "{{.Name}} {{.Version}}{{if .Revision}} ({{.Revision}}){{end}}\n", nil))
func (a *App) builtinCommands() []Declaration {
help := captureCommand(CommandSpec[helpInput]{
Name: "help",
@@ -39,14 +40,12 @@ func (a *App) builtinCommands() []Declaration {
return current.renderHelpTargets(input.Targets.Value)
})
scopeDefault := "app"
formatDefault := "text"
version := NewCommand(CommandSpec[versionInput]{
Name: "version",
Summary: "Show application or CommandKit version.",
Description: "Report identity and build metadata without loading application configuration.",
Flags: []Flag[versionInput]{
ValueFlag(FlagMeta{Name: "scope", Usage: "version subject", Completion: CompleteChoices(CompletionChoice{Value: "app"}, CompletionChoice{Value: "commandkit"})}, &scopeDefault, parseVersionScope, func(input *versionInput, value Supplied[string]) { input.Scope = value.Value }),
ValueFlag(FlagMeta{Name: "format", Usage: "output format", Completion: CompleteChoices(CompletionChoice{Value: "text"}, CompletionChoice{Value: "yaml"})}, &formatDefault, parseVersionFormat, func(input *versionInput, value Supplied[string]) { input.Format = value.Value }),
},
Run: func(invocation Invocation, input versionInput) Outcome {
identity := a.identity
@@ -56,7 +55,7 @@ func (a *App) builtinCommands() []Declaration {
if identity.Version == "" {
identity.Version = "dev"
}
return renderVersionOutcome(identity, input.Format, invocation.Reporter())
return renderVersionOutcome(identity, invocation.Reporter())
},
})
return []Declaration{help, version}
@@ -69,13 +68,6 @@ func parseVersionScope(value string) (string, error) {
return value, nil
}
func parseVersionFormat(value string) (string, error) {
if value != "text" && value != "yaml" {
return "", fmt.Errorf("format must be text or yaml, got %q", value)
}
return value, nil
}
func (a *App) renderHelpViewOutcomeWithSession(view commandmeta.HelpView, reporter *Reporter, session *internalcobra.Session) Outcome {
content, failure := session.RenderHelpView(view)
if failure != nil {
@@ -91,36 +83,14 @@ func (a *App) renderHelpViewOutcomeWithSession(view commandmeta.HelpView, report
return Success()
}
func renderVersionOutcome(identity Identity, format string, reporter *Reporter) Outcome {
func renderVersionOutcome(identity Identity, reporter *Reporter) Outcome {
if identity.Version == "" {
identity.Version = "dev"
}
switch format {
case "text":
line := identity.Name + " " + identity.Version
if identity.Revision != "" {
line += " (" + identity.Revision + ")"
}
_ = reporter.RenderOutput(func(w io.Writer) error {
_, err := io.WriteString(w, line+"\n")
return err
})
case "yaml":
_ = reporter.RenderOutput(func(w io.Writer) error {
return encodeYAML(w, versionDocument{Name: identity.Name, Version: identity.Version, Revision: identity.Revision})
})
default:
return Usage(fmt.Sprintf("unsupported version format %q", format))
}
_ = reporter.Report(Report{Value: versionDocument{Name: identity.Name, Version: identity.Version, Revision: identity.Revision}, TextTemplate: versionTextTemplate})
return Success()
}
func encodeYAML(writer io.Writer, document any) error {
encoder := yaml.NewEncoder(writer)
encoder.SetIndent(2)
return encoder.Encode(document)
}
func readBuildInfo() *debug.BuildInfo {
info, ok := debug.ReadBuildInfo()
if !ok {