diff --git a/example/otel/go.mod b/example/otel/go.mod index 59178f9b900..1b1cd44281d 100644 --- a/example/otel/go.mod +++ b/example/otel/go.mod @@ -1,11 +1,11 @@ -module github.com/google/go-github/v82/example/otel +module github.com/google/go-github/v81/example/otel go 1.24.0 require ( - github.com/google/go-github/v82 v82.0.0 - github.com/google/go-github/v82/otel v0.0.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 + github.com/google/go-github/v81 v81.0.0 + github.com/google/go-github/v81/otel v0.0.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 go.opentelemetry.io/otel/sdk v1.27.0 ) @@ -19,6 +19,6 @@ require ( golang.org/x/sys v0.39.0 // indirect ) -replace github.com/google/go-github/v82 => ../../ +replace github.com/google/go-github/v81 => ../../ -replace github.com/google/go-github/v82/otel => ../../otel +replace github.com/google/go-github/v81/otel => ../../otel diff --git a/example/otel/go.sum b/example/otel/go.sum index 6d1563c3d2c..e7517823d57 100644 --- a/example/otel/go.sum +++ b/example/otel/go.sum @@ -16,8 +16,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 h1:/0YaXu3755A/cFbtXp+21lkXgI0QE5avTWA2HjU9/WE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0/go.mod h1:m7SFxp0/7IxmJPLIY3JhOcU9CoFzDaCPL6xxQIxhA+o= go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= diff --git a/example/otel/main.go b/example/otel/main.go index 05dc4df4af4..ae0cf64506d 100644 --- a/example/otel/main.go +++ b/example/otel/main.go @@ -13,8 +13,8 @@ import ( "log" "net/http" - "github.com/google/go-github/v82/github" - "github.com/google/go-github/v82/otel" + "github.com/google/go-github/v81/github" + "github.com/google/go-github/v81/otel" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/sdk/trace" ) @@ -43,7 +43,6 @@ func main() { ), } - // Create GitHub client client := github.NewClient(httpClient) // Make a request (Get Rate Limits is public and cheap) diff --git a/example/otel/otel b/example/otel/otel new file mode 100755 index 00000000000..484721c0eb5 Binary files /dev/null and b/example/otel/otel differ diff --git a/github/github.go b/github/github.go index 490351d1343..319d07fc871 100644 --- a/github/github.go +++ b/github/github.go @@ -36,12 +36,12 @@ const ( defaultUserAgent = "go-github" + "/" + Version uploadBaseURL = "https://uploads.github.com/" - headerAPIVersion = "X-Github-Api-Version" - headerRateLimit = "X-Ratelimit-Limit" - headerRateRemaining = "X-Ratelimit-Remaining" - headerRateUsed = "X-Ratelimit-Used" + HeaderRateLimit = "X-Ratelimit-Limit" + HeaderRateRemaining = "X-Ratelimit-Remaining" + HeaderRateUsed = "X-Ratelimit-Used" HeaderRateReset = "X-Ratelimit-Reset" HeaderRateResource = "X-Ratelimit-Resource" + headerAPIVersion = "X-Github-Api-Version" headerOTP = "X-Github-Otp" headerRetryAfter = "Retry-After" @@ -785,13 +785,13 @@ func (r *Response) populatePageValues() { // parseRate parses the rate related headers. func parseRate(r *http.Response) Rate { var rate Rate - if limit := r.Header.Get(headerRateLimit); limit != "" { + if limit := r.Header.Get(HeaderRateLimit); limit != "" { rate.Limit, _ = strconv.Atoi(limit) } - if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + if remaining := r.Header.Get(HeaderRateRemaining); remaining != "" { rate.Remaining, _ = strconv.Atoi(remaining) } - if used := r.Header.Get(headerRateUsed); used != "" { + if used := r.Header.Get(HeaderRateUsed); used != "" { rate.Used, _ = strconv.Atoi(used) } if reset := r.Header.Get(HeaderRateReset); reset != "" { @@ -1451,10 +1451,7 @@ func CheckResponse(r *http.Response) error { switch { case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): return (*TwoFactorAuthError)(errorResponse) - // Primary rate limit exceeded: GitHub returns 403 or 429 with X-RateLimit-Remaining: 0 - // See: https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api - case (r.StatusCode == http.StatusForbidden || r.StatusCode == http.StatusTooManyRequests) && - r.Header.Get(headerRateRemaining) == "0": + case r.StatusCode == http.StatusForbidden && r.Header.Get(HeaderRateRemaining) == "0": return &RateLimitError{ Rate: parseRate(r), Response: errorResponse.Response, diff --git a/github/github_test.go b/github/github_test.go index 8cffb7f7ef6..7ce660dd177 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -1230,9 +1230,9 @@ func TestDo_rateLimit(t *testing.T) { client, mux, _ := setup(t) mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "59") - w.Header().Set(headerRateUsed, "1") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "59") + w.Header().Set(HeaderRateUsed, "1") w.Header().Set(HeaderRateReset, "1372700873") w.Header().Set(HeaderRateResource, "core") }) @@ -1349,9 +1349,9 @@ func TestDo_rateLimit_errorResponse(t *testing.T) { client, mux, _ := setup(t) mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "59") - w.Header().Set(headerRateUsed, "1") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "59") + w.Header().Set(HeaderRateUsed, "1") w.Header().Set(HeaderRateReset, "1372700873") w.Header().Set(HeaderRateResource, "core") http.Error(w, "Bad Request", 400) @@ -1390,9 +1390,9 @@ func TestDo_rateLimit_rateLimitError(t *testing.T) { client, mux, _ := setup(t) mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, "1372700873") w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1440,9 +1440,9 @@ func TestDo_rateLimit_noNetworkCall(t *testing.T) { reset := time.Now().UTC().Add(time.Minute).Round(time.Second) // Rate reset is a minute from now, with 1 second precision. mux.HandleFunc("/first", func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1508,9 +1508,9 @@ func TestDo_rateLimit_ignoredFromCache(t *testing.T) { // By adding the X-From-Cache header we pretend this is served from a cache. mux.HandleFunc("/first", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("X-From-Cache", "1") - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1556,9 +1556,9 @@ func TestDo_rateLimit_sleepUntilResponseResetLimit(t *testing.T) { mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { if firstRequest { firstRequest = false - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1569,9 +1569,9 @@ func TestDo_rateLimit_sleepUntilResponseResetLimit(t *testing.T) { }`) return } - w.Header().Set(headerRateLimit, "5000") - w.Header().Set(headerRateRemaining, "5000") - w.Header().Set(headerRateUsed, "0") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1600,9 +1600,9 @@ func TestDo_rateLimit_sleepUntilResponseResetLimitRetryOnce(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1634,9 +1634,9 @@ func TestDo_rateLimit_sleepUntilClientResetLimit(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "5000") - w.Header().Set(headerRateRemaining, "5000") - w.Header().Set(headerRateUsed, "0") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1667,9 +1667,9 @@ func TestDo_rateLimit_abortSleepContextCancelled(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "60") - w.Header().Set(headerRateRemaining, "0") - w.Header().Set(headerRateUsed, "60") + w.Header().Set(HeaderRateLimit, "60") + w.Header().Set(HeaderRateRemaining, "0") + w.Header().Set(HeaderRateUsed, "60") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1702,9 +1702,9 @@ func TestDo_rateLimit_abortSleepContextCancelledClientLimit(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "5000") - w.Header().Set(headerRateRemaining, "5000") - w.Header().Set(headerRateUsed, "0") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1858,7 +1858,7 @@ func TestDo_rateLimit_abuseRateLimitError_xRateLimitReset(t *testing.T) { mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set(HeaderRateReset, strconv.Itoa(int(blockUntil))) - w.Header().Set(headerRateRemaining, "1") // set remaining to a value > 0 to distinct from a primary rate limit + w.Header().Set(HeaderRateRemaining, "1") // set remaining to a value > 0 to distinct from a primary rate limit w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, `{ "message": "You have triggered an abuse detection mechanism ...", @@ -1917,7 +1917,7 @@ func TestDo_rateLimit_abuseRateLimitError_maxDuration(t *testing.T) { mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set(HeaderRateReset, strconv.Itoa(int(blockUntil))) - w.Header().Set(headerRateRemaining, "1") // set remaining to a value > 0 to distinct from a primary rate limit + w.Header().Set(HeaderRateRemaining, "1") // set remaining to a value > 0 to distinct from a primary rate limit w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, `{ "message": "You have triggered an abuse detection mechanism ...", @@ -1956,9 +1956,14 @@ func TestDo_rateLimit_disableRateLimitCheck(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "5000") - w.Header().Set(headerRateRemaining, "5000") - w.Header().Set(headerRateUsed, "0") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") + w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) + w.Header().Set(HeaderRateResource, "core") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -1992,9 +1997,9 @@ func TestDo_rateLimit_bypassRateLimitCheck(t *testing.T) { requestCount := 0 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { requestCount++ - w.Header().Set(headerRateLimit, "5000") - w.Header().Set(headerRateRemaining, "5000") - w.Header().Set(headerRateUsed, "0") + w.Header().Set(HeaderRateLimit, "5000") + w.Header().Set(HeaderRateRemaining, "5000") + w.Header().Set(HeaderRateUsed, "0") w.Header().Set(HeaderRateReset, fmt.Sprint(reset.Add(time.Hour).Unix())) w.Header().Set(HeaderRateResource, "core") w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -2135,9 +2140,9 @@ func TestCheckResponse_RateLimit(t *testing.T) { Body: io.NopCloser(strings.NewReader(`{"message":"m", "documentation_url": "url"}`)), } - res.Header.Set(headerRateLimit, "60") - res.Header.Set(headerRateRemaining, "0") - res.Header.Set(headerRateUsed, "1") + res.Header.Set(HeaderRateLimit, "60") + res.Header.Set(HeaderRateRemaining, "0") + res.Header.Set(HeaderRateUsed, "1") res.Header.Set(HeaderRateReset, "243424") res.Header.Set(HeaderRateResource, "core") diff --git a/otel/go.mod b/otel/go.mod index 7f98b378b84..ef7ca64e6d7 100644 --- a/otel/go.mod +++ b/otel/go.mod @@ -1,9 +1,9 @@ -module github.com/google/go-github/v82/otel +module github.com/google/go-github/v81/otel go 1.24.0 require ( - github.com/google/go-github/v82 v82.0.0 + github.com/google/go-github/v81 v81.0.0 go.opentelemetry.io/otel v1.27.0 go.opentelemetry.io/otel/metric v1.27.0 go.opentelemetry.io/otel/sdk v1.27.0 @@ -17,4 +17,4 @@ require ( golang.org/x/sys v0.39.0 // indirect ) -replace github.com/google/go-github/v82 => ../ +replace github.com/google/go-github/v81 => ../ diff --git a/otel/transport.go b/otel/transport.go index 45a9f69ae73..f6e1d41ba2f 100644 --- a/otel/transport.go +++ b/otel/transport.go @@ -11,7 +11,7 @@ import ( "net/http" "strconv" - "github.com/google/go-github/v82/github" + "github.com/google/go-github/v81/github" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -80,12 +80,12 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { // Capture response attributes span.SetAttributes(attribute.Int("http.status_code", resp.StatusCode)) // Capture GitHub Specifics - if limit := resp.Header.Get("X-Ratelimit-Limit"); limit != "" { + if limit := resp.Header.Get(github.HeaderRateLimit); limit != "" { if v, err := strconv.Atoi(limit); err == nil { span.SetAttributes(attribute.Int("github.rate_limit.limit", v)) } } - if remaining := resp.Header.Get("X-Ratelimit-Remaining"); remaining != "" { + if remaining := resp.Header.Get(github.HeaderRateRemaining); remaining != "" { if v, err := strconv.Atoi(remaining); err == nil { span.SetAttributes(attribute.Int("github.rate_limit.remaining", v)) } diff --git a/otel/transport_test.go b/otel/transport_test.go index c005691490a..ab5b1fae911 100644 --- a/otel/transport_test.go +++ b/otel/transport_test.go @@ -11,7 +11,7 @@ import ( "net/http/httptest" "testing" - "github.com/google/go-github/v82/github" + "github.com/google/go-github/v81/github" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -57,8 +57,8 @@ func TestRoundTrip_Spans(t *testing.T) { // Setup Headers headers := http.Header{} - headers.Set("X-Ratelimit-Limit", "5000") - headers.Set("X-Ratelimit-Remaining", "4999") + headers.Set(github.HeaderRateLimit, "5000") + headers.Set(github.HeaderRateRemaining, "4999") headers.Set(github.HeaderRateReset, "1372700873") headers.Set("X-Github-Request-Id", "1234-5678") headers.Set(github.HeaderRateResource, "core")