Pull in the GraphQL API functionality#8
Conversation
api/client.go
Outdated
| success := resp.StatusCode >= 200 && resp.StatusCode < 300 | ||
|
|
||
| if success { | ||
| gr := &graphQLResponse{Data: v} |
There was a problem hiding this comment.
I'm still getting used to go's variable naming patterns. Is gr a bad name? Is resp better than response? I use v above because I've notice that pattern for interface{} values, but I don't understand why it is v.
There was a problem hiding this comment.
i think v is just short for value. i may not agree with go's terseness, but i think gr is a fine variable name in this context. when in rome.
There was a problem hiding this comment.
I think golang's "official" stance on guidelines for variable naming is that 1–2-letter (abbreviated) variable names are fine as long as the variable is used close to the place of its assignment.
| PullRequests edges | ||
| } | ||
| ViewerCreated edges | ||
| ReviewRequested edges |
There was a problem hiding this comment.
So, I was using the json tag syntax like json:"edges", but when I removed it everything still worked. I can't find any documentation but it seems like go handles this automatically.
There was a problem hiding this comment.
by default go tries to auto-guess field names for serializing. if it works, it works.
vilmibm
left a comment
There was a problem hiding this comment.
given that we're in master now i'd like to see us consistently avoiding panic in favor of go-style errors.
api/client.go
Outdated
| success := resp.StatusCode >= 200 && resp.StatusCode < 300 | ||
|
|
||
| if success { | ||
| gr := &graphQLResponse{Data: v} |
There was a problem hiding this comment.
i think v is just short for value. i may not agree with go's terseness, but i think gr is a fine variable name in this context. when in rome.
| PullRequests edges | ||
| } | ||
| ViewerCreated edges | ||
| ReviewRequested edges |
There was a problem hiding this comment.
by default go tries to auto-guess field names for serializing. if it works, it works.
| currentBranch, error := git.Head() | ||
| if error != nil { | ||
| panic(error) | ||
| prPayload, err := api.PullRequests() |
There was a problem hiding this comment.
this makes perfect sense in the context of the PR and shouldn't change. but for discussion's sake, i've been working on something like this (ignoring errors for brevity's sake):
ghRepo, _ := context.CurrentGitHubRepository()
prs, _ := ghRepo.GetPullRequestsByCurrentBranch()the GitHubRepository struct has methods that would work with api. Does that seem like a good direction?
There was a problem hiding this comment.
Yess love the verbosity of it ✨
| panic(error) | ||
| fmt.Printf("Current Pr\n") | ||
| if prPayload.CurrentPR != nil { | ||
| printPr(*prPayload.CurrentPR) |
There was a problem hiding this comment.
the CurrentPR and similar members are so specific; I wonder if it's worth putting those under some more specific function name like UserPullRequests or something to distinguish between a general list of PRs and the user-oriented lists we've been doing?
i don't know this is probably not urgent
There was a problem hiding this comment.
The problem I ran into is how to have specific functions but keep it as one graphql request.
There was a problem hiding this comment.
ah yeah, I meant keep the one single query but just name the collective output something more specific than "PullRequests" to indicate that it's a particular bundling / organization of PRs
|
@probablycorey What is the best way to trigger HTTP, GitHub API, and GraphQL errors? Thank you. |
|
@tierninho In the future the errors will pre presented better (now they say "panic: blah blah blah")
|
mislav
left a comment
There was a problem hiding this comment.
I like how clean is the API client implementation that supports basically only one endpoint!
api/client.go
Outdated
| success := resp.StatusCode >= 200 && resp.StatusCode < 300 | ||
|
|
||
| if success { | ||
| gr := &graphQLResponse{Data: v} |
There was a problem hiding this comment.
I think golang's "official" stance on guidelines for variable naming is that 1–2-letter (abbreviated) variable names are fine as long as the variable is used close to the place of its assignment.
api/client.go
Outdated
| func handleResponse(resp *http.Response, body []byte, v interface{}) error { | ||
| success := resp.StatusCode >= 200 && resp.StatusCode < 300 | ||
|
|
||
| if success { |
There was a problem hiding this comment.
I was surprised that the "success" path is indented here and returns early, while the error path (handleHTTPError) continues in the main function body. The typical golang style is the other way around: error paths are indented and return early, and the most common (expected case) remains at the top level of a function body.
Would such a general guideline make sense for this logic as well?
command/pr.go
Outdated
| ExecutePr() | ||
| err := ExecutePr() | ||
| if err != nil { | ||
| panic(err) // In the future this should handle the error better, but for now panic seems like a valid reaction |
There was a problem hiding this comment.
This is the approach we've taken in the prototype branch re: cobra commands that potentially return an error:
RunE: func(cmd *cobra.Command, args []string) error {
return ExecutePr()
}I think it's easier to follow that here as well than to panic.
There was a problem hiding this comment.
Ahh, I didn't know about the RunE method! Perfect!
| currentBranch, error := git.Head() | ||
| if error != nil { | ||
| panic(error) | ||
| prPayload, err := api.PullRequests() |
There was a problem hiding this comment.
Yess love the verbosity of it ✨
api/client.go
Outdated
| return handleResponse(resp, body, v) | ||
| } | ||
|
|
||
| func handleResponse(resp *http.Response, body []byte, v interface{}) error { |
There was a problem hiding this comment.
I would prefer to use more descriptive argument names than "v" because function signatures can be shown in text editors/IDEs, and them having human-readable argument names helps understand the purpose of those arguments.
There was a problem hiding this comment.
I spent too long coming up with a new name and settled on "data". I ended up choosing this because it is what the go documentation uses for json.Unmarshal, which has very similar behavior.
|
|
||
| func PullRequests() (PullRequestsPayload, error) { | ||
| type edges struct { | ||
| Edges []struct { |
There was a problem hiding this comment.
TIL:
- that one can define nested struct types directly in the parent struct definition
- that structs can also be defined within a function call 😲
There was a problem hiding this comment.
that structs can also be defined within a function call
I wasn't sure about this pattern. But since the struct is only used in the PullRequests function I figured it keeps everything more contained.
api/queries.go
Outdated
| pullRequests(headRefName: $headRefName, first: 1) { | ||
| edges { | ||
| node { | ||
| ...pr |
There was a problem hiding this comment.
One thing I observe here is how deeply some of these queries can be indented due to nesting. I'm predicting that we will even go deeper. Perhaps indenting by tab is not the best approach for GraphQL, since tabs are shown so wide by default (8 spaces in GitHub UI), and changes around GraphQL queries might be tricky to review due to online diff formatting. Not a huge issue right now; just something to keep in mind!
There was a problem hiding this comment.
My preferred solution would be to use tabs everywhere and make GitHub show tabs as two spaces, but I don't think that's an option. So spaces it is!
vilmibm
left a comment
There was a problem hiding this comment.
errors are consolidated and handling has been moved up, thanks! i'm a fan of mislav's suggestion of putting the panic even higher but i don't think that needs to be addressed here in this PR; i just didn't want a proliferation of new panics
handle errors in port forwarding
This does a few things:
apipackage and aPullRequestsfunction. I didn't expose a more genericGraphQLfunction because it seems like an implementation detail. Also, it keeps all the graphql queries and error handling out of our command files.DEBUGenv to get log debug info from api calls. The output is not pretty and I have regret that I didn't make it easier to read. But a life without regrets is no life at all.gh pr listcommand because the point of this PR is to use GraphQL, not to implement thegh pr listcommand.I've left some inline comments below.