Skip to content

Support Google App Engine with recent context changes #582

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

Merged
merged 4 commits into from
Mar 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ straightforward.
[contributing]: CONTRIBUTING.md


## Google App Engine ##

Go on App Engine Classic (which as of this writing uses Go 1.6) can not use
the `"context"` import and still relies on `"golang.org/x/net/context"`.
As a result, if you wish to continue to use `go-github` on App Engine Classic,
you will need to rewrite all the `"context"` imports using the following command:

`gofmt -w -r '"context" -> "golang.org/x/net/context"' *.go`

See `with_appengine.go` for more details.

## License ##

This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE)
Expand Down
11 changes: 11 additions & 0 deletions github/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,16 @@ github.Response struct.
opt.ListOptions.Page = resp.NextPage
}

Google App Engine

Go on App Engine Classic (which as of this writing uses Go 1.6) can not use
the "context" import and still relies on "golang.org/x/net/context".
As a result, if you wish to continue to use "go-github" on App Engine Classic,
you will need to rewrite all the "context" imports using the following command:

gofmt -w -r '"context" -> "golang.org/x/net/context"' *.go

See "with_appengine.go" for more details.

*/
package github
2 changes: 1 addition & 1 deletion github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func parseRate(r *http.Response) Rate {
// The provided ctx must be non-nil. If it is canceled or times out,
// ctx.Err() will be returned.
func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) {
req = req.WithContext(ctx)
ctx, req = withContext(ctx, req)

rateLimitCategory := category(req.URL.Path)

Expand Down
5 changes: 3 additions & 2 deletions github/repos_contents.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,11 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st
}
var resp *http.Response
// Use http.DefaultTransport if no custom Transport is configured
ctx, req = withContext(ctx, req)
if s.client.client.Transport == nil {
resp, err = http.DefaultTransport.RoundTrip(req.WithContext(ctx))
resp, err = http.DefaultTransport.RoundTrip(req)
} else {
resp, err = s.client.client.Transport.RoundTrip(req.WithContext(ctx))
resp, err = s.client.client.Transport.RoundTrip(req)
}
if err != nil {
return nil, nil, err
Expand Down
3 changes: 2 additions & 1 deletion github/repos_releases.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, r
}
defer func() { s.client.client.CheckRedirect = saveRedirect }()

resp, err := s.client.client.Do(req.WithContext(ctx))
ctx, req = withContext(ctx, req)
resp, err := s.client.client.Do(req)
if err != nil {
if !strings.Contains(err.Error(), "disable redirect") {
return nil, "", err
Expand Down
26 changes: 26 additions & 0 deletions github/with_appengine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build appengine

// This file provides glue for making github work on App Engine.
// In order to get the entire github package to compile with
// Go 1.6, you will need to rewrite all the import "context" lines.
// Fortunately, this is easy with "gofmt":
//
// gofmt -w -r '"context" -> "golang.org/x/net/context"' *.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asking users to modify the source code of a package in order to get it to work is pretty unusual, and I feel this comment would be hard to spot.

I think a nice thing we can do for users is mention this in a new "App Engine" section of README (and package comment, to keep them in sync). It can simply state the current situation, that the package is expected not to build by default and needs to be modified, and point to this file for further instructions. Similar to what you wrote in #582 (comment).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.
Done.


package github

import (
"context"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't use App Engine, so I'm not familiar. If #526 (comment) is accurate, and App Engine uses/forces you to use Go 1.6, how does this work? Package context was added to Go standard library in Go 1.7, it wasn't available in Go 1.6.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an excellent point, and I believe this was an oversight on my part.
Internally, we have our own context so I didn't remember this was an issue.
I'll change it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although now that I'm thinking about this a little more, I'm wondering how the other import "context" in the rest of this package are going to work.

I think I'm going to have to do some more experimentation with this PR before we call it ready for review. Sorry, @shurcooL.

Copy link
Member

@dmitshur dmitshur Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the case, that's going to be an issue. Just about every single file in package github imports context.

If we need the appengine version to import golang.org/x/net/context instead, we will have to make a copy of each and every .go file.

That would be a pretty significant disturbance, and it was one of the main reasons we decided to wait for Go 1.8 to come out, so that we could drop support for 1.6 and older before adding context support to this package.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I seem to remember hearing Dave Symonds say that the two implementations are 100% compatible... so maybe I don't need to change things after all... I'm just not sure if the Go 1.6 compiler will actually find the bare "context" import or not.
I definitely think that we don't need to make those kinds of accommodations here in this repo, though.

"net/http"

"google.golang.org/appengine"
)

func withContext(ctx context.Context, req *http.Request) (context.Context, *http.Request) {
return appengine.WithContext(ctx, req), req
}
19 changes: 19 additions & 0 deletions github/without_appengine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !appengine

// This file provides glue for making github work without App Engine.

package github

import (
"context"
"net/http"
)

func withContext(ctx context.Context, req *http.Request) (context.Context, *http.Request) {
return ctx, req.WithContext(ctx)
}