From 837fac0da3084207be1a2578a38b4567d9b7f38b Mon Sep 17 00:00:00 2001 From: satotake Date: Wed, 17 Aug 2022 01:23:53 +0900 Subject: [PATCH 1/2] Add age column to `pr list` --- pkg/cmd/pr/list/fixtures/prList.json | 3 +++ pkg/cmd/pr/list/list.go | 10 ++++++++++ pkg/cmd/pr/list/list_test.go | 25 +++++++++++++++++-------- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/pr/list/fixtures/prList.json b/pkg/cmd/pr/list/fixtures/prList.json index 13d124f52..eb2b5d31f 100644 --- a/pkg/cmd/pr/list/fixtures/prList.json +++ b/pkg/cmd/pr/list/fixtures/prList.json @@ -8,6 +8,7 @@ "number": 32, "title": "New feature", "url": "https://github.com/monalisa/hello/pull/32", + "createtedAt": "2011-01-26T19:01:12Z", "headRefName": "feature", "state": "OPEN", "isDraft": true @@ -16,6 +17,7 @@ "number": 29, "title": "Fixed bad bug", "url": "https://github.com/monalisa/hello/pull/29", + "createtedAt": "2011-01-26T19:01:12Z", "headRefName": "bug-fix", "state": "OPEN", "isDraft": false, @@ -29,6 +31,7 @@ "state": "MERGED", "isDraft": false, "title": "Improve documentation", + "createtedAt": "2011-01-26T19:01:12Z", "url": "https://github.com/monalisa/hello/pull/28", "headRefName": "docs" } diff --git a/pkg/cmd/pr/list/list.go b/pkg/cmd/pr/list/list.go index b33fe9ff5..07569d998 100644 --- a/pkg/cmd/pr/list/list.go +++ b/pkg/cmd/pr/list/list.go @@ -5,6 +5,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" @@ -123,6 +124,7 @@ var defaultFields = []string{ "headRepositoryOwner", "isCrossRepository", "isDraft", + "createdAt", } func listRun(opts *ListOptions) error { @@ -202,12 +204,20 @@ func listRun(opts *ListOptions) error { if table.IsTTY() { prNum = "#" + prNum } + now := time.Now() + ago := now.Sub(pr.CreatedAt) + table.AddField(prNum, nil, cs.ColorFromString(shared.ColorForPRState(pr))) table.AddField(text.ReplaceExcessiveWhitespace(pr.Title), nil, nil) table.AddField(pr.HeadLabel(), nil, cs.Cyan) if !table.IsTTY() { table.AddField(prStateWithDraft(&pr), nil, nil) } + if table.IsTTY() { + table.AddField(utils.FuzzyAgo(ago), nil, cs.Gray) + } else { + table.AddField(pr.CreatedAt.String(), nil, nil) + } table.EndRow() } err = table.Render() diff --git a/pkg/cmd/pr/list/list_test.go b/pkg/cmd/pr/list/list_test.go index 006f2e78b..ba6149e29 100644 --- a/pkg/cmd/pr/list/list_test.go +++ b/pkg/cmd/pr/list/list_test.go @@ -4,6 +4,7 @@ import ( "bytes" "io" "net/http" + "regexp" "strings" "testing" @@ -71,14 +72,18 @@ func TestPRList(t *testing.T) { t.Fatal(err) } + out := output.String() + timeRE := regexp.MustCompile(`\d+ years`) + out = timeRE.ReplaceAllString(out, "X years") + assert.Equal(t, heredoc.Doc(` Showing 3 of 3 open pull requests in OWNER/REPO - #32 New feature feature - #29 Fixed bad bug hubot:bug-fix - #28 Improve documentation docs - `), output.String()) + #32 New feature feature about X years ago + #29 Fixed bad bug hubot:bug-fix about X years ago + #28 Improve documentation docs about X years ago + `), out) assert.Equal(t, ``, output.Stderr()) } @@ -95,10 +100,14 @@ func TestPRList_nontty(t *testing.T) { assert.Equal(t, "", output.Stderr()) - assert.Equal(t, `32 New feature feature DRAFT -29 Fixed bad bug hubot:bug-fix OPEN -28 Improve documentation docs MERGED -`, output.String()) + out := output.String() + timeRE := regexp.MustCompile(`\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d .\d\d\d\d UTC`) + out = timeRE.ReplaceAllString(out, "XXXX-XX-XX XX:XX:XX +XXXX UTC") + + assert.Equal(t, `32 New feature feature DRAFT XXXX-XX-XX XX:XX:XX +XXXX UTC +29 Fixed bad bug hubot:bug-fix OPEN XXXX-XX-XX XX:XX:XX +XXXX UTC +28 Improve documentation docs MERGED XXXX-XX-XX XX:XX:XX +XXXX UTC +`, out) } func TestPRList_filtering(t *testing.T) { From 61e0c5a294e4b97e4275e8d73dddaf2da4979c99 Mon Sep 17 00:00:00 2001 From: satotake Date: Wed, 17 Aug 2022 02:02:53 +0900 Subject: [PATCH 2/2] Add age field to `pr view` --- pkg/cmd/pr/view/view.go | 11 +++++++++-- pkg/cmd/pr/view/view_test.go | 17 +++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/pr/view/view.go b/pkg/cmd/pr/view/view.go index c385e1654..669da72b1 100644 --- a/pkg/cmd/pr/view/view.go +++ b/pkg/cmd/pr/view/view.go @@ -5,6 +5,7 @@ import ( "sort" "strconv" "strings" + "time" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" @@ -31,12 +32,15 @@ type ViewOptions struct { SelectorArg string BrowserMode bool Comments bool + + Now func() time.Time } func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Command { opts := &ViewOptions{ IO: f.IOStreams, Browser: f.Browser, + Now: time.Now, } cmd := &cobra.Command{ @@ -81,7 +85,7 @@ var defaultFields = []string{ "isDraft", "maintainerCanModify", "mergeable", "additions", "deletions", "commitsCount", "baseRefName", "headRefName", "headRepositoryOwner", "headRepository", "isCrossRepository", "reviewRequests", "reviews", "assignees", "labels", "projectCards", "milestone", - "comments", "reactionGroups", + "comments", "reactionGroups", "createdAt", } func viewRun(opts *ViewOptions) error { @@ -167,16 +171,19 @@ func printRawPrPreview(io *iostreams.IOStreams, pr *api.PullRequest) error { func printHumanPrPreview(opts *ViewOptions, pr *api.PullRequest) error { out := opts.IO.Out cs := opts.IO.ColorScheme() + now := opts.Now() + ago := now.Sub(pr.CreatedAt) // Header (Title and State) fmt.Fprintf(out, "%s #%d\n", cs.Bold(pr.Title), pr.Number) fmt.Fprintf(out, - "%s • %s wants to merge %s into %s from %s • %s %s \n", + "%s • %s wants to merge %s into %s from %s • %s • %s %s \n", shared.StateTitleWithColor(cs, *pr), pr.Author.Login, utils.Pluralize(pr.Commits.TotalCount, "commit"), pr.BaseRefName, pr.HeadRefName, + utils.FuzzyAgo(ago), cs.Green("+"+strconv.Itoa(pr.Additions)), cs.Red("-"+strconv.Itoa(pr.Deletions)), ) diff --git a/pkg/cmd/pr/view/view_test.go b/pkg/cmd/pr/view/view_test.go index a909f0b6c..5791fb59d 100644 --- a/pkg/cmd/pr/view/view_test.go +++ b/pkg/cmd/pr/view/view_test.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "os" + "regexp" "testing" "github.com/cli/cli/v2/api" @@ -351,7 +352,7 @@ func TestPRView_Preview(t *testing.T) { }, expectedOutputs: []string{ `Blueberries are from a fork #12`, - `Open.*nobody wants to merge 12 commits into master from blueberries.+100.-10`, + `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago.+100.-10`, `blueberries taste good`, `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, }, @@ -364,7 +365,7 @@ func TestPRView_Preview(t *testing.T) { }, expectedOutputs: []string{ `Blueberries are from a fork #12`, - `Open.*nobody wants to merge 12 commits into master from blueberries.+100.-10`, + `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago.+100.-10`, `Reviewers:.*1 \(.*Requested.*\)\n`, `Assignees:.*marseilles, monaco\n`, `Labels:.*one, two, three, four, five\n`, @@ -396,7 +397,7 @@ func TestPRView_Preview(t *testing.T) { }, expectedOutputs: []string{ `Blueberries are from a fork #12`, - `Closed.*nobody wants to merge 12 commits into master from blueberries.+100.-10`, + `Closed.*nobody wants to merge 12 commits into master from blueberries . about X years ago.+100.-10`, `blueberries taste good`, `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, }, @@ -409,7 +410,7 @@ func TestPRView_Preview(t *testing.T) { }, expectedOutputs: []string{ `Blueberries are from a fork #12`, - `Merged.*nobody wants to merge 12 commits into master from blueberries.+100.-10`, + `Merged.*nobody wants to merge 12 commits into master from blueberries . about X years ago.+100.-10`, `blueberries taste good`, `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, }, @@ -422,7 +423,7 @@ func TestPRView_Preview(t *testing.T) { }, expectedOutputs: []string{ `Blueberries are from a fork #12`, - `Draft.*nobody wants to merge 12 commits into master from blueberries.+100.-10`, + `Draft.*nobody wants to merge 12 commits into master from blueberries . about X years ago.+100.-10`, `blueberries taste good`, `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, }, @@ -445,8 +446,12 @@ func TestPRView_Preview(t *testing.T) { assert.Equal(t, "", output.Stderr()) + out := output.String() + timeRE := regexp.MustCompile(`\d+ years`) + out = timeRE.ReplaceAllString(out, "X years") + //nolint:staticcheck // prefer exact matchers over ExpectLines - test.ExpectLines(t, output.String(), tc.expectedOutputs...) + test.ExpectLines(t, out, tc.expectedOutputs...) }) } }