Repository: google/go-github (Go)

Issue:
Add NewTokenClient constructor
I often write one-off tools using this module and I keep needing to come back to the docs to copy/paste this snippet.

``` go
client := github.NewClient(
	oauth2.NewClient(
		ctx, oauth2.StaticTokenSource(
			&oauth2.Token{
				AccessToken: token,
			},
		),
	),
)
```

It would be nice if there was a helper to do this.

``` go
client := github.NewTokenClient(ctx, token)
```


Discussion:
I don't see the harm. Go for it. 
Thank you, @icholy .
Please check out our CONTRIBUTING.md guide if you haven't already done so, and I look forward to your PR.
Maybe at the same time you might want to add a `github.NewTokenTransport` to address questions like:  https://github.com/google/go-github/issues/2631 ?
Sure, I'll open separate PRs though.
The oauth2 module doesn't expose a way to construct a transport, so the `NewTokenTransport` implementation would have to be something like:

``` go
func NewTokenTransport(ctx context.Context, token string) http.RoundTripper {
	return NewTokenClient(ctx, token).Client().Transport
}
```

> The oauth2 module doesn't expose a way to construct a transport, so the `NewTokenTransport` implementation would have to be something like:

Ah, then maybe it is not worth it.  Thanks.


But couldn't you just add a parameter for `Base` instead of `dbg.New` ?

```go
import (
  dbg "github.com/gmlewis/go-httpdebug/httpdebug"
  "github.com/google/go-github/v49/github"
  "golang.org/x/oauth2"
)
...
ctx := context.Background()
ts := oauth2.StaticTokenSource(
	&oauth2.Token{AccessToken: token},
)
tc := &oauth2.Transport{Source: ts, Base: dbg.New()}

client := github.NewClient(&http.Client{Transport: tc})
```
Something like:

```go
// NewTokenClientWithRoundTripper returns a new GitHub API client authenticated with the provided token and
// using the provided RoundTripper.
func NewTokenClientWithRoundTripper(token string, rt http.RoundTripper) *Client {
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := &oauth2.Transport{Source: ts, Base: rt}
	return github.NewClient(&http.Client{Transport: tc})
}
```
Users can already pass a transport in the context.

``` go
tr := /* user transport */
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{Transport: rt})
client :=  NewTokenClient(ctx, token)
```

edit: I thought that's why we kept the context parameter.
Ah!  Fantastic.  Thanks, @icholy - sorry for the noise.  Carry on.  :smile: 
Is it worth updating the test/examples to use `NewTokenClient` ?
Not a bad idea! 



Patch:
diff --git a/github/github.go b/github/github.go
index e97e31f2f5d..7d915dfa72e 100644
--- a/github/github.go
+++ b/github/github.go
@@ -24,6 +24,7 @@ import (
 	"time"
 
 	"github.com/google/go-querystring/query"
+	"golang.org/x/oauth2"
 )
 
 const (
@@ -346,6 +347,11 @@ func NewClient(httpClient *http.Client) *Client {
 	return c
 }
 
+// NewTokenClient returns a new GitHub API client authenticated with the provided token.
+func NewTokenClient(ctx context.Context, token string) *Client {
+	return NewClient(oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})))
+}
+
 // NewEnterpriseClient returns a new GitHub API client with provided
 // base URL and upload URL (often is your GitHub Enterprise hostname).
 // If the base URL does not have the suffix "/api/v3/", it will be added automatically.


Test patch:
diff --git a/github/github_test.go b/github/github_test.go
index 53809399fac..50ecd5435bc 100644
--- a/github/github_test.go
+++ b/github/github_test.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/google/go-cmp/cmp"
+	"golang.org/x/oauth2"
 )
 
 const (
@@ -266,6 +267,19 @@ func TestClient(t *testing.T) {
 	}
 }
 
+func TestNewTokenClient(t *testing.T) {
+	token := "gh_test_token"
+	ctx := context.Background()
+	c := NewTokenClient(ctx, token)
+	tr, ok := c.Client().Transport.(*oauth2.Transport)
+	if !ok {
+		t.Error("Client transport is not oauth2.Transport")
+	}
+	if tok, err := tr.Source.Token(); err != nil || tok.AccessToken != token {
+		t.Errorf("Client not using correct token")
+	}
+}
+
 func TestNewEnterpriseClient(t *testing.T) {
 	baseURL := "https://custom-url/api/v3/"
 	uploadURL := "https://custom-upload-url/api/uploads/"