diff --git a/go.mod b/go.mod index ae29b6df..1a059108 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/go-git/go-git/v6 v6.0.0-20250711134917-1f24ae85fe16 github.com/google/go-github/v69 v69.2.0 github.com/google/uuid v1.6.0 + github.com/hashicorp/go-retryablehttp v0.7.8 github.com/in-toto/attestation v1.1.2 github.com/maxbrunsfeld/counterfeiter/v6 v6.12.0 github.com/migueleliasweb/go-github-mock v1.4.0 @@ -99,7 +100,6 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.1-vault-7 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect diff --git a/pkg/auth/authenticator.go b/pkg/auth/authenticator.go index 4e0de3dd..f2888e21 100644 --- a/pkg/auth/authenticator.go +++ b/pkg/auth/authenticator.go @@ -14,6 +14,7 @@ import ( "github.com/fatih/color" "github.com/google/go-github/v69/github" + "github.com/hashicorp/go-retryablehttp" "github.com/slsa-framework/source-tool/pkg/sourcetool/models" ) @@ -132,7 +133,12 @@ func (a *Authenticator) GetGitHubClient() (*github.Client, error) { if token == "" { return nil, errors.New("token is empty") } - return github.NewClient(nil).WithAuthToken(token), nil + + rClient := retryablehttp.NewClient() + rClient.RetryMax = 3 + rClient.Logger = nil // Comment this line to monitor GH api calls + httpClient := rClient.StandardClient() + return github.NewClient(httpClient).WithAuthToken(token), nil } // WhoAmI returns the user authenticated with the token diff --git a/pkg/ghcontrol/connection.go b/pkg/ghcontrol/connection.go index bcc709e1..7a19b84b 100644 --- a/pkg/ghcontrol/connection.go +++ b/pkg/ghcontrol/connection.go @@ -9,6 +9,7 @@ import ( "os" "github.com/google/go-github/v69/github" + "github.com/hashicorp/go-retryablehttp" ) const tokenEnvVar = "GITHUB_TOKEN" //nolint:gosec // These are not credentials @@ -21,7 +22,11 @@ type GitHubConnection struct { } func NewGhConnection(owner, repo, ref string) *GitHubConnection { - return NewGhConnectionWithClient(owner, repo, ref, github.NewClient(nil)) + opts := defaultOptions + rClient := retryablehttp.NewClient() + rClient.RetryMax = int(opts.ApiRetries) + rClient.Logger = nil + return NewGhConnectionWithClient(owner, repo, ref, github.NewClient(rClient.StandardClient())) } func NewGhConnectionWithClient(owner, repo, ref string, client *github.Client) *GitHubConnection { diff --git a/pkg/ghcontrol/options.go b/pkg/ghcontrol/options.go index 484de303..a3c869a0 100644 --- a/pkg/ghcontrol/options.go +++ b/pkg/ghcontrol/options.go @@ -5,6 +5,7 @@ package ghcontrol var defaultOptions = Options{ AllowMergeCommits: false, + ApiRetries: 3, } type Options struct { @@ -14,4 +15,7 @@ type Options struct { // accessToken is the token we will use to connect to the GitHub API accessToken string + + // ApiRetries controls the number of time we retry calls to the GitHub API + ApiRetries uint8 }