Wire CLI action summaries
This commit is contained in:
@@ -50,7 +50,6 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer)
|
||||
}
|
||||
|
||||
func (r Runner) Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) error {
|
||||
_ = stderr
|
||||
if r.Clock == nil {
|
||||
r.Clock = timeutil.SystemClock{}
|
||||
}
|
||||
@@ -61,24 +60,32 @@ func (r Runner) Run(ctx context.Context, args []string, stdout io.Writer, stderr
|
||||
|
||||
switch args[0] {
|
||||
case "generate":
|
||||
req, err := r.resolveGenerate(args[1:])
|
||||
req, opts, err := r.resolveGenerateAction(args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return app.Generate(ctx, req)
|
||||
result, err := app.GenerateDetailed(ctx, req)
|
||||
if result != nil {
|
||||
summary := newGenerateSummary(result, err)
|
||||
if encodeErr := writeActionResult(stdout, stderr, summary, outputOptions{Quiet: opts.Quiet}, nil); encodeErr != nil {
|
||||
return encodeErr
|
||||
}
|
||||
}
|
||||
return err
|
||||
case "run":
|
||||
req, err := r.resolveRun(args[1:])
|
||||
req, opts, err := r.resolveRunAction(args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := app.RunBatchDetailed(ctx, req)
|
||||
if result != nil {
|
||||
if encodeErr := writeActionResult(stdout, stderr, result, outputOptions{}, func(w io.Writer) {
|
||||
summary := newBatchSummary(result)
|
||||
if encodeErr := writeActionResult(stdout, stderr, summary, outputOptions{Quiet: opts.Quiet}, func(w io.Writer) {
|
||||
writeBatchStatus(w, result)
|
||||
}); encodeErr != nil {
|
||||
return encodeErr
|
||||
}
|
||||
if result.Failed > 0 {
|
||||
if summary.Status == summaryStatusFailed {
|
||||
return app.BatchError{Result: result}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +103,7 @@ type commonOptions struct {
|
||||
Timezone string
|
||||
Output string
|
||||
OutputDir string
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
type generateOptions struct {
|
||||
@@ -181,20 +189,25 @@ func runInspectRunCommand(ctx context.Context, stdout io.Writer, command inspect
|
||||
}
|
||||
|
||||
func (r Runner) resolveGenerate(args []string) (app.GenerateRequest, error) {
|
||||
req, _, err := r.resolveGenerateAction(args)
|
||||
return req, err
|
||||
}
|
||||
|
||||
func (r Runner) resolveGenerateAction(args []string) (app.GenerateRequest, commonOptions, error) {
|
||||
if r.Clock == nil {
|
||||
r.Clock = timeutil.SystemClock{}
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return app.GenerateRequest{}, fmt.Errorf("generate requires a report name")
|
||||
return app.GenerateRequest{}, commonOptions{}, fmt.Errorf("generate requires a report name")
|
||||
}
|
||||
if _, err := report.IDForCommandName(args[0]); err != nil {
|
||||
return app.GenerateRequest{}, fmt.Errorf("unknown generate report %q", args[0])
|
||||
return app.GenerateRequest{}, commonOptions{}, fmt.Errorf("unknown generate report %q", args[0])
|
||||
}
|
||||
reportKind := app.ReportKind(args[0])
|
||||
|
||||
opts, err := parseGenerateFlags(reportKind, args[1:])
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
cfg, err := config.Load(config.LoadOptions{
|
||||
Path: opts.ConfigPath,
|
||||
@@ -202,11 +215,11 @@ func (r Runner) resolveGenerate(args []string) (app.GenerateRequest, error) {
|
||||
Timezone: opts.Timezone,
|
||||
})
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
location, err := timeutil.LoadLocation(cfg.WeatherAPI.Timezone)
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
|
||||
req := app.GenerateRequest{
|
||||
@@ -219,11 +232,11 @@ func (r Runner) resolveGenerate(args []string) (app.GenerateRequest, error) {
|
||||
switch reportKind {
|
||||
case app.ReportDaily:
|
||||
if opts.Date == "" {
|
||||
return app.GenerateRequest{}, fmt.Errorf("generate daily requires --date YYYY-MM-DD")
|
||||
return app.GenerateRequest{}, commonOptions{}, fmt.Errorf("generate daily requires --date YYYY-MM-DD")
|
||||
}
|
||||
req.Date, err = timeutil.ParseLocalDate(opts.Date, location)
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
case app.ReportToday:
|
||||
if opts.Date == "" {
|
||||
@@ -231,41 +244,46 @@ func (r Runner) resolveGenerate(args []string) (app.GenerateRequest, error) {
|
||||
} else {
|
||||
req.Date, err = timeutil.ParseLocalDate(opts.Date, location)
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
}
|
||||
case app.ReportStorm:
|
||||
if opts.Start == "" {
|
||||
return app.GenerateRequest{}, fmt.Errorf("generate storm requires --start")
|
||||
return app.GenerateRequest{}, commonOptions{}, fmt.Errorf("generate storm requires --start")
|
||||
}
|
||||
if opts.End == "" {
|
||||
return app.GenerateRequest{}, fmt.Errorf("generate storm requires --end")
|
||||
return app.GenerateRequest{}, commonOptions{}, fmt.Errorf("generate storm requires --end")
|
||||
}
|
||||
period, err := report.ParseStormPeriod(opts.Start, opts.End, location)
|
||||
if err != nil {
|
||||
return app.GenerateRequest{}, err
|
||||
return app.GenerateRequest{}, commonOptions{}, err
|
||||
}
|
||||
req.StormStart = period.Start
|
||||
req.StormEnd = period.End
|
||||
}
|
||||
|
||||
return req, nil
|
||||
return req, opts.commonOptions, nil
|
||||
}
|
||||
|
||||
func (r Runner) resolveRun(args []string) (app.BatchRequest, error) {
|
||||
req, _, err := r.resolveRunAction(args)
|
||||
return req, err
|
||||
}
|
||||
|
||||
func (r Runner) resolveRunAction(args []string) (app.BatchRequest, commonOptions, error) {
|
||||
if r.Clock == nil {
|
||||
r.Clock = timeutil.SystemClock{}
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return app.BatchRequest{}, fmt.Errorf("run requires a batch name")
|
||||
return app.BatchRequest{}, commonOptions{}, fmt.Errorf("run requires a batch name")
|
||||
}
|
||||
if _, err := report.BatchForCommandName(args[0]); err != nil {
|
||||
return app.BatchRequest{}, fmt.Errorf("unknown run batch %q", args[0])
|
||||
return app.BatchRequest{}, commonOptions{}, fmt.Errorf("unknown run batch %q", args[0])
|
||||
}
|
||||
batch := app.BatchKind(args[0])
|
||||
opts, err := parseRunFlags(args[1:])
|
||||
if err != nil {
|
||||
return app.BatchRequest{}, err
|
||||
return app.BatchRequest{}, commonOptions{}, err
|
||||
}
|
||||
cfg, err := config.Load(config.LoadOptions{
|
||||
Path: opts.ConfigPath,
|
||||
@@ -273,9 +291,9 @@ func (r Runner) resolveRun(args []string) (app.BatchRequest, error) {
|
||||
Timezone: opts.Timezone,
|
||||
})
|
||||
if err != nil {
|
||||
return app.BatchRequest{}, err
|
||||
return app.BatchRequest{}, commonOptions{}, err
|
||||
}
|
||||
return app.BatchRequest{Config: cfg, Batch: batch, Now: r.Clock.Now(), OutputDir: opts.OutputDir}, nil
|
||||
return app.BatchRequest{Config: cfg, Batch: batch, Now: r.Clock.Now(), OutputDir: opts.OutputDir}, opts, nil
|
||||
}
|
||||
|
||||
func resolveRun(args []string) (app.BatchRequest, error) {
|
||||
@@ -287,6 +305,7 @@ func parseGenerateFlags(report app.ReportKind, args []string) (generateOptions,
|
||||
fs.SetOutput(io.Discard)
|
||||
opts := generateOptions{}
|
||||
addCommonFlags(fs, &opts.commonOptions, true)
|
||||
fs.BoolVar(&opts.Quiet, "quiet", false, "suppress successful action output")
|
||||
if report == app.ReportDaily || report == app.ReportToday {
|
||||
fs.StringVar(&opts.Date, "date", "", "report date in YYYY-MM-DD")
|
||||
}
|
||||
@@ -309,6 +328,7 @@ func parseRunFlags(args []string) (commonOptions, error) {
|
||||
opts := commonOptions{}
|
||||
addCommonFlags(fs, &opts, false)
|
||||
fs.StringVar(&opts.OutputDir, "out-dir", "", "extra Markdown report copy directory")
|
||||
fs.BoolVar(&opts.Quiet, "quiet", false, "suppress successful action output")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return commonOptions{}, err
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestRunGenerateThreeDayWritesMarkdownReport(t *testing.T) {
|
||||
outPath := fixture.path("three-day.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
output, err := runTestCommand(t, runner,
|
||||
"generate", "three-day",
|
||||
"--config", fixture.configPath,
|
||||
"--out", outPath,
|
||||
@@ -143,6 +143,20 @@ func TestRunGenerateThreeDayWritesMarkdownReport(t *testing.T) {
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "three-day", "2026-05-29", "data_package.*.yaml")
|
||||
assertFileContains(t, dataPackagePath, "id: three_day")
|
||||
assertFileContains(t, dataPackagePath, "derived_daypart_summaries:")
|
||||
|
||||
summary := decodeGenerateSummary(t, output.stdout)
|
||||
if summary.Command != "generate" || summary.Status != "succeeded" || summary.ReportID != report.ThreeDay {
|
||||
t.Fatalf("generate summary = %#v, want successful 3-day summary", summary)
|
||||
}
|
||||
if summary.ReportPath == "" || summary.MetadataPath == "" || summary.DataPackagePath == "" || summary.PreflightPath == "" {
|
||||
t.Fatalf("summary paths = %#v, want managed artifact paths", summary)
|
||||
}
|
||||
if summary.OutputPath != outPath {
|
||||
t.Fatalf("summary OutputPath = %q, want %q", summary.OutputPath, outPath)
|
||||
}
|
||||
if summary.GeneratedTextRawPath != "" || summary.GeneratedTextResultPath != "" || summary.GeneratedTextPath != "" || summary.RenderContextPath != "" {
|
||||
t.Fatalf("generated-text paths = %#v, want omitted for markdown report", summary)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunGenerateWeekendWritesMarkdownReport(t *testing.T) {
|
||||
@@ -197,9 +211,9 @@ func TestRunMorningReportsPartialFailureAndContinues(t *testing.T) {
|
||||
t.Fatalf("Run() error = %q, want aggregate failure", err.Error())
|
||||
}
|
||||
|
||||
var summary app.BatchResult
|
||||
if decodeErr := json.Unmarshal([]byte(output.stdout), &summary); decodeErr != nil {
|
||||
t.Fatalf("decode summary: %v\n%s", decodeErr, output.stdout)
|
||||
summary := decodeBatchSummary(t, output.stdout)
|
||||
if summary.Command != "run" || summary.Status != "failed" {
|
||||
t.Fatalf("summary command/status = %q/%q, want run/failed", summary.Command, summary.Status)
|
||||
}
|
||||
if summary.Total != 2 || summary.Succeeded != 1 || summary.Failed != 1 {
|
||||
t.Fatalf("summary total/succeeded/failed = %d/%d/%d, want 2/1/1", summary.Total, summary.Succeeded, summary.Failed)
|
||||
@@ -387,9 +401,9 @@ func TestRunEveningUsesOutputDirectoryAndSummary(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
var summary app.BatchResult
|
||||
if decodeErr := json.Unmarshal([]byte(output.stdout), &summary); decodeErr != nil {
|
||||
t.Fatalf("decode summary: %v\n%s", decodeErr, output.stdout)
|
||||
summary := decodeBatchSummary(t, output.stdout)
|
||||
if summary.Command != "run" || summary.Status != "succeeded" {
|
||||
t.Fatalf("summary command/status = %q/%q, want run/succeeded", summary.Command, summary.Status)
|
||||
}
|
||||
if summary.Total != 1 || summary.Failed != 0 {
|
||||
t.Fatalf("summary total/failed = %d/%d, want 1/0", summary.Total, summary.Failed)
|
||||
@@ -402,6 +416,24 @@ func TestRunEveningUsesOutputDirectoryAndSummary(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunQuietSuppressesSuccessfulOutput(t *testing.T) {
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
output, err := runTestCommand(t, runner,
|
||||
"run", "evening",
|
||||
"--config", fixture.configPath,
|
||||
"--quiet",
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
if output.stdout != "" || output.stderr != "" {
|
||||
t.Fatalf("stdout/stderr = %q/%q, want quiet success output", output.stdout, output.stderr)
|
||||
}
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "reports", "tomorrow", "2026-05-30", "report.*.md")
|
||||
}
|
||||
|
||||
func TestRunEveningReportsOmitsPerReportNotification(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
var uploadCount int
|
||||
@@ -437,9 +469,9 @@ func TestRunEveningReportsOmitsPerReportNotification(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
var summary app.BatchResult
|
||||
if decodeErr := json.Unmarshal(stdout.Bytes(), &summary); decodeErr != nil {
|
||||
t.Fatalf("decode summary: %v\n%s", decodeErr, stdout.String())
|
||||
summary := decodeBatchSummary(t, stdout.String())
|
||||
if summary.Command != "run" || summary.Status != "succeeded" {
|
||||
t.Fatalf("summary command/status = %q/%q, want run/succeeded", summary.Command, summary.Status)
|
||||
}
|
||||
if len(summary.Reports) != 1 {
|
||||
t.Fatalf("reports = %#v, want one report", summary.Reports)
|
||||
@@ -489,9 +521,9 @@ func TestRunEveningReportsDoesNotRequirePerReportDistributorToken(t *testing.T)
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
var summary app.BatchResult
|
||||
if decodeErr := json.Unmarshal(stdout.Bytes(), &summary); decodeErr != nil {
|
||||
t.Fatalf("decode summary: %v\n%s", decodeErr, stdout.String())
|
||||
summary := decodeBatchSummary(t, stdout.String())
|
||||
if summary.Command != "run" || summary.Status != "succeeded" {
|
||||
t.Fatalf("summary command/status = %q/%q, want run/succeeded", summary.Command, summary.Status)
|
||||
}
|
||||
if len(summary.Reports) != 1 {
|
||||
t.Fatalf("summary reports = %#v, want one report", summary.Reports)
|
||||
@@ -541,12 +573,12 @@ func TestRunGenerateDailyWritesMarkdownReport(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
report, err := os.ReadFile(outPath)
|
||||
reportData, err := os.ReadFile(outPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read report: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(report), "# Friday's Weather") {
|
||||
t.Fatalf("report output missing markdown:\n%s", string(report))
|
||||
if !strings.Contains(string(reportData), "# Friday's Weather") {
|
||||
t.Fatalf("report output missing markdown:\n%s", string(reportData))
|
||||
}
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-29", "data_package.*.yaml")
|
||||
data, err := os.ReadFile(dataPackagePath)
|
||||
@@ -598,7 +630,7 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
report, err := os.ReadFile(outPath)
|
||||
reportData, err := os.ReadFile(outPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read report: %v", err)
|
||||
}
|
||||
@@ -607,8 +639,8 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
"Today starts with showers before improving.",
|
||||
"Morning showers should taper as drier air arrives.",
|
||||
} {
|
||||
if !strings.Contains(string(report), want) {
|
||||
t.Fatalf("today report output missing %q:\n%s", want, string(report))
|
||||
if !strings.Contains(string(reportData), want) {
|
||||
t.Fatalf("today report output missing %q:\n%s", want, string(reportData))
|
||||
}
|
||||
}
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-29", "data_package.*.yaml")
|
||||
@@ -630,6 +662,20 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
assertFileContains(t, validatedGeneratedTextPath, `"summary":"Today starts with showers before improving."`)
|
||||
assertFileContains(t, renderContextPath, `"Title": "Today's Weather"`)
|
||||
assertFileContains(t, managedReportPath, "# Today's Weather")
|
||||
|
||||
summary := decodeGenerateSummary(t, stdout.String())
|
||||
if summary.Command != "generate" || summary.Status != "succeeded" || summary.ReportID != report.Today {
|
||||
t.Fatalf("generate summary = %#v, want successful Today summary", summary)
|
||||
}
|
||||
if summary.RunID == "" || summary.ReportPath == "" || summary.MetadataPath == "" || summary.DataPackagePath == "" || summary.PreflightPath == "" {
|
||||
t.Fatalf("summary identity/paths = %#v, want run id and managed artifact paths", summary)
|
||||
}
|
||||
if summary.GeneratedTextRawPath == "" || summary.GeneratedTextResultPath == "" || summary.GeneratedTextPath == "" || summary.RenderContextPath == "" {
|
||||
t.Fatalf("generated-text paths = %#v, want generated-text artifact paths", summary)
|
||||
}
|
||||
if summary.OutputPath != outPath {
|
||||
t.Fatalf("summary OutputPath = %q, want %q", summary.OutputPath, outPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
@@ -647,7 +693,7 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
report, err := os.ReadFile(outPath)
|
||||
reportData, err := os.ReadFile(outPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read report: %v", err)
|
||||
}
|
||||
@@ -657,8 +703,8 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
"A cold front is moving into the region.",
|
||||
"A front will keep the region unsettled.",
|
||||
} {
|
||||
if !strings.Contains(string(report), want) {
|
||||
t.Fatalf("report output missing %q:\n%s", want, string(report))
|
||||
if !strings.Contains(string(reportData), want) {
|
||||
t.Fatalf("report output missing %q:\n%s", want, string(reportData))
|
||||
}
|
||||
}
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "hourly", "2026-05-29", "data_package.*.yaml")
|
||||
@@ -685,6 +731,76 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
assertFileContains(t, managedReportPath, "# Hourly Report")
|
||||
}
|
||||
|
||||
func TestRunGenerateQuietSuppressesSuccessfulOutput(t *testing.T) {
|
||||
fixture := newCLIFixture(t, writeStructuredOutputScriptorium)
|
||||
outPath := fixture.path("today.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
output, err := runTestCommand(t, runner,
|
||||
"generate", "today",
|
||||
"--config", fixture.configPath,
|
||||
"--date", "2026-05-29",
|
||||
"--out", outPath,
|
||||
"--quiet",
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
if output.stdout != "" || output.stderr != "" {
|
||||
t.Fatalf("stdout/stderr = %q/%q, want quiet success output", output.stdout, output.stderr)
|
||||
}
|
||||
assertFileContains(t, outPath, "# Today's Weather")
|
||||
}
|
||||
|
||||
func TestRunGeneratePreRunErrorEmitsNoJSON(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
err := runner.Run(context.Background(), []string{"generate", "daily"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want required date error")
|
||||
}
|
||||
if stdout.Len() != 0 {
|
||||
t.Fatalf("stdout = %q, want no partial JSON", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunGenerateNotificationFailureEmitsFailureSummary(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
distributorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("unexpected distributor request with unset token: %s", r.URL.Path)
|
||||
}))
|
||||
t.Cleanup(distributorServer.Close)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfigWithDistributor(t, server, scriptoriumPath, workspaceRoot, distributorServer.URL)
|
||||
t.Setenv("CLI_DISTRIBUTOR_TOKEN", "")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
output, err := runTestCommand(t, runner,
|
||||
"generate", "three-day",
|
||||
"--config", configPath,
|
||||
)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want notification failure")
|
||||
}
|
||||
summary := decodeGenerateSummary(t, output.stdout)
|
||||
if summary.Command != "generate" || summary.Status != "failed" || summary.Error == "" {
|
||||
t.Fatalf("summary = %#v, want failed generate summary", summary)
|
||||
}
|
||||
if !strings.Contains(summary.Error, "token environment variable") {
|
||||
t.Fatalf("summary error = %q, want token environment context", summary.Error)
|
||||
}
|
||||
if summary.ReportPath == "" || summary.MetadataPath == "" || summary.NotificationPath == "" {
|
||||
t.Fatalf("summary paths = %#v, want inspectable report, metadata, and notification paths", summary)
|
||||
}
|
||||
if strings.Contains(output.stdout, "CLI_DISTRIBUTOR_TOKEN_VALUE") || strings.Contains(output.stderr, "CLI_DISTRIBUTOR_TOKEN_VALUE") {
|
||||
t.Fatalf("output contains distributor token value\nstdout=%s\nstderr=%s", output.stdout, output.stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunInspectTodayArtifacts(t *testing.T) {
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
@@ -791,6 +907,22 @@ func TestRunInspectMissingMetadata(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunInspectRejectsQuiet(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
configPath := writeWorkspaceConfig(t, filepath.Join(tempDir, "workspace"))
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
err := runner.Run(context.Background(), []string{"inspect", "reports", "--config", configPath, "--quiet"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatal("Run(inspect reports --quiet) error = nil, want unexpected flag error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "flag provided but not defined") {
|
||||
t.Fatalf("error = %q, want unexpected quiet flag", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunInspectRunCommandsParseRunIDAndConfig(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
configPath := writeWorkspaceConfig(t, filepath.Join(tempDir, "workspace"))
|
||||
@@ -1179,6 +1311,24 @@ func runTestCommand(t *testing.T, runner Runner, args ...string) (commandOutput,
|
||||
}, err
|
||||
}
|
||||
|
||||
func decodeGenerateSummary(t *testing.T, text string) generateSummary {
|
||||
t.Helper()
|
||||
var summary generateSummary
|
||||
if err := json.Unmarshal([]byte(text), &summary); err != nil {
|
||||
t.Fatalf("decode generate summary: %v\n%s", err, text)
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func decodeBatchSummary(t *testing.T, text string) batchSummary {
|
||||
t.Helper()
|
||||
var summary batchSummary
|
||||
if err := json.Unmarshal([]byte(text), &summary); err != nil {
|
||||
t.Fatalf("decode batch summary: %v\n%s", err, text)
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func dailyServer(t *testing.T) *httptest.Server {
|
||||
t.Helper()
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user