From 0d5a8d9fada19f10b80a63035a84399ba7d3f5fb Mon Sep 17 00:00:00 2001 From: Gautam Korlam Date: Wed, 9 Apr 2025 02:26:17 -0700 Subject: [PATCH] Update to use github app for auth --- README.md | 20 ++++++------------ cmd/gitops-actions/main.go | 3 --- internal/git/client.go | 27 ++++++++++-------------- internal/github/client.go | 43 +++++++++----------------------------- 4 files changed, 27 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 4d4bf10..9ec90a7 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,9 @@ steps: TARGET_STACK: # If specified, will only run deployments for the specified stack (optional) GLOBAL_CONFIG: # Path to the global gitops config (optional if app config is provided) VALUE: # Value to update the files in the config repository (required) - GH_TOKEN: # Github PAT with proper permissions (optional if GH_APP_KEY is provided) - GH_APP_KEY: # Github App private key (optional if GH_TOKEN is provided) - GH_APP_ID: # Github App ID (optional if GH_TOKEN is provided) - GH_APP_INSTALLATION_ID: # Github App Installation ID (optional if GH_TOKEN is provided) + GH_APP_KEY: # Github App private key + GH_APP_ID: # Github App ID + GH_APP_INSTALLATION_ID: # Github App Installation ID GIT_COMMIT_AUTHOR_NAME: # Name of the commit author (optional) GIT_COMMIT_AUTHOR_EMAIL: # Email of the commit author (optional) PR_TITLE: # Title of the PR in the config repository (optional) @@ -330,16 +329,12 @@ jobs: run: | echo "service=$(echo ${{ matrix.service-path }} | sed 's/services\///g')" >> "${GITHUB_OUTPUT}" - - id: create_token - uses: tibdex/github-app-token@v2 - with: - app_id: 12345 - private_key: ${{ secrets.PRIVATE_KEY }} - - name: Deploy uses: docker://ghcr.io/geode-io/gitops-tools:latest env: - GH_TOKEN: ${{ steps.create_token.outputs.token }} + GH_APP_KEY: # Github App private key + GH_APP_ID: # Github App ID + GH_APP_INSTALLATION_ID: # Github App Installation ID APP_NAME: ${{ steps.service-name.outputs.service }} APP_CONFIG: ${{ matrix.service-path }}/gitops-actions.yaml # load the service specific config if exists TARGET_STACK: dev # if you want to deploy to a specific stack @@ -347,6 +342,3 @@ jobs: GLOBAL_CONFIG: gitops-actions.yaml GIT_COMMIT_AUTHOR_NAME: "geode-actions-bot" ``` - -> [!TIP] -> It is recommended to use a Github App to authenticate with Github API. You can use the `tibdex/github-app-token` action to create a token for the Github App and use it in the action. diff --git a/cmd/gitops-actions/main.go b/cmd/gitops-actions/main.go index 62bccdb..ac25e9d 100644 --- a/cmd/gitops-actions/main.go +++ b/cmd/gitops-actions/main.go @@ -21,7 +21,6 @@ func main() { appConfig := kingpin.Flag("app-config", "Path to the gitops app config file. required if app-name is not provided").Envar("APP_CONFIG").String() value := kingpin.Flag("value", "Value to update in the config files").Required().Envar("VALUE").String() targetStack := kingpin.Flag("target-stack", "Target stack to update").Envar("TARGET_STACK").String() - ghToken := kingpin.Flag("gh-token", "Github Token for git and Github operations").Envar("GH_TOKEN").String() ghAppKey := kingpin.Flag("gh-app-key", "Github App Key for Github operations").Envar("GH_APP_KEY").String() ghAppId := kingpin.Flag("gh-app-id", "Github App ID for Github operations").Envar("GH_APP_ID").Int64() ghAppInstallationId := kingpin.Flag("gh-app-installation-id", "Github App Installation ID for Github operations").Envar("GH_APP_INSTALLATION_ID").Int64() @@ -53,7 +52,6 @@ func main() { actions.Infof("initializing git client ...") git, err := git.NewClient(&git.ClientOpts{ - Token: *ghToken, AppKey: *ghAppKey, AppId: *ghAppId, AppInstallationId: *ghAppInstallationId, @@ -66,7 +64,6 @@ func main() { actions.Infof("initializing github client ...") gh, err := github.NewClient(&github.ClientOpts{ - Token: *ghToken, AppKey: *ghAppKey, AppId: *ghAppId, AppInstallationId: *ghAppInstallationId, diff --git a/internal/git/client.go b/internal/git/client.go index 7c46090..29e4637 100644 --- a/internal/git/client.go +++ b/internal/git/client.go @@ -9,7 +9,7 @@ import ( ) type ClientOpts struct { - Token, AppKey string + AppKey string AppId, AppInstallationId int64 AuthorName, AuthorEmail string } @@ -41,21 +41,16 @@ func NewClient(opts *ClientOpts) (*Client, error) { authorName: opts.AuthorName, authorEmail: opts.AuthorEmail, } - token := opts.Token - if token == "" { - client.authMethod = "app" - client.ctx = context.Background() - itr, err := ghinstallation.NewKeyFromFile(net.DefaultTransport, opts.AppId, opts.AppInstallationId, opts.AppKey) - if err != nil { - return nil, err - } - client.itr = itr - token, err = itr.Token(client.ctx) - if err != nil { - return nil, err - } - } else { - client.authMethod = "token" + client.authMethod = "app" + client.ctx = context.Background() + itr, err := ghinstallation.New(net.DefaultTransport, opts.AppId, opts.AppInstallationId, []byte(opts.AppKey)) + if err != nil { + return nil, err + } + client.itr = itr + token, err := itr.Token(client.ctx) + if err != nil { + return nil, err } client.auth = &http.BasicAuth{ Username: "gitops-actions", diff --git a/internal/github/client.go b/internal/github/client.go index e5d07af..6490e25 100644 --- a/internal/github/client.go +++ b/internal/github/client.go @@ -2,7 +2,6 @@ package github import ( "context" - "fmt" "net/http" "time" @@ -10,7 +9,6 @@ import ( "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v61/github" - "golang.org/x/oauth2" ) var ( @@ -23,7 +21,7 @@ type Client struct { } type ClientOpts struct { - Token, AppKey string + AppKey string AppId, AppInstallationId int64 } @@ -31,17 +29,9 @@ func NewClient(opts *ClientOpts) (*Client, error) { var err error ctx := context.Background() client := github.NewClient(nil) - - if opts.Token != "" { - client, err = GetGHClient(opts, ctx, "pat") - if err != nil { - return nil, err - } - } else { - client, err = GetGHClient(opts, ctx, "app") - if err != nil { - return nil, err - } + client, err = GetGHClient(opts, ctx) + if err != nil { + return nil, err } c := &Client{ Client: client, @@ -56,26 +46,13 @@ func NewClient(opts *ClientOpts) (*Client, error) { return c, nil } -func GetGHClient(opts *ClientOpts, ctx context.Context, clientType string) (*github.Client, error) { - switch clientType { - case "pat": - ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: opts.Token}, - ) - tc := oauth2.NewClient(ctx, ts) - client := github.NewClient(tc) - return client, nil - case "app": - itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, opts.AppId, opts.AppInstallationId, opts.AppKey) - if err != nil { - return nil, err - } - client := github.NewClient(&http.Client{Transport: itr}) - return client, nil - +func GetGHClient(opts *ClientOpts, ctx context.Context) (*github.Client, error) { + itr, err := ghinstallation.New(http.DefaultTransport, opts.AppId, opts.AppInstallationId, []byte(opts.AppKey)) + if err != nil { + return nil, err } - return nil, fmt.Errorf("invalid client type") + client := github.NewClient(&http.Client{Transport: itr}) + return client, nil } func (c *Client) CheckRateLimit() error {