Add report artifact inspection commands

This commit is contained in:
2026-05-29 18:33:24 +00:00
parent 18fe82f441
commit 88aaae3661
8 changed files with 633 additions and 4 deletions

View File

@@ -23,6 +23,12 @@ Usage:
weatherreporter generate storm [--config PATH] [--units VALUE] [--tz NAME] [--out PATH] --start TIME --end TIME
weatherreporter run morning [--config PATH] [--units VALUE] [--tz NAME] [--out-dir PATH]
weatherreporter run evening [--config PATH] [--units VALUE] [--tz NAME] [--out-dir PATH]
weatherreporter inspect reports [--config PATH] [--limit N]
weatherreporter inspect metadata [--config PATH] RUN_ID
weatherreporter inspect briefing [--config PATH] RUN_ID
weatherreporter inspect data-package [--config PATH] RUN_ID
weatherreporter inspect prior [--config PATH] RUN_ID
weatherreporter inspect sources [--config PATH] RUN_ID
Options:
-h, --help Show this help message.
@@ -74,6 +80,8 @@ func (r Runner) Run(ctx context.Context, args []string, stdout io.Writer, stderr
}
}
return err
case "inspect":
return r.runInspect(ctx, args[1:], stdout)
default:
return fmt.Errorf("unknown command %q", args[0])
}
@@ -94,6 +102,107 @@ type generateOptions struct {
End string
}
type inspectOptions struct {
ConfigPath string
Limit int
RunID string
}
func (r Runner) runInspect(ctx context.Context, args []string, stdout io.Writer) error {
if len(args) == 0 {
return fmt.Errorf("inspect requires a command")
}
command := args[0]
switch command {
case "reports":
opts, err := parseInspectReportsFlags(args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
records, err := app.InspectReports(ctx, app.InspectReportsRequest{Config: cfg, Limit: opts.Limit})
if err != nil {
return err
}
return writeJSON(stdout, records)
case "metadata":
opts, err := parseInspectRunFlags(command, args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
metadata, err := app.InspectMetadata(ctx, app.InspectRunRequest{Config: cfg, RunID: opts.RunID})
if err != nil {
return err
}
return writeJSON(stdout, metadata)
case "briefing":
opts, err := parseInspectRunFlags(command, args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
pkg, err := app.InspectBriefing(ctx, app.InspectRunRequest{Config: cfg, RunID: opts.RunID})
if err != nil {
return err
}
return writeJSON(stdout, pkg)
case "data-package":
opts, err := parseInspectRunFlags(command, args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
pkg, err := app.InspectDataPackage(ctx, app.InspectRunRequest{Config: cfg, RunID: opts.RunID})
if err != nil {
return err
}
return writeJSON(stdout, pkg)
case "prior":
opts, err := parseInspectRunFlags(command, args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
prior, err := app.InspectPriorSnapshot(ctx, app.InspectRunRequest{Config: cfg, RunID: opts.RunID})
if err != nil {
return err
}
return writeJSON(stdout, prior)
case "sources":
opts, err := parseInspectRunFlags(command, args[1:])
if err != nil {
return err
}
cfg, err := config.Load(config.LoadOptions{Path: opts.ConfigPath})
if err != nil {
return err
}
sources, err := app.InspectSources(ctx, app.InspectRunRequest{Config: cfg, RunID: opts.RunID})
if err != nil {
return err
}
return writeJSON(stdout, sources)
default:
return fmt.Errorf("unknown inspect command %q", command)
}
}
func (r Runner) resolveGenerate(args []string) (app.GenerateRequest, error) {
if r.Clock == nil {
r.Clock = timeutil.SystemClock{}
@@ -230,12 +339,51 @@ func parseRunFlags(args []string) (commonOptions, error) {
return opts, nil
}
func parseInspectReportsFlags(args []string) (inspectOptions, error) {
fs := flag.NewFlagSet("inspect reports", flag.ContinueOnError)
fs.SetOutput(io.Discard)
opts := inspectOptions{Limit: 20}
fs.StringVar(&opts.ConfigPath, "config", "", "configuration file path")
fs.IntVar(&opts.Limit, "limit", 20, "maximum reports to list")
if err := fs.Parse(args); err != nil {
return inspectOptions{}, err
}
if fs.NArg() > 0 {
return inspectOptions{}, fmt.Errorf("unexpected argument %q", fs.Arg(0))
}
if opts.Limit < 0 {
return inspectOptions{}, fmt.Errorf("limit must be zero or greater")
}
return opts, nil
}
func parseInspectRunFlags(command string, args []string) (inspectOptions, error) {
fs := flag.NewFlagSet("inspect "+command, flag.ContinueOnError)
fs.SetOutput(io.Discard)
opts := inspectOptions{}
fs.StringVar(&opts.ConfigPath, "config", "", "configuration file path")
if err := fs.Parse(args); err != nil {
return inspectOptions{}, err
}
if fs.NArg() != 1 {
return inspectOptions{}, fmt.Errorf("inspect %s requires a run id", command)
}
opts.RunID = fs.Arg(0)
return opts, nil
}
func writeRunSummary(stdout io.Writer, result *app.BatchResult) error {
encoder := json.NewEncoder(stdout)
encoder.SetIndent("", " ")
return encoder.Encode(result)
}
func writeJSON(stdout io.Writer, value any) error {
encoder := json.NewEncoder(stdout)
encoder.SetIndent("", " ")
return encoder.Encode(value)
}
func writeRunLogs(stderr io.Writer, result *app.BatchResult) {
if stderr == nil || result == nil {
return