diff --git a/go.mod b/go.mod index cc5da72b..330996c4 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( cloud.google.com/go/storage v1.50.0 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.25.0 github.com/avvmoto/buf-readerat v0.0.0-20171115124131-a17c8cb89270 + github.com/bradleyfalzon/ghinstallation/v2 v2.13.0 github.com/chainguard-dev/clog v1.5.1 github.com/cloudevents/sdk-go/v2 v2.15.2 github.com/coreos/go-oidc/v3 v3.12.0 @@ -74,8 +75,10 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/flatbuffers v23.5.26+incompatible // indirect + github.com/google/go-github/v68 v68.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/s2a-go v0.1.8 // indirect diff --git a/go.sum b/go.sum index 707b1025..903136f1 100644 --- a/go.sum +++ b/go.sum @@ -105,6 +105,8 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradleyfalzon/ghinstallation/v2 v2.13.0 h1:5FhjW93/YLQJDmPdeyMPw7IjAPzqsr+0jHPfrPz0sZI= +github.com/bradleyfalzon/ghinstallation/v2 v2.13.0/go.mod h1:EJ6fgedVEHa2kUyBTTvslJCXJafS/mhJNNKEOCspZXQ= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -170,6 +172,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -202,6 +206,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go= github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY= +github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= +github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-replayers/grpcreplay v1.3.0 h1:1Keyy0m1sIpqstQmgz307zhiJ1pV4uIlFds5weTmxbo= diff --git a/modules/github-bots/sdk/github.go b/modules/github-bots/sdk/github.go index ae28873c..22b7c029 100644 --- a/modules/github-bots/sdk/github.go +++ b/modules/github-bots/sdk/github.go @@ -14,6 +14,7 @@ import ( "time" bufra "github.com/avvmoto/buf-readerat" + "github.com/bradleyfalzon/ghinstallation/v2" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" @@ -53,6 +54,46 @@ func NewGitHubClient(ctx context.Context, org, repo, policyName string, opts ... return client } +type installationTokenSource struct { + ctx context.Context + transport *ghinstallation.Transport +} + +func (ts *installationTokenSource) Token() (*oauth2.Token, error) { + token, err := ts.transport.Token(ts.ctx) + if err != nil { + return nil, fmt.Errorf("failed to get token: %w", err) + } + expiry, _, err := ts.transport.Expiry() + if err != nil { + return nil, fmt.Errorf("failed to get token expiry: %w", err) + } + return &oauth2.Token{ + AccessToken: token, + Expiry: expiry, + }, nil +} + +func NewInstallationClient(ctx context.Context, org, repo string, tr *ghinstallation.Transport, opts ...GitHubClientOption) GitHubClient { + ts := oauth2.ReuseTokenSource(nil, &installationTokenSource{ + ctx: ctx, + transport: tr, + }) + client := GitHubClient{ + inner: github.NewClient(&http.Client{Transport: tr}), + ts: ts, + bufSize: 1024 * 1024, // 1MB buffer for requests + org: org, + repo: repo, + } + + for _, opt := range opts { + opt(&client) + } + + return client +} + type tokenSource struct { org, repo, policyName, tok string } @@ -506,7 +547,8 @@ func (c GitHubClient) CloneRepo(ctx context.Context, ref, destDir string) (*git. repo := fmt.Sprintf("https://github.com/%s/%s.git", c.org, c.repo) auth := &gitHttp.BasicAuth{ - Username: "notchecked", // username is not checked, only the token in the password field is used. + // https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation#about-authentication-as-a-github-app-installation + Username: "x-access-token", Password: tok.AccessToken, }