From 29687a0d8d2e53d936871d58328dab612a94b08c Mon Sep 17 00:00:00 2001 From: Jonathan Seth Mainguy Date: Sun, 24 Mar 2024 09:35:14 -0400 Subject: [PATCH] feat: add output options as flags --- README.md | 55 +++++++++++++++++++++++++++++++++++++++-- main.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++---- prs.go | 10 ++++---- prs_test.go | 4 +-- structs.go | 4 +-- 5 files changed, 128 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0c6e941..4f4b690 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ token: e0e9eac4e84446df6f3db180d07bfb222e91234 Running the progam ``` -ghreport +ghreport [-output=] ``` -Sample output +### Sample output with default format. ``` jmainguy@fedora:~/Github/ghreport$ ./ghreport @@ -60,6 +60,57 @@ https://github.com/Standouthost/Multicraft/pull/28 mergeable ✅ ``` +### Sample output with single-line format + +``` +jmainguy@fedora:~/Github/ghreport$ ./ghreport -output singleline +https://github.com/Jmainguy/coastie-operator/pull/2 author: dependabot Age: 409 days reviewDecision: 🔍 mergeable: ✅ +https://github.com/Jmainguy/coastie-operator/pull/3 author: dependabot Age: 384 days reviewDecision: 🔍 mergeable: ✅ +https://github.com/Jmainguy/coastie-operator/pull/4 author: renovate Age: 354 days reviewDecision: 🔍 mergeable: ✅ +https://github.com/Standouthost/Multicraft/pull/9 author: TheWebGamer Age: 3321 days reviewDecision: ✅ mergeable: ❌ +``` + + +### Sample output with JSON format + +``` +jmainguy@fedora:~/Github/ghreport$ ./ghreport -output json +{"url":"https://github.com/Jmainguy/k8sCapcity/pull/50","author":"github-actions","age":"24 days","review_decision":"😅","mergeable":"✅"} +{"url":"https://github.com/Jmainguy/k8sDrainReport/pull/27","author":"github-actions","age":"8 days","review_decision":"😅","mergeable":"✅"} +{"url":"https://github.com/Standouthost/Multicraft/pull/9","author":"TheWebGamer","age":"3321 days","review_decision":"✅","mergeable":"❌"} +``` + +### Fun with jq and JSON +#### Select on repo name +``` +jmainguy@fedora:~/Github/ghreport$ ./ghreport -output=json | jq '. | select(.url | contains("k8sCapcity"))' +{ + "url": "https://github.com/Jmainguy/k8sCapcity/pull/50", + "author": "github-actions", + "age": "24 days", + "review_decision": "😅", + "mergeable": "✅" +} +``` +#### Select on author +``` +jmainguy@fedora:~/Github/ghreport$ ./ghreport -output=json | jq '. | select(.author == "github-actions")' +{ + "url": "https://github.com/Jmainguy/k8sDrainReport/pull/27", + "author": "github-actions", + "age": "8 days", + "review_decision": "😅", + "mergeable": "✅" +} +{ + "url": "https://github.com/Jmainguy/k8sCapcity/pull/50", + "author": "github-actions", + "age": "24 days", + "review_decision": "😅", + "mergeable": "✅" +} +``` + ## Releases We currently build releases for RPM, DEB, macOS, and Windows. diff --git a/main.go b/main.go index e33efdc..644ecb9 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,8 @@ package main import ( + "encoding/json" + "flag" "fmt" "os" "strings" @@ -8,8 +10,14 @@ import ( "time" ) +// Flags : Define a struct to hold command-line flags +type Flags struct { + OutputFormat string +} + func main() { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + // Parse command-line flags + flags := parseFlags() config, err := getConfig() if err != nil { @@ -60,6 +68,8 @@ func main() { repoMap[strings.ToLower(repoString)] = true } + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + // List of repos to watch for ownerRepo := range repoMap { @@ -83,11 +93,62 @@ func main() { mergeableEmoji := getMergeableEmoji(string(pr.Mergeable)) - fmt.Fprintf(w, "%s\n\tauthor: %s\n\tAge: %s \n\treviewDecision: %s\n\tmergeable %s\n", pr.URL, pr.Owner, timeLabel, reviewDecisionEmoji, mergeableEmoji) - - //fmt.Fprintf(w, "%s:\tauthor: %s\tcreatedAt %s\treviewDecison %s\tmergeable %s\n", pr.URL, pr.Owner, pr.CreatedAt, pr.ReviewDecision, pr.Mergeable) + // Choose output format based on the flag + switch flags.OutputFormat { + case "json": + outputJSON(pr, timeLabel, reviewDecisionEmoji, mergeableEmoji) + case "singleline": + outputSingleLine(pr, timeLabel, reviewDecisionEmoji, mergeableEmoji) + default: + outputDefault(w, pr, timeLabel, reviewDecisionEmoji, mergeableEmoji) + } } } - w.Flush() + if flags.OutputFormat == "" { + w.Flush() + } +} + +// Function to parse command-line flags +func parseFlags() Flags { + var outputFormat string + flag.StringVar(&outputFormat, "output", "", "Output format (default, singleline, json)") + flag.Parse() + return Flags{OutputFormat: outputFormat} +} + +// Function to output data in default format +func outputDefault(w *tabwriter.Writer, pr PullRequest, timeLabel, reviewDecisionEmoji, mergeableEmoji string) { + fmt.Fprintf(w, "%s\n\tauthor: %s\n\tAge: %s \n\treviewDecision: %s\n\tmergeable %s\n", pr.URL, pr.Owner, timeLabel, reviewDecisionEmoji, mergeableEmoji) +} + +// Function to output data in single-line format +func outputSingleLine(pr PullRequest, timeLabel, reviewDecisionEmoji, mergeableEmoji string) { + fmt.Printf("%s author: %s Age: %s reviewDecision: %s mergeable: %s\n", pr.URL, pr.Owner, timeLabel, reviewDecisionEmoji, mergeableEmoji) +} + +// Function to output data in JSON format +func outputJSON(pr PullRequest, timeLabel, reviewDecisionEmoji, mergeableEmoji string) { + data := struct { + URL string `json:"url"` + Author string `json:"author"` + Age string `json:"age"` + ReviewDecision string `json:"review_decision"` + Mergeable string `json:"mergeable"` + }{ + URL: pr.URL, + Author: string(pr.Owner), + Age: timeLabel, + ReviewDecision: reviewDecisionEmoji, + Mergeable: mergeableEmoji, + } + + jsonData, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(string(jsonData)) } diff --git a/prs.go b/prs.go index d840d70..dfc4b2a 100644 --- a/prs.go +++ b/prs.go @@ -7,7 +7,7 @@ import ( "github.com/shurcooL/githubv4" ) -func getPrFromRepo(client Client, org, repo string) ([]PR, error) { +func getPrFromRepo(client Client, org, repo string) ([]PullRequest, error) { var repoQuery struct { Repository struct { PullRequests struct { @@ -23,7 +23,7 @@ func getPrFromRepo(client Client, org, repo string) ([]PR, error) { githubv4.PullRequestStateOpen, } - var PRS []PR + var PRS []PullRequest variables := map[string]interface{}{ "org": githubv4.String(org), @@ -57,12 +57,12 @@ func getPrFromRepo(client Client, org, repo string) ([]PR, error) { return PRS, nil } -func extractPRDataFromEdges(edges []PullRequestEdge) []PR { - var PRS []PR +func extractPRDataFromEdges(edges []PullRequestEdge) []PullRequest { + var PRS []PullRequest for _, edge := range edges { if !bool(edge.Node.IsDraft) { - var pr PR + var pr PullRequest pr.URL = edge.Node.URL.String() pr.CreatedAt = edge.Node.CreatedAt pr.Owner = edge.Node.Author.Login diff --git a/prs_test.go b/prs_test.go index 60fe9fe..f78b47a 100644 --- a/prs_test.go +++ b/prs_test.go @@ -73,7 +73,7 @@ func TestExtractPRDataFromEdges(t *testing.T) { } // Define expected output - expected := []PR{ + expected := []PullRequest{ { URL: "https://github.com/my-org/my-repo/pull/1", CreatedAt: githubv4.DateTime{Time: time.Now().UTC().Truncate(time.Hour)}, @@ -92,7 +92,7 @@ func TestGetPrFromRepo(t *testing.T) { // Mock data for testing org := "testOrg" repo := "testRepo" - prs := []PR{ + prs := []PullRequest{ {CreatedAt: githubv4.DateTime{}, URL: "https://github.com/testOrg/testRepo/pull/1", Owner: "john_doe"}, } diff --git a/structs.go b/structs.go index 5465c62..85824de 100644 --- a/structs.go +++ b/structs.go @@ -6,8 +6,8 @@ import ( "github.com/shurcooL/githubv4" ) -// PR : A pullRequest -type PR struct { +// PullRequest : A pullRequest +type PullRequest struct { CreatedAt githubv4.DateTime `json:"createdAt"` URL string `json:"url"` Owner githubv4.String `json:"owner"`