diff --git a/flow/flow.go b/flow/flow.go index 78bf9e6..ce922c1 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "strconv" "strings" "github.com/sakajunquality/cloud-pubsub-events/gcrevent" @@ -15,18 +16,45 @@ var ( ) type Flow struct { - Env string - githubToken string + Env string + useApp bool + githubToken *string + githubAppID *int64 + githubAppInstlationID *int64 + githubAppPrivateKeyPath *string } func New(c *Config) (*Flow, error) { cfg = c - f := &Flow{ - githubToken: os.Getenv("FLOW_GITHUB_TOKEN"), + f := &Flow{} + + githubToken := os.Getenv("FLOW_GITHUB_TOKEN") + githubAppID := os.Getenv("FLOW_GITHUB_APP_ID") + githubAppInstlationID := os.Getenv("FLOW_GITHUB_APP_INSTALLATION_ID") + githubAppPrivateKeyPath := os.Getenv("FLOW_GITHUB_APP_PRIVATE_KEY_PATH") + + f.githubToken = &githubToken + + if githubAppID != "" { + f.useApp = true + + githubAppIDInt, err := strconv.ParseInt(githubAppID, 10, 64) + if err != nil { + return nil, errors.New("invalid value for FLOW_GITHUB_APP_ID") + } + f.githubAppID = &githubAppIDInt + + githubAppInstlationIDInt, err := strconv.ParseInt(githubAppInstlationID, 10, 64) + if err != nil { + return nil, errors.New("invalid value for FLOW_GITHUB_APP_INSTALLATION_ID") + } + f.githubAppInstlationID = &githubAppInstlationIDInt + + f.githubAppPrivateKeyPath = &githubAppPrivateKeyPath } - if f.githubToken == "" { - return nil, errors.New("you need to specify a non-empty value for FLOW_GITHUB_TOKEN") + if !f.useApp && f.githubToken == nil { + return nil, errors.New("you need to specify a non-empty value for FLOW_GITHUB_TOKEN if you don't specify FLOW_GITHUB_APP_ID") } return f, nil diff --git a/flow/process.go b/flow/process.go index 9d272e3..1864147 100644 --- a/flow/process.go +++ b/flow/process.go @@ -47,9 +47,16 @@ func (f *Flow) processImage(ctx context.Context, image, version string) error { return nil } +func (f *Flow) getGitbotClient(ctx context.Context) *github.Client { + if f.useApp { + return gitbot.NewGitHubClientWithApp(ctx, *f.githubAppID, *f.githubAppInstlationID, *f.githubAppPrivateKeyPath) + } + return gitbot.NewGitHubClient(ctx, *f.githubToken) +} + func (f *Flow) process(ctx context.Context, app *Application, version string) PullRequests { var prs PullRequests - client := gitbot.NewGitHubClient(ctx, f.githubToken) + client := f.getGitbotClient(ctx) for _, manifest := range app.Manifests { if !shouldProcess(manifest, version) { diff --git a/gitbot/client.go b/gitbot/client.go index bc1bb9d..1859ebf 100644 --- a/gitbot/client.go +++ b/gitbot/client.go @@ -2,7 +2,10 @@ package gitbot import ( "context" + "log" + "net/http" + "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v57/github" "golang.org/x/oauth2" @@ -13,3 +16,12 @@ func NewGitHubClient(ctx context.Context, token string) *github.Client { tc := oauth2.NewClient(ctx, ts) return github.NewClient(tc) } + +func NewGitHubClientWithApp(ctx context.Context, appID, installationID int64, privateKeyPath string) *github.Client { + tr := http.DefaultTransport + itr, err := ghinstallation.NewKeyFromFile(tr, appID, installationID, privateKeyPath) + if err != nil { + log.Fatal(err) + } + return github.NewClient(&http.Client{Transport: itr}) +} diff --git a/go.mod b/go.mod index 3f5b5f4..02bfb74 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/sakajunquality/flow/v4 require ( github.com/GoogleCloudPlatform/berglas v1.0.3 + github.com/bradleyfalzon/ghinstallation/v2 v2.10.0 github.com/dlclark/regexp2 v1.11.0 github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/render v1.0.3 @@ -26,8 +27,10 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-github/v60 v60.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/go.sum b/go.sum index eee748b..0296aff 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/GoogleCloudPlatform/berglas v1.0.3 h1:NjJYDz13vWct7+joxkBkIZhD6Cmwf5X github.com/GoogleCloudPlatform/berglas v1.0.3/go.mod h1:JBsGyi6Z5RwyHXMdEebok6MChukLE+dWXzPor2aeMtw= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/bradleyfalzon/ghinstallation/v2 v2.10.0 h1:XWuWBRFEpqVrHepQob9yPS3Xg4K3Wr9QCx4fu8HbUNg= +github.com/bradleyfalzon/ghinstallation/v2 v2.10.0/go.mod h1:qoGA4DxWPaYTgVCrmEspVSjlTu4WYAiSxMIhorMRXXc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -43,6 +45,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/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= @@ -70,6 +74,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/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs= github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw= +github.com/google/go-github/v60 v60.0.0 h1:oLG98PsLauFvvu4D/YPxq374jhSxFYdzQGNCyONLfn8= +github.com/google/go-github/v60 v60.0.0/go.mod h1:ByhX2dP9XT9o/ll2yXAu2VD8l5eNVg8hD4Cr0S/LmQk= 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/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=