diff --git a/internal/client/github.go b/internal/client/github.go index a4172818a..b309a152f 100644 --- a/internal/client/github.go +++ b/internal/client/github.go @@ -75,8 +75,15 @@ func (c *githubClient) checkRateLimit(ctx *context.Context) { return } sleep := limits.Core.Reset.UTC().Sub(time.Now().UTC()) + if sleep <= 0 { + // it seems that sometimes, after the rate limit just reset, it might + // still get <100 remaining and a reset time in the past... in such + // cases we can probably sleep a bit more before trying again... + sleep = 15 * time.Second + } log.Warnf("token too close to rate limiting, will sleep for %s before continuing...", sleep) time.Sleep(sleep) + c.checkRateLimit(ctx) } func (c *githubClient) GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error) { diff --git a/internal/client/github_test.go b/internal/client/github_test.go index 58b406557..fa1a8f0d3 100644 --- a/internal/client/github_test.go +++ b/internal/client/github_test.go @@ -8,6 +8,7 @@ import ( "net/http" "net/http/httptest" "os" + "sync/atomic" "testing" "text/template" "time" @@ -821,12 +822,21 @@ func TestGitHubCreateFileFeatureBranchDoesNotExist(t *testing.T) { func TestCheckRateLimit(t *testing.T) { now := time.Now().UTC() reset := now.Add(1392 * time.Millisecond) + var first atomic.Bool srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() if r.URL.Path == "/rate_limit" { w.WriteHeader(http.StatusOK) resetstr, _ := github.Timestamp{Time: reset}.MarshalJSON() + if first.Load() { + // second time asking for the rate limit + fmt.Fprintf(w, `{"resources":{"core":{"remaining":138,"reset":%s}}}`, string(resetstr)) + return + } + + // first time asking for the rate limit fmt.Fprintf(w, `{"resources":{"core":{"remaining":98,"reset":%s}}}`, string(resetstr)) + first.Store(true) return } t.Error("unhandled request: " + r.Method + " " + r.URL.Path)