cmd/watchflakes: use github.NewClient API

Thanks to Russ for adding it.

For golang/go#65353.

Change-Id: Ie8aa589ade3e076c6a0c1dcf6776dc85a8a3aec2
Reviewed-on: https://go-review.googlesource.com/c/build/+/580016
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/cmd/watchflakes/github.go b/cmd/watchflakes/github.go
index 1e33f1f..938b0f8 100644
--- a/cmd/watchflakes/github.go
+++ b/cmd/watchflakes/github.go
@@ -7,9 +7,7 @@
 import (
 	"fmt"
 	"log"
-	"net/http"
 	"regexp"
-	"runtime"
 	"sort"
 	"strings"
 
@@ -377,34 +375,3 @@
 	}
 	return gh.AddIssueComment(issue.Issue, body+signature)
 }
-
-// defaultTransportWithRSCIOGitHubAuth is an http.RoundTripper
-// that implements authentication for the rsc.io/github.Client
-// type, but otherwise defers to http.DefaultTransport.
-//
-// It's brittle and exists only until there's a better API for
-// providing an *http.Client to the rsc.io/github package.
-type defaultTransportWithRSCIOGitHubAuth struct {
-	GitHubToken interface{ SetAuthHeader(*http.Request) }
-}
-
-func (t defaultTransportWithRSCIOGitHubAuth) RoundTrip(req *http.Request) (*http.Response, error) {
-	if req.URL.Host == "api.github.com" && req.URL.Scheme == "https" {
-		if req.Host != "api.github.com" {
-			return nil, fmt.Errorf("internal error: req.Host is %q, want api.github.com", req.Host)
-		}
-		// Confirm that the caller is the expected method of rsc.io/github.Client.
-		//
-		// Note: This is brittle and not great. But it works for now, and will go
-		// away after we can pass a custom *http.Client to github.Client directly.
-		var pc = make([]uintptr, 1)
-		if n := runtime.Callers(6, pc); n == 0 {
-			return nil, fmt.Errorf("internal error: unknown caller")
-		} else if f, _ := runtime.CallersFrames(pc).Next(); f.Function != "rsc.io/github.(*Client).graphQL" {
-			return nil, fmt.Errorf("internal error: caller is %q, want rsc.io/github", f.Function)
-		}
-		req = req.Clone(req.Context())
-		t.GitHubToken.SetAuthHeader(req)
-	}
-	return http.DefaultTransport.RoundTrip(req)
-}
diff --git a/cmd/watchflakes/github_test.go b/cmd/watchflakes/github_test.go
deleted file mode 100644
index 431e916..0000000
--- a/cmd/watchflakes/github_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"net/http"
-	"reflect"
-	"strings"
-	"testing"
-
-	"golang.org/x/oauth2"
-	"rsc.io/github"
-)
-
-func TestDefaultTransportWithRSCIOGitHubAuth(t *testing.T) {
-	if testing.Short() {
-		t.Skip("not running test that uses internet in short mode")
-	}
-
-	if !reflect.ValueOf(*http.DefaultClient).IsZero() {
-		t.Fatal("internal error: the initial value of *http.DefaultClient is unexpectedly non-zero")
-	}
-	http.DefaultClient.Transport = defaultTransportWithRSCIOGitHubAuth{
-		GitHubToken: &oauth2.Token{AccessToken: "pretend-token"},
-	}
-	t.Cleanup(func() { http.DefaultClient.Transport = nil })
-	gh := new(github.Client)
-
-	_, err := gh.GraphQLQuery(`query { viewer { login } }`, nil)
-	if err == nil {
-		t.Fatal("GraphQLQuery returned nil error, want non-nil error")
-	} else if got, wantPrefix := err.Error(), "401 Unauthorized"; !strings.HasPrefix(got, wantPrefix) {
-		t.Fatalf("GraphQLQuery returned %v, want prefix %v", got, wantPrefix)
-	}
-}
diff --git a/cmd/watchflakes/main.go b/cmd/watchflakes/main.go
index d21b684..9f02b5f 100644
--- a/cmd/watchflakes/main.go
+++ b/cmd/watchflakes/main.go
@@ -11,9 +11,7 @@
 	"flag"
 	"fmt"
 	"log"
-	"net/http"
 	"os"
-	"reflect"
 	"runtime"
 	"strings"
 	"time"
@@ -23,7 +21,6 @@
 	"golang.org/x/build/buildenv"
 	"golang.org/x/build/cmd/watchflakes/internal/script"
 	"golang.org/x/build/internal/secret"
-	"golang.org/x/oauth2"
 	"rsc.io/github"
 )
 
@@ -82,16 +79,7 @@
 		if err != nil {
 			log.Fatalln("failed to retrieve GitHub token from Secret Manager:", err)
 		}
-		// TODO: Use a better API for providing authentication to github.Client, after it's available.
-		// For now, rely on the fact this is package main and we don't expect any of our dependencies
-		// to modify http.DefaultClient (or to access it concurrently).
-		if !reflect.ValueOf(*http.DefaultClient).IsZero() {
-			log.Fatalln("internal error: the initial value of *http.DefaultClient is unexpectedly non-zero")
-		}
-		http.DefaultClient.Transport = defaultTransportWithRSCIOGitHubAuth{
-			GitHubToken: &oauth2.Token{AccessToken: ghToken},
-		}
-		gh = new(github.Client)
+		gh = github.NewClient(ghToken)
 	} else {
 		// Use credentials in $HOME/.netrc.
 		var err error
diff --git a/go.mod b/go.mod
index af4c651..cf8616e 100644
--- a/go.mod
+++ b/go.mod
@@ -71,7 +71,7 @@
 	google.golang.org/grpc v1.59.0
 	google.golang.org/protobuf v1.31.0
 	gopkg.in/inf.v0 v0.9.1
-	rsc.io/github v0.3.0
+	rsc.io/github v0.3.1-0.20240418182958-01bebb0c456a
 	rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef
 )
 
diff --git a/go.sum b/go.sum
index 2fc1dca..8ee049f 100644
--- a/go.sum
+++ b/go.sum
@@ -1446,8 +1446,8 @@
 modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
 modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/github v0.3.0 h1:SxddQ4yzzaxyZGbyfaXP0qeqp2VLgFdvJs60bWqCV4w=
-rsc.io/github v0.3.0/go.mod h1:sfdP6cCYDjTBOwHSu579zk9KnSkyBCryjecSeffMKXs=
+rsc.io/github v0.3.1-0.20240418182958-01bebb0c456a h1:nL7IfptuTYRttdK05UjWL6zvtx26DMIX403ypCrWai8=
+rsc.io/github v0.3.1-0.20240418182958-01bebb0c456a/go.mod h1:sfdP6cCYDjTBOwHSu579zk9KnSkyBCryjecSeffMKXs=
 rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
 rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
 rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=