Skip to content

Commit cfbe0dc

Browse files
authored
Replace raw fmt.Fprintf output in outcomes_history.go with console package (#39248)
1 parent 7bf71f4 commit cfbe0dc

2 files changed

Lines changed: 85 additions & 9 deletions

File tree

pkg/cli/outcomes_history.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strconv"
1010
"strings"
1111

12+
"github.com/github/gh-aw/pkg/console"
1213
"github.com/github/gh-aw/pkg/constants"
1314
ghmapping "github.com/github/gh-aw/pkg/github"
1415
"github.com/github/gh-aw/pkg/workflow"
@@ -162,7 +163,7 @@ func RunOutcomesHistory(config OutcomesHistoryConfig) error {
162163
return nil
163164
}
164165

165-
fmt.Fprintf(os.Stderr, "Objective history for %s (limit %d)\n", repo, config.Limit)
166+
fmt.Fprintln(os.Stderr, console.FormatSectionHeader(fmt.Sprintf("Objective history for %s (limit %d)", repo, config.Limit)))
166167
if data.Issues != nil {
167168
renderHistoricalObjectiveReport(*data.Issues)
168169
}
@@ -295,22 +296,41 @@ func buildHistoricalObjectiveReport(source string, items []historicalGitHubItem,
295296
}
296297

297298
func renderHistoricalObjectiveReport(report historicalObjectiveReport) {
298-
fmt.Fprintf(os.Stderr, "\n%s\n", strings.ToUpper(report.Source))
299-
fmt.Fprintf(os.Stderr, " Sample size: %d\n", report.SampleSize)
300-
fmt.Fprintf(os.Stderr, " Scored items: %d\n", report.ScoredItems)
301-
fmt.Fprintf(os.Stderr, " Total objective value: %d\n", report.TotalObjectiveValue)
299+
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatSectionHeader(strings.ToUpper(report.Source)))
300+
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Sample size: %d", report.SampleSize)))
301+
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Scored items: %d", report.ScoredItems)))
302+
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Total objective value: %d", report.TotalObjectiveValue)))
302303

303304
if len(report.ObjectiveBuckets) > 0 {
304-
fmt.Fprintln(os.Stderr, " Top objective buckets:")
305+
bucketRows := make([][]string, 0, min(len(report.ObjectiveBuckets), 8))
305306
for _, bucket := range report.ObjectiveBuckets[:min(len(report.ObjectiveBuckets), 8)] {
306-
fmt.Fprintf(os.Stderr, " %-22s %3d x %3d = %4d\n", bucket.Label, bucket.Count, bucket.MappedValue, bucket.ContributedValue)
307+
bucketRows = append(bucketRows, []string{
308+
bucket.Label,
309+
strconv.Itoa(bucket.Count),
310+
strconv.Itoa(bucket.MappedValue),
311+
strconv.Itoa(bucket.ContributedValue),
312+
})
307313
}
314+
fmt.Fprint(os.Stderr, console.RenderTable(console.TableConfig{
315+
Title: "Top objective buckets",
316+
Headers: []string{"Bucket", "Count", "Mapped Value", "Contributed Value"},
317+
Rows: bucketRows,
318+
}))
308319
}
309320

310321
if len(report.RepresentativeItems) > 0 {
311-
fmt.Fprintln(os.Stderr, " Representative items:")
322+
itemRows := make([][]string, 0, min(len(report.RepresentativeItems), 5))
312323
for _, item := range report.RepresentativeItems[:min(len(report.RepresentativeItems), 5)] {
313-
fmt.Fprintf(os.Stderr, " #%d %-3d %s\n", item.Number, item.ObjectiveValue, item.Title)
324+
itemRows = append(itemRows, []string{
325+
fmt.Sprintf("#%d", item.Number),
326+
strconv.Itoa(item.ObjectiveValue),
327+
item.Title,
328+
})
314329
}
330+
fmt.Fprint(os.Stderr, console.RenderTable(console.TableConfig{
331+
Title: "Representative items",
332+
Headers: []string{"Number", "Value", "Title"},
333+
Rows: itemRows,
334+
}))
315335
}
316336
}

pkg/cli/outcomes_history_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
ghmapping "github.com/github/gh-aw/pkg/github"
12+
"github.com/github/gh-aw/pkg/testutil"
1213
"github.com/spf13/cobra"
1314
"github.com/stretchr/testify/assert"
1415
"github.com/stretchr/testify/require"
@@ -121,6 +122,61 @@ func TestRunOutcomesHistory_JSON(t *testing.T) {
121122
assert.Equal(t, 65, data.PRs.TotalObjectiveValue)
122123
}
123124

125+
func TestRunOutcomesHistory_PrettyOutput(t *testing.T) {
126+
oldRunGH := outcomesHistoryRunGH
127+
defer func() { outcomesHistoryRunGH = oldRunGH }()
128+
129+
outcomesHistoryRunGH = func(spinnerMessage string, args ...string) ([]byte, error) {
130+
if len(args) >= 2 && args[0] == "issue" && args[1] == "list" {
131+
return []byte(`[
132+
{"number":101,"title":"Automation issue","url":"https://example.com/issues/101","closedAt":"2026-06-08T00:00:00Z","labels":[{"name":"automation"}]}
133+
]`), nil
134+
}
135+
if len(args) >= 2 && args[0] == "pr" && args[1] == "list" {
136+
return []byte(`[
137+
{"number":202,"title":"Testing PR","url":"https://example.com/pull/202","mergedAt":"2026-06-08T00:00:00Z","labels":[{"name":"testing"}]}
138+
]`), nil
139+
}
140+
return nil, assert.AnError
141+
}
142+
143+
require.NoError(t, os.Setenv("OBJECTIVE_MAPPING_JSON", `{"label_to_value":{"automation":40,"testing":65},"multi_label_logic":"max"}`))
144+
t.Cleanup(func() { os.Unsetenv("OBJECTIVE_MAPPING_JSON") })
145+
146+
stderr := testutil.CaptureStderr(t, func() {
147+
err := RunOutcomesHistory(OutcomesHistoryConfig{RepoOverride: "owner/repo", JSONOutput: false, Limit: 10, Source: historySourceAll})
148+
require.NoError(t, err)
149+
})
150+
151+
// Top-level section header.
152+
assert.Contains(t, stderr, "Objective history for owner/repo (limit 10)")
153+
154+
// Issues section header.
155+
assert.Contains(t, stderr, "ISSUES")
156+
157+
// Issues stats.
158+
assert.Contains(t, stderr, "Sample size: 1")
159+
assert.Contains(t, stderr, "Scored items: 1")
160+
assert.Contains(t, stderr, "Total objective value: 40")
161+
162+
// Issues bucket table title and headers.
163+
assert.Contains(t, stderr, "Top objective buckets")
164+
assert.Contains(t, stderr, "Bucket")
165+
assert.Contains(t, stderr, "Mapped Value")
166+
assert.Contains(t, stderr, "Contributed Value")
167+
168+
// Issues representative items table title and headers.
169+
assert.Contains(t, stderr, "Representative items")
170+
assert.Contains(t, stderr, "Number")
171+
assert.Contains(t, stderr, "Title")
172+
173+
// PRs section header.
174+
assert.Contains(t, stderr, "PRS")
175+
176+
// PRs stats.
177+
assert.Contains(t, stderr, "Total objective value: 65")
178+
}
179+
124180
func TestNewOutcomesHistorySubcommand_InheritsGlobalVerboseFlag(t *testing.T) {
125181
cmd := NewOutcomesHistorySubcommand()
126182
require.NotNil(t, cmd)

0 commit comments

Comments
 (0)