Skip to content

Commit 8668251

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
lint
1 parent 0ecd608 commit 8668251

File tree

5 files changed

+172
-139
lines changed

5 files changed

+172
-139
lines changed

cmd/prcost/main.go

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package main
44
import (
55
"context"
66
"encoding/json"
7+
"errors"
78
"flag"
89
"fmt"
910
"log"
@@ -26,13 +27,15 @@ func main() {
2627

2728
flag.Usage = func() {
2829
fmt.Fprintf(os.Stderr, "Usage: %s [options] <PR_URL>\n\n", os.Args[0])
29-
fmt.Fprintf(os.Stderr, "Calculate the real-world cost of a GitHub pull request.\n\n")
30-
fmt.Fprintf(os.Stderr, "Options:\n")
30+
fmt.Fprint(os.Stderr, "Calculate the real-world cost of a GitHub pull request.\n\n")
31+
fmt.Fprint(os.Stderr, "Options:\n")
3132
flag.PrintDefaults()
32-
fmt.Fprintf(os.Stderr, "\nExamples:\n")
33+
fmt.Fprint(os.Stderr, "\nExamples:\n")
3334
fmt.Fprintf(os.Stderr, " %s https://github.com/owner/repo/pull/123\n", os.Args[0])
3435
fmt.Fprintf(os.Stderr, " %s --salary 300000 --benefits 1.4 https://github.com/owner/repo/pull/123\n", os.Args[0])
35-
fmt.Fprintf(os.Stderr, " %s --salary 200000 --benefits 1.25 --event-minutes 30 --format json https://github.com/owner/repo/pull/123\n", os.Args[0])
36+
fmt.Fprintf(os.Stderr,
37+
" %s --salary 200000 --benefits 1.25 --event-minutes 30 --format json https://github.com/owner/repo/pull/123\n",
38+
os.Args[0])
3639
}
3740

3841
flag.Parse()
@@ -47,7 +50,7 @@ func main() {
4750

4851
// Validate PR URL format
4952
if !strings.HasPrefix(prURL, "https://github.com/") || !strings.Contains(prURL, "/pull/") {
50-
log.Fatalf("Invalid PR URL. Expected format: https://github.com/owner/repo/pull/123")
53+
log.Fatal("Invalid PR URL. Expected format: https://github.com/owner/repo/pull/123")
5154
}
5255

5356
// Create cost configuration from flags
@@ -57,9 +60,9 @@ func main() {
5760
cfg.EventDuration = time.Duration(*eventMinutes) * time.Minute
5861
cfg.DelayCostFactor = *overheadFactor
5962

60-
// Get GitHub token from gh CLI
63+
// Retrieve GitHub token from gh CLI
6164
ctx := context.Background()
62-
token, err := getGitHubToken(ctx)
65+
token, err := authToken(ctx)
6366
if err != nil {
6467
log.Fatalf("Failed to get GitHub token: %v\nPlease ensure 'gh' is installed and authenticated (run 'gh auth login')", err)
6568
}
@@ -76,24 +79,26 @@ func main() {
7679
// Output in requested format
7780
switch *format {
7881
case "human":
79-
printHumanReadable(breakdown, prURL)
82+
printHumanReadable(&breakdown, prURL)
8083
case "json":
81-
printJSON(breakdown)
84+
if err := printJSON(&breakdown); err != nil {
85+
log.Fatalf("Failed to output results: %v", err)
86+
}
8287
default:
8388
log.Fatalf("Unknown format: %s (must be human or json)", *format)
8489
}
8590
}
8691

87-
// getGitHubToken retrieves a GitHub token using the gh CLI.
88-
func getGitHubToken(ctx context.Context) (string, error) {
92+
// authToken retrieves a GitHub token using the gh CLI.
93+
func authToken(ctx context.Context) (string, error) {
8994
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
9095
defer cancel()
9196

9297
cmd := exec.CommandContext(ctx, "gh", "auth", "token")
9398
output, err := cmd.Output()
9499
if err != nil {
95100
if ctx.Err() == context.DeadlineExceeded {
96-
return "", fmt.Errorf("timeout getting auth token")
101+
return "", errors.New("timeout getting auth token")
97102
}
98103
return "", fmt.Errorf("failed to get auth token (is 'gh' installed and authenticated?): %w", err)
99104
}
@@ -103,31 +108,32 @@ func getGitHubToken(ctx context.Context) (string, error) {
103108
}
104109

105110
// printHumanReadable outputs a detailed itemized bill in human-readable format.
106-
func printHumanReadable(b cost.Breakdown, prURL string) {
107-
fmt.Printf("PULL REQUEST COST ANALYSIS\n")
108-
fmt.Printf("==========================\n\n")
111+
func printHumanReadable(breakdown *cost.Breakdown, prURL string) {
112+
fmt.Println("PULL REQUEST COST ANALYSIS")
113+
fmt.Println("==========================")
114+
fmt.Println()
109115
fmt.Printf("PR URL: %s\n", prURL)
110116
fmt.Printf("Hourly Rate: $%.2f ($%.0f salary * %.1fX total benefits multiplier)\n\n",
111-
b.HourlyRate, b.AnnualSalary, b.BenefitsMultiplier)
117+
breakdown.HourlyRate, breakdown.AnnualSalary, breakdown.BenefitsMultiplier)
112118

113119
// Author Costs
114-
fmt.Printf("AUTHOR COSTS\n")
120+
fmt.Println("AUTHOR COSTS")
115121
fmt.Printf(" Code Cost (COCOMO) $%10.2f (%d LOC, %.2f hrs)\n",
116-
b.Author.CodeCost, b.Author.LinesAdded, b.Author.CodeHours)
122+
breakdown.Author.CodeCost, breakdown.Author.LinesAdded, breakdown.Author.CodeHours)
117123
fmt.Printf(" Code Context Switching $%10.2f (%.2f hrs)\n",
118-
b.Author.CodeContextCost, b.Author.CodeContextHours)
124+
breakdown.Author.CodeContextCost, breakdown.Author.CodeContextHours)
119125
fmt.Printf(" GitHub Time $%10.2f (%d events, %.2f hrs)\n",
120-
b.Author.GitHubCost, b.Author.Events, b.Author.GitHubHours)
126+
breakdown.Author.GitHubCost, breakdown.Author.Events, breakdown.Author.GitHubHours)
121127
fmt.Printf(" GitHub Context Switching $%10.2f (%d sessions, %.2f hrs)\n",
122-
b.Author.GitHubContextCost, b.Author.Sessions, b.Author.GitHubContextHours)
123-
fmt.Printf(" ---\n")
128+
breakdown.Author.GitHubContextCost, breakdown.Author.Sessions, breakdown.Author.GitHubContextHours)
129+
fmt.Println(" ---")
124130
fmt.Printf(" Author Subtotal $%10.2f (%.2f hrs total)\n\n",
125-
b.Author.TotalCost, b.Author.TotalHours)
131+
breakdown.Author.TotalCost, breakdown.Author.TotalHours)
126132

127133
// Participant Costs
128-
if len(b.Participants) > 0 {
129-
fmt.Printf("PARTICIPANT COSTS\n")
130-
for _, p := range b.Participants {
134+
if len(breakdown.Participants) > 0 {
135+
fmt.Println("PARTICIPANT COSTS")
136+
for _, p := range breakdown.Participants {
131137
fmt.Printf(" %s\n", p.Actor)
132138
fmt.Printf(" Event Time $%10.2f (%d events, %.2f hrs)\n",
133139
p.GitHubCost, p.Events, p.GitHubHours)
@@ -140,53 +146,51 @@ func printHumanReadable(b cost.Breakdown, prURL string) {
140146
// Sum all participant costs
141147
var totalParticipantCost float64
142148
var totalParticipantHours float64
143-
for _, p := range b.Participants {
149+
for _, p := range breakdown.Participants {
144150
totalParticipantCost += p.TotalCost
145151
totalParticipantHours += p.TotalHours
146152
}
147-
fmt.Printf(" ---\n")
153+
fmt.Println(" ---")
148154
fmt.Printf(" Participants Subtotal $%10.2f (%.2f hrs total)\n\n",
149155
totalParticipantCost, totalParticipantHours)
150156
}
151157

152158
// Delay Cost
153-
fmt.Printf("DELAY COST\n")
154-
if b.DelayCapped {
159+
fmt.Println("DELAY COST")
160+
if breakdown.DelayCapped {
155161
fmt.Printf(" %-32s $%10.2f (%.0f hrs, capped at 60 days)\n",
156-
"Project Delay (20%)", b.DelayCostDetail.ProjectDelayCost, b.DelayCostDetail.ProjectDelayHours)
162+
"Project Delay (20%)", breakdown.DelayCostDetail.ProjectDelayCost, breakdown.DelayCostDetail.ProjectDelayHours)
157163
} else {
158164
fmt.Printf(" %-32s $%10.2f (%.2f hrs)\n",
159-
"Project Delay (20%)", b.DelayCostDetail.ProjectDelayCost, b.DelayCostDetail.ProjectDelayHours)
165+
"Project Delay (20%)", breakdown.DelayCostDetail.ProjectDelayCost, breakdown.DelayCostDetail.ProjectDelayHours)
160166
}
161167

162-
if b.DelayCostDetail.ReworkPercentage > 0 {
163-
label := fmt.Sprintf("Code Updates (%.0f%% rework)", b.DelayCostDetail.ReworkPercentage)
168+
if breakdown.DelayCostDetail.ReworkPercentage > 0 {
169+
label := fmt.Sprintf("Code Updates (%.0f%% rework)", breakdown.DelayCostDetail.ReworkPercentage)
164170
fmt.Printf(" %-32s $%10.2f (%.2f hrs)\n",
165-
label, b.DelayCostDetail.CodeUpdatesCost, b.DelayCostDetail.CodeUpdatesHours)
171+
label, breakdown.DelayCostDetail.CodeUpdatesCost, breakdown.DelayCostDetail.CodeUpdatesHours)
166172
}
167173

168174
fmt.Printf(" %-32s $%10.2f (%.2f hrs)\n",
169-
"Future GitHub (3 events)", b.DelayCostDetail.FutureGitHubCost, b.DelayCostDetail.FutureGitHubHours)
170-
fmt.Printf(" ---\n")
175+
"Future GitHub (3 events)", breakdown.DelayCostDetail.FutureGitHubCost, breakdown.DelayCostDetail.FutureGitHubHours)
176+
fmt.Println(" ---")
171177

172-
if b.DelayCapped {
178+
if breakdown.DelayCapped {
173179
fmt.Printf(" Total Delay Cost $%10.2f (actual: %.0f hours open)\n\n",
174-
b.DelayCost, b.DelayHours)
180+
breakdown.DelayCost, breakdown.DelayHours)
175181
} else {
176-
fmt.Printf(" Total Delay Cost $%10.2f\n\n", b.DelayCost)
182+
fmt.Printf(" Total Delay Cost $%10.2f\n\n", breakdown.DelayCost)
177183
}
178184

179185
// Total
180-
fmt.Printf("==========================\n")
181-
fmt.Printf("TOTAL COST $%10.2f\n", b.TotalCost)
182-
fmt.Printf("==========================\n")
186+
fmt.Println("==========================")
187+
fmt.Printf("TOTAL COST $%10.2f\n", breakdown.TotalCost)
188+
fmt.Println("==========================")
183189
}
184190

185191
// printJSON outputs the cost breakdown in JSON format.
186-
func printJSON(b cost.Breakdown) {
192+
func printJSON(breakdown *cost.Breakdown) error {
187193
encoder := json.NewEncoder(os.Stdout)
188194
encoder.SetIndent("", " ")
189-
if err := encoder.Encode(b); err != nil {
190-
log.Fatalf("Failed to encode JSON: %v", err)
191-
}
195+
return encoder.Encode(breakdown)
192196
}

0 commit comments

Comments
 (0)