feat!: Refactor client constructor to use options pattern#4201
feat!: Refactor client constructor to use options pattern#4201stevehipwell wants to merge 1 commit intogoogle:masterfrom
Conversation
Signed-off-by: Steve Hipwell <steve.hipwell@gmail.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4201 +/- ##
==========================================
- Coverage 93.71% 93.48% -0.23%
==========================================
Files 209 209
Lines 19772 19885 +113
==========================================
+ Hits 18529 18590 +61
- Misses 1046 1094 +48
- Partials 197 201 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
gmlewis
left a comment
There was a problem hiding this comment.
Thank you, @stevehipwell.
Although I like the overall pattern, I have a few concerns with this PR.
First, the various fields within Client were originally exported individually, on a case-by-case basis, as users had need to access them. Suddenly unexporting all fields may wreak havoc.
Second, the clientMu was indeed needed to solve a race condition found when copying clients that were currently in-flight, if I'm remembering correctly.
Can we keep the nice builder pattern you've created here without unexporting all the fields and without removing the mutex that is protecting the client?
| fmt.Printf("\nerror: %v\n", err) | ||
| return |
There was a problem hiding this comment.
| fmt.Printf("\nerror: %v\n", err) | |
| return | |
| log.Fatalf("error: %v", err) |
There was a problem hiding this comment.
I intentionally kept the existing pattern for the individual examples rather than standardising them all.
| fmt.Printf("Error creating GitHub client: %v\n", err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client: %v\n", err) | |
| os.Exit(1) | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| fmt.Printf("Error creating GitHub client: %v\n", err) | ||
| return |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client: %v\n", err) | |
| return | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| client := github.NewClient(nil).WithAuthToken(string(token)) | ||
| client, err := github.NewClient(github.WithAuthToken(string(token))) | ||
| if err != nil { | ||
| log.Fatalf("Error creating GitHub client: %v\n", err) |
There was a problem hiding this comment.
| log.Fatalf("Error creating GitHub client: %v\n", err) | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| client := github.NewClient(nil).WithAuthToken(token) | ||
| client, err := github.NewClient(github.WithAuthToken(token)) | ||
| if err != nil { | ||
| log.Fatalf("Error creating GitHub client: %v\n", err) |
There was a problem hiding this comment.
| log.Fatalf("Error creating GitHub client: %v\n", err) | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| fmt.Printf("Error creating GitHub client: %v\n", err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client: %v\n", err) | |
| os.Exit(1) | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| fmt.Printf("Error creating GitHub client with token: %v\n", err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client with token: %v\n", err) | |
| os.Exit(1) | |
| log.Fatalf("Error creating GitHub client with token: %v", err) |
| fmt.Printf("Error creating GitHub client: %v\n", err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client: %v\n", err) | |
| os.Exit(1) | |
| log.Fatalf("Error creating GitHub client: %v", err) |
| fmt.Printf("Error creating GitHub client with token: %v\n", err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
| fmt.Printf("Error creating GitHub client with token: %v\n", err) | |
| os.Exit(1) | |
| log.Fatalf("Error creating GitHub client with token: %v", err) |
|
|
||
| // for testing | ||
| GithubURL string `kong:"hidden,default='https://api.github.com'"` | ||
| UploadURL string `kong:"hidden,default='https://uploads.github.com'"` |
There was a problem hiding this comment.
This seems unrelated. Are you addressing two issues in this PR?
There was a problem hiding this comment.
The old pattern allowed you to leave the client in an invalid state and would just error when you used an empty URL. The new pattern checks for errors early so there is no uncertainty later as to why a call failed.
|
@gmlewis if you look at the code you'll see that Unexporting the values and putting them behind the options pattern to make the client immutable is core I the whole pattern. Could you provide some examples where these need changing and |
This PR refactors the client to be immutable and to use the with options pattern for construction. This is a significant change but it should reduce the overall complexity and support better UX around new capabilities and backwards compatibility (e.g.
github.WithAPIVersion("2026-03-10")orgithub.WithGHESVersion("3.15")).Clientis immutableNewClientis the only way to create a newClientClientis created if you need to create a new one you can useCloneClientconfiguration is explicitNewClientcauses an early error instead of waiting for a failure or silently doing nothingclientMuwas unnecessaryCloses #3870
Closes #3915