-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add support for context package. #529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
github/github.go
Outdated
// to pass during the transition period. Once all endpoints are updated | ||
// to accept ctx parameter, the old Do method can be removed, and this | ||
// new do method with ctx parameter should be made to take its place. | ||
func (c *Client) do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { | ||
rateLimitCategory := category(req.URL.Path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would a nil check make sense here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's unnecessary.
The context
package is already documented to say that nil
value of context.Context
shouldn't be passed:
Do not pass a nil Context, even if a function permits it. Pass context.TODO if you are unsure about which Context to use.
So all valid code will always have non-nil
value of ctx
.
Invalid code can be easily caught by static analysis tools such as go vet, as the context
package docs allude:
Programs that use Contexts should follow these rules to keep interfaces consistent across packages and enable static analysis tools to check context propagation
TODO is recognized by static analysis tools that determine whether Contexts are propagated correctly in a program.
.travis.yml
Outdated
- 1.6.3 | ||
- 1.7 | ||
- tip | ||
- 1.7.x |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add 1.8.x here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should, once it comes out.
I'll update the PR at that time to include it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that 1.8 is out, this is done in 1ebf55f (see line below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
github/github.go
Outdated
rateLimitCategory := category(req.URL.Path) | ||
|
||
// If we've hit rate limit, don't make further requests before Reset time. | ||
if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { | ||
return nil, err | ||
} | ||
|
||
resp, err := c.client.Do(req) | ||
resp, err := c.client.Do(req.WithContext(ctx)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the WithContext docs state that "the provided ctx must be non-nil." worth erroring about here, or is the panic in net/http okay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a
I like this approach, @shurcooL. |
Ok this looks good to me |
@@ -149,7 +150,7 @@ func TestIssuesService_Get(t *testing.T) { | |||
fmt.Fprint(w, `{"number":1, "labels": [{"url": "u", "name": "n", "color": "c"}]}`) | |||
}) | |||
|
|||
issue, _, err := client.Issues.Get("o", "r", 1) | |||
issue, _, err := client.Issues.Get(context.Background(), "o", "r", 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just for brevity, we might want to have a package-level:
var ctx = context.Background()
(or is that discouraged somewhere?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally liked context.Background()
everywhere (even in tests), but it was mostly because I wasn't sure if reusing the same context value in multiple places was okay. It turns out it is (/cc @rakyll), because of how it's implemented.
I still kinda like/don't mind context.Background()
everywhere because it's readable and I don't think saving a bit of typing is worth it, but I'm also okay with with var bg = context.Background()
or similar (in tests only).
Previous discussions:
Okay, now that 1.8 is out, this is unblocked. I wanted to make some progress here. I decided to prototype the rest of the change. Basically, change all the endpoints to accept Also, doing a global replace of I'll push the final version and post my observations afterwards. |
Okay, here are my 3 observations from prototyping the entire PR:
I'm going to let this sit as is and think about point 2 myself. If I still think it's a good idea, I might try to change signature of |
I've thought about observation 2 some more, and decided to make See commit 1563515, the rationale is inside its commit message:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to stop the review at this point and see if you agree with splitting this into 3 PRs.
Thank you, @shurcooL!
examples/basicauth/main.go
Outdated
|
||
// Is this a two-factor auth error? If so, prompt for OTP and try again. | ||
if _, ok := err.(*github.TwoFactorAuthError); err != nil && ok { | ||
fmt.Print("\nGitHub OTP: ") | ||
otp, _ := r.ReadString('\n') | ||
tp.OTP = strings.TrimSpace(otp) | ||
user, _, err = client.Users.Get("") | ||
user, _, err = client.Users.Get(context.Background(), "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to show calling context.Background
twice in a row within a single function as an example to be followed. Instead, please assign ctx := context.Background()
once before or after line 37 and then use ctx
in both locations in place of context.Background()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In examples I think it would be better to use context.TODO()
tbh to emphasize to the user that they should set as appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... I'm not sure I agree with that.
Most clients that are not being used within a server will simply want ctx := context.Background()
and as such is a fine example, especially for newbie Go devs. More experienced Go programmers will realize that they can replace the context with any one that they already have in operation and will have no problem swapping it out for their own.
But having said that, I don't feel really strongly about TODO
vs Background
.
I feel more strongly, though, about not duplicating the call and instead assigning to a ctx
variable, as that is more idiomatic Go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, using context.TODO()
can be seen in two ways:
- It's a TODO for the reader to replace it with a proper context.
- It's a TODO that we, the library authors, haven't resolved.
I think you want it to be seen as 1, but it might be seen as 2... So I'd rather use context.Background()
over context.TODO()
for that reason. I think it's clear that someone can/should replace context.Background()
with their own context if they need/want to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github/event_types.go
Outdated
@@ -130,19 +130,6 @@ type GollumEvent struct { | |||
Installation *Installation `json:"installation,omitempty"` | |||
} | |||
|
|||
// IssueActivityEvent represents the payload delivered by Issue webhook. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read your discussion about deprecation and agree, but now that I look at this, I think we want 3 separate PRs to make for a clean and easy-to-understand history:
- PR#1 - Update repo to Go 1.7 and Go 1.8 and bump version number
- PR#2 - Remove everything that is deprecated
- PR#3 - Support context.Context (only)
If that order is not correct, then put them in the correct order.
My point here is that PR#2 and PR#3 are completely orthogonal, or should be made so as much as possible.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great to me. I'll break it up into 3 PRs, it's just a matter of splitting up those commits, I won't have to do anything extra. :)
However, the tests of 3rd PR will fail until 1st is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, the tests of 3rd PR will fail until 1st is merged.
Actually, I just came up with a really sneaky way of getting around that. 😜
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are any sorts of tools that can detect unused function parameters, those might be useful for detecting (in an automated way) a missing req.WithContext(ctx)
.
examples/basicauth/main.go
Outdated
|
||
// Is this a two-factor auth error? If so, prompt for OTP and try again. | ||
if _, ok := err.(*github.TwoFactorAuthError); err != nil && ok { | ||
fmt.Print("\nGitHub OTP: ") | ||
otp, _ := r.ReadString('\n') | ||
tp.OTP = strings.TrimSpace(otp) | ||
user, _, err = client.Users.Get("") | ||
user, _, err = client.Users.Get(context.Background(), "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In examples I think it would be better to use context.TODO()
tbh to emphasize to the user that they should set as appropriate.
Agree on this |
Edit: Both #554 and #555 have been reviewed and merged to This is part 3 of 3 PRs to resolve #526 (as was suggested to split this PR in #529 (comment)). |
66f3140
to
dae2143
Compare
dae2143
to
f34b33d
Compare
This is a breaking API change. Prototype the change on one endpoint: IssuesService.Get(ctx context.Context, owner string, repo string, number int) Note that the new do method is temporary, needed only so that I don't have to change all other endpoints at the same time (otherwise they would have build errors).
The idea is to try to change everything else, and see if any additional insight comes from doing that.
These two methods make custom HTTP calls and do not use the github.Client.Do method, and were missed. I caught them now thanks to a tool written by @dominikh that reports unused method parameters.
Everything still looks good, I'm proceeding with the plan to merge this PR now. |
Update for context support added in google/go-github#529.
Update for context support added in google/go-github#529.
This reverts commit 23d6cb9.
ctx is a common and well understood variable name that represents the current context.Context value. This is a followup to #529.
Hello, I'm a relatively new go dev but this PR just broke completely the API of this library (as said in the description of 23d6cb9) . I'm not able (too noob in go) to discus choices made with this context added in all Method of the API, and not willing to discus about that.
What is your solution for people that do not want to fix all already existing codebase to add a mysterious "context" (for me) in all Method call (even if the compiler yell clearly about whats wrong) ? Regards, |
@ztec: take a look at https://golang.org/wiki/PackageManagementTools |
@willnorris So you are saying that not-so-go/unofficial/unfinished/bogous tools should be used to do vendor locking ? I find it weird because almost everything in go is "standard" and integrated in the go environment. I'v already found libraries doing basic versioning for major breaking change like the one of this PR. They use different branches (v1/v2/...) and often state that older versions are not maintained anymore. This allow updates for older versions as well as usage by existing code. What about your (this repo managers) responsibility about defining versions with clear information about breaking changes of the library ? Like Semver specify it for example. Or simply by creating a branch for older version with warning about maintenance ? ps: I find tools of your link good ideas and solutions. |
I'm not trying to tell anyone what they should do, I was merely answering your question about how to handle vendoring in Go. As you probably saw on that page, there is an official tool in the works, but it's not ready yet. The other option is to manually snapshot specific versions of your dependencies and check them in to your version control system, which is basically what many people did before the availability of the above tools. It's a lot more work, but addresses your concern about relying on unofficial or unfinished tools. There has been discussion of versioning in general as well as tagging our releases in git (see #376). At the time, we opted not to do git tags and to increment the libraryVersion const on breaking changes. Admittedly, that doesn't really help with build breakages, since you can't read the const at that point anyway. Managing dependency versions has been a problem within the Go community for a long time. In the time since #376, there has been much more effort to organize a "real" solution, and I'm happy to make whatever changes we need to work in that world. I'm happy to continue this discussion over on #376, so we can keep it all together. |
Adds support for changes in go-github package in: google/go-github#529 Fixes #12.
* Update github package to support updated go-github library Adds support for changes in go-github package in: google/go-github#529 Fixes #12. * Pass gin context object instead of creating new
This is a large breaking API change. It is unavoidable and necessary to resolve google#526. This breaking change is part of bump to libraryVersion 3. It adds ctx context.Context as first parameter to all endpoint methods, including Do. Updating for this API change should be easy and the compiler will help catch instances that need to be updated. For example: main.go:193: not enough arguments in call to gh.Activity.MarkRepositoryNotificationsRead have (string, string, time.Time) want (context.Context, string, string, time.Time) ... You should pass the available context as first parameter. If your code does not have context.Context available and you want to maintain previous normal behavior, use context.Background(). Don't pass nil context; use context.TODO() instead if you wish to delay figuring out the best context to use. Then you can address the TODO at a later time. Refer to documentation of package context at https://godoc.org/context for more information. This commit also changes ./tests/fields to use context.Background() instead of deprecated oauth2.NoContext. Resolves google#526.
DO NOT MERGE. I plan to propose changes before we merge.Edit: Changes proposed in #526 (comment) and applied to this PR.Resolves #526.