Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for github app auth #288

Merged
merged 13 commits into from
Nov 13, 2024
Merged

add support for github app auth #288

merged 13 commits into from
Nov 13, 2024

Conversation

djeebus
Copy link
Collaborator

@djeebus djeebus commented Oct 1, 2024

Closes #247. Builds on top of #249. Also gracefully handles missing comment permissions

Adds the following env vars:

Env Var Description Default Value
KUBECHECKS_GITHUB_APP_ID Github App ID. 0
KUBECHECKS_GITHUB_INSTALLATION_ID Github Installation ID. 0
KUBECHECKS_GITHUB_PRIVATE_KEY Github App Private Key.
KUBECHECKS_VCS_EMAIL VCS Email.
KUBECHECKS_VCS_USERNAME VCS Username.

In order to use app auth, you'll need to set APP_ID, INSTALLATION_ID, and PRIVATE_KEY. Github apps don't have usernames or emails, so we'll default those to "kubechecks" and "kubechecks@zapier.com". If you don't want those values, you can override them via VCS_EMAIL and VCS_USERNAME. These will also work if you use a gitlab or github token, but they're not required.

Copy link

github-actions bot commented Oct 1, 2024

Temporary image deleted.

@DrFaust92
Copy link
Contributor

Hi, any news on merging this?

# Conflicts:
#	.github/actions/build-image/action.yaml
#	docs/usage.md
@zapier-sre-bot
Copy link
Collaborator

Mergecat's Review

Click to read mergecats review!

😼 Mergecat review of .github/actions/build-image/action.yaml

@@ -44,7 +44,7 @@ runs:
 
     - name: Build and push the Docker image
       shell: bash
-      run: >-       
+      run: >-
         ./earthly.sh 
         ${{ inputs.push == 'true' && '--push' || '' }} 
         +docker-multiarch

Feedback & Suggestions: The change in the diff is a minor formatting adjustment, removing trailing spaces. While this change does not affect functionality, it is a good practice to remove unnecessary whitespace for cleaner code. However, ensure that this change does not affect any formatting-sensitive tools or scripts that might rely on the exact formatting of the file. 🧹✨


😼 Mergecat review of pkg/vcs/types.go

 // Client represents a VCS client
 type Client interface {
 	// PostMessage takes in project name in form "owner/repo" (ie zapier/kubechecks), the PR/MR id, and the actual message
-	PostMessage(context.Context, PullRequest, string) *msg.Message
+	PostMessage(context.Context, PullRequest, string) (*msg.Message, error)
 	// UpdateMessage update a message with new content
 	UpdateMessage(context.Context, *msg.Message, string) error
 	// VerifyHook validates a webhook secret and return the body; must be called even if no secret

Feedback & Suggestions:

  1. Error Handling: 👍 The change to return an error alongside *msg.Message in PostMessage is a good improvement. It allows the caller to handle potential errors that may occur during the execution of this method. Ensure that all implementations of this interface are updated to handle and return errors appropriately.

  2. Documentation Update: 📝 Consider updating the comment for PostMessage to reflect the new return type. This will help maintain clarity and ensure that the documentation is consistent with the code.


😼 Mergecat review of pkg/config/config.go

@@ -33,11 +33,18 @@ type ServerConfig struct {
 	OtelCollectorPort string `mapstructure:"otel-collector-port"`
 
 	// vcs
+	VcsUsername  string `mapstructure:"vcs-username"`
+	VcsEmail     string `mapstructure:"vcs-email"`
 	VcsBaseUrl   string `mapstructure:"vcs-base-url"`
 	VcsUploadUrl string `mapstructure:"vcs-upload-url"` // github enterprise upload URL
 	VcsToken     string `mapstructure:"vcs-token"`
 	VcsType      string `mapstructure:"vcs-type"`
 
+	//github
+	GithubPrivateKey     string `mapstructure:"github-private-key"`
+	GithubAppID          int64  `mapstructure:"github-app-id"`
+	GithubInstallationID int64  `mapstructure:"github-installation-id"`
+
 	// webhooks
 	EnsureWebhooks bool   `mapstructure:"ensure-webhooks"`
 	WebhookSecret  string `mapstructure:"webhook-secret"`

Feedback & Suggestions:

  1. Sensitive Data Handling:

    • The addition of GithubPrivateKey and VcsToken fields suggests handling sensitive data. Ensure these fields are securely managed and not logged or exposed inadvertently. Consider using environment variables or a secure vault for these values. 🔒
  2. Validation:

    • It might be beneficial to add validation for the new fields, such as checking if VcsEmail is a valid email format or ensuring GithubAppID and GithubInstallationID are positive integers. This can prevent potential misconfigurations. ✅
  3. Documentation:

    • Ensure that the new fields are well-documented, both in code comments and any external documentation, to help other developers understand their purpose and usage. 📚
  4. Consistency:

    • Ensure that the naming conventions are consistent across the configuration fields. For example, consider whether VcsUsername and VcsEmail should follow the same naming pattern as other fields like VcsBaseUrl. 🤔

😼 Mergecat review of go.mod

@@ -12,6 +12,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/eks v1.46.0
 	github.com/aws/aws-sdk-go-v2/service/sts v1.30.1
 	github.com/aws/smithy-go v1.20.3
+	github.com/bradleyfalzon/ghinstallation/v2 v2.6.0
 	github.com/cenkalti/backoff/v4 v4.3.0
 	github.com/chainguard-dev/git-urls v1.0.2
 	github.com/creasty/defaults v1.7.0
@@ -105,7 +106,6 @@ require (
 	github.com/blang/semver/v4 v4.0.0 // indirect
 	github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
 	github.com/bombsimon/logrusr/v2 v2.0.1 // indirect
-	github.com/bradleyfalzon/ghinstallation/v2 v2.6.0 // indirect
 	github.com/bufbuild/protocompile v0.6.0 // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/chai2010/gettext-go v1.0.2 // indirect

Feedback & Suggestions:

  1. Dependency Management: The change moves github.com/bradleyfalzon/ghinstallation/v2 v2.6.0 from an indirect dependency to a direct one. Ensure that this package is indeed required directly by your codebase. If it is not directly used, it should remain as an indirect dependency to avoid unnecessary clutter in the require section.

  2. Version Consistency: Double-check that the version v2.6.0 is the correct and intended version for your project. If there are newer versions available, consider whether an update is beneficial or necessary.

  3. Documentation: If this change is intentional and the package is now directly used, update any relevant documentation or comments in your codebase to reflect this new dependency.


😼 Mergecat review of pkg/vcs/gitlab_client/message.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
 	"github.com/xanzy/go-gitlab"
 
@@ -16,8 +17,8 @@ import (
 
 const MaxCommentLength = 1_000_000
 
-func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message string) *msg.Message {
-	_, span := tracer.Start(ctx, "PostMessageToMergeRequest")
+func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message string) (*msg.Message, error) {
+	_, span := tracer.Start(ctx, "PostMessage")
 	defer span.End()
 
 	if len(message) > MaxCommentLength {
@@ -32,10 +33,10 @@ func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message st
 		})
 	if err != nil {
 		telemetry.SetError(span, err, "Create Merge Request Note")
-		log.Error().Err(err).Msg("could not post message to MR")
+		return nil, errors.Wrap(err, "could not post message to MR")
 	}
 
-	return msg.NewMessage(pr.FullName, pr.CheckID, n.ID, c)
+	return msg.NewMessage(pr.FullName, pr.CheckID, n.ID, c), nil
 }
 
 func (c *Client) hideOutdatedMessages(ctx context.Context, projectName string, mergeRequestID int, notes []*gitlab.Note) error {

Feedback & Suggestions:

  1. Error Handling Improvement: The change to return an error from PostMessage is a good improvement for error handling. However, ensure that all calling functions are updated to handle this new error return value properly. This will prevent any potential runtime errors due to unhandled nil pointers.

  2. Error Wrapping: The use of errors.Wrap is a great addition for providing more context to errors. This can be very helpful for debugging. Just make sure that the error messages are consistent and informative across the codebase.

  3. Tracer Span Naming: The change from "PostMessageToMergeRequest" to "PostMessage" in the tracer span name is a simplification. Ensure that this change aligns with your tracing and logging conventions, and that it doesn't cause any confusion or loss of specificity in tracing logs.

  4. Function Signature Change: The change in the function signature of PostMessage to return an error is a breaking change. Ensure that all usages of this function are updated accordingly to handle the new return type.

Overall, these changes improve error handling and provide better context for debugging, which is a positive step for code maintainability and reliability. 🛠️


😼 Mergecat review of cmd/root.go

@@ -45,7 +45,7 @@ func init() {
 				zerolog.LevelDebugValue,
 				zerolog.LevelTraceValue,
 			).
-			withDefault("info").
+			withDefault(zerolog.LevelInfoValue).
 			withShortHand("l"),
 	)
 	boolFlag(flags, "persist-log-level", "Persists the set log level down to other module loggers.")
@@ -56,6 +56,11 @@ func init() {
 			withChoices("github", "gitlab").
 			withDefault("gitlab"))
 	stringFlag(flags, "vcs-token", "VCS API token.")
+	stringFlag(flags, "vcs-username", "VCS Username.")
+	stringFlag(flags, "vcs-email", "VCS Email.")
+	stringFlag(flags, "github-private-key", "Github App Private Key.")
+	int64Flag(flags, "github-app-id", "Github App ID.")
+	int64Flag(flags, "github-installation-id", "Github Installation ID.")
 	stringFlag(flags, "argocd-api-token", "ArgoCD API token.")
 	stringFlag(flags, "argocd-api-server-addr", "ArgoCD API Server Address.",
 		newStringOpts().
@@ -121,7 +126,10 @@ func setupLogOutput() {
 
 	// Default level is info, unless debug flag is present
 	levelFlag := viper.GetString("log-level")
-	level, _ := zerolog.ParseLevel(levelFlag)
+	level, err := zerolog.ParseLevel(levelFlag)
+	if err != nil {
+		log.Error().Err(err).Msg("Invalid log level")
+	}
 
 	zerolog.SetGlobalLevel(level)
 	log.Debug().Msg("Debug level logging enabled.")

Feedback & Suggestions:

  1. Security Concerns:

    • The addition of sensitive information flags such as vcs-username, vcs-email, github-private-key, github-app-id, and github-installation-id should be handled with care. Ensure these values are not logged or exposed in any way. Consider using environment variables or secure vaults to manage these credentials. 🔒
  2. Error Handling:

    • The addition of error handling for zerolog.ParseLevel is a good improvement. However, consider adding a fallback to a default log level if an invalid level is provided, to ensure the application continues to run with a known state. For example:
      if err != nil {
          log.Error().Err(err).Msg("Invalid log level, defaulting to info")
          level = zerolog.InfoLevel
      }
  3. Consistency:

    • The change from "info" to zerolog.LevelInfoValue for the default log level is a good move for consistency. Ensure similar changes are applied throughout the codebase for other log levels if applicable. 📏
  4. Documentation:

    • With the addition of new flags, ensure that the documentation is updated to reflect these changes. This includes any README files, help commands, or user guides. 📚

😼 Mergecat review of pkg/vcs/github_client/message.go

@@ -6,6 +6,7 @@ import (
 	"strings"
 
 	"github.com/google/go-github/v62/github"
+	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
 	"github.com/shurcooL/githubv4"
 
@@ -17,7 +18,7 @@ import (
 
 const MaxCommentLength = 64 * 1024
 
-func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message string) *msg.Message {
+func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message string) (*msg.Message, error) {
 	_, span := tracer.Start(ctx, "PostMessageToMergeRequest")
 	defer span.End()
 
@@ -37,10 +38,10 @@ func (c *Client) PostMessage(ctx context.Context, pr vcs.PullRequest, message st
 
 	if err != nil {
 		telemetry.SetError(span, err, "Create Pull Request comment")
-		log.Error().Err(err).Msg("could not post message to PR")
+		return nil, errors.Wrap(err, "could not post message to PR")
 	}
 
-	return msg.NewMessage(pr.FullName, pr.CheckID, int(*comment.ID), c)
+	return msg.NewMessage(pr.FullName, pr.CheckID, int(*comment.ID), c), nil
 }
 
 func (c *Client) UpdateMessage(ctx context.Context, m *msg.Message, msg string) error {

Feedback & Suggestions:

  1. Error Handling Improvement: The change to return an error from PostMessage is a good improvement for error handling. However, ensure that all calling functions are updated to handle this new error return value properly. This will prevent any potential runtime errors due to unhandled nil pointers.

  2. Error Wrapping: The use of errors.Wrap is a good practice as it provides more context to the error. Make sure that this pattern is consistently applied across other functions for uniformity and better debugging.

  3. Importing errors Package: The addition of the github.com/pkg/errors package is appropriate for error wrapping. Ensure that this package is used consistently throughout the codebase for error handling to maintain consistency.

  4. Documentation Update: Since the function signature of PostMessage has changed, ensure that any documentation or comments related to this function are updated to reflect the new return type.

  5. Testing: Ensure that there are tests in place to cover the new error handling logic. This will help in verifying that the changes work as expected and handle errors gracefully.


😼 Mergecat review of pkg/events/check.go

@@ -201,7 +201,7 @@ func (ce *CheckEvent) getRepo(ctx context.Context, vcsClient hasUsername, cloneU
 	ce.clonedRepos[reposKey] = repo
 
 	// if we cloned 'HEAD', figure out its original branch and store a copy of the repo there
-	if branchName == "" || branchName == "HEAD" {
+	if branchName == "HEAD" {
 		remoteHeadBranchName, err := repo.GetRemoteHead()
 		if err != nil {
 			return repo, errors.Wrap(err, "failed to determine remote head")
@@ -260,12 +260,17 @@ func (ce *CheckEvent) Process(ctx context.Context) error {
 
 	if len(ce.affectedItems.Applications) <= 0 && len(ce.affectedItems.ApplicationSets) <= 0 {
 		ce.logger.Info().Msg("No affected apps or appsets, skipping")
-		ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, "No changes")
+		if _, err := ce.ctr.VcsClient.PostMessage(ctx, ce.pullRequest, "No changes"); err != nil {
+			return errors.Wrap(err, "failed to post changes")
+		}
 		return nil
 	}
 
 	// We make one comment per run, containing output for all the apps
-	ce.vcsNote = ce.createNote(ctx)
+	ce.vcsNote, err = ce.createNote(ctx)
+	if err != nil {
+		return errors.Wrap(err, "failed to create note")
+	}
 
 	for num := 0; num <= ce.ctr.Config.MaxConcurrenctChecks; num++ {
 
@@ -375,8 +380,8 @@ Check kubechecks application logs for more information.
 `
 )
 
-// Creates a generic Note struct that we can write into across all worker threads
-func (ce *CheckEvent) createNote(ctx context.Context) *msg.Message {
+// createNote creates a generic Note struct that we can write into across all worker threads
+func (ce *CheckEvent) createNote(ctx context.Context) (*msg.Message, error) {
 	ctx, span := otel.Tracer("check").Start(ctx, "createNote")
 	defer span.End()
 

Feedback & Suggestions:

  1. Error Handling in createNote: The change to return an error from createNote is a good improvement for error handling. However, ensure that all calls to createNote are updated to handle the error appropriately. This includes checking if the error is logged or handled in a way that informs the user of the failure.

  2. Branch Name Check: The removal of the empty string check for branchName in the getRepo function could lead to issues if branchName is ever an empty string. Consider adding a separate check or handling for empty branchName to avoid potential errors.

  3. Error Logging: When wrapping errors with errors.Wrap, ensure that the error messages are informative and provide enough context for debugging. This is especially important in distributed systems where logs might be the primary source of debugging information.

  4. Concurrency Limit: In the Process function, the loop for creating workers uses <= ce.ctr.Config.MaxConcurrenctChecks. Ensure that this is intentional and that the concurrency limit is correctly set to avoid potential performance issues or resource exhaustion.

  5. Function Documentation: The updated comment for createNote is clearer. Ensure that all function comments follow this pattern for consistency and clarity. 📚


😼 Mergecat review of docs/usage.md

@@ -47,6 +47,9 @@ The full list of supported environment variables is described below:
 |`KUBECHECKS_ENABLE_PREUPGRADE`|Enable preupgrade checks.|`true`|
 |`KUBECHECKS_ENSURE_WEBHOOKS`|Ensure that webhooks are created in repositories referenced by argo.|`false`|
 |`KUBECHECKS_FALLBACK_K8S_VERSION`|Fallback target Kubernetes version for schema / upgrade checks.|`1.23.0`|
+|`KUBECHECKS_GITHUB_APP_ID`|Github App ID.|`0`|
+|`KUBECHECKS_GITHUB_INSTALLATION_ID`|Github Installation ID.|`0`|
+|`KUBECHECKS_GITHUB_PRIVATE_KEY`|Github App Private Key.||
 |`KUBECHECKS_KUBERNETES_CLUSTERID`|Kubernetes Cluster ID, must be specified if kubernetes-type is eks.||
 |`KUBECHECKS_KUBERNETES_CONFIG`|Path to your kubernetes config file, used to monitor applications.||
 |`KUBECHECKS_KUBERNETES_TYPE`|Kubernetes Type One of eks, or local.|`local`|
@@ -66,9 +69,11 @@ The full list of supported environment variables is described below:
 |`KUBECHECKS_SHOW_DEBUG_INFO`|Set to true to print debug info to the footer of MR comments.|`false`|
 |`KUBECHECKS_TIDY_OUTDATED_COMMENTS_MODE`|Sets the mode to use when tidying outdated comments. One of hide, delete.|`hide`|
 |`KUBECHECKS_VCS_BASE_URL`|VCS base url, useful if self hosting gitlab, enterprise github, etc.||
+|`KUBECHECKS_VCS_EMAIL`|VCS Email.||
 |`KUBECHECKS_VCS_TOKEN`|VCS API token.||
 |`KUBECHECKS_VCS_TYPE`|VCS type. One of gitlab or github.|`gitlab`|
 |`KUBECHECKS_VCS_UPLOAD_URL`|VCS upload url, required for enterprise github.||
+|`KUBECHECKS_VCS_USERNAME`|VCS Username.||
 |`KUBECHECKS_WEBHOOK_SECRET`|Optional secret key for validating the source of incoming webhooks.||
 |`KUBECHECKS_WEBHOOK_URL_BASE`|The endpoint to listen on for incoming PR/MR event webhooks. For example, 'https://checker.mycompany.com'.||
 |`KUBECHECKS_WEBHOOK_URL_PREFIX`|If your application is running behind a proxy that uses path based routing, set this value to match the path prefix. For example, '/hello/world'.||

Feedback & Suggestions:

  1. Security Considerations:

    • For KUBECHECKS_GITHUB_PRIVATE_KEY, consider adding a note about the importance of securing this key. It should be stored securely and not hardcoded in configuration files. 🔐
    • Similarly, for KUBECHECKS_VCS_TOKEN, KUBECHECKS_VCS_EMAIL, and KUBECHECKS_VCS_USERNAME, ensure users are aware of the need to handle these credentials securely.
  2. Default Values:

    • The default values for KUBECHECKS_GITHUB_APP_ID and KUBECHECKS_GITHUB_INSTALLATION_ID are set to 0. It might be helpful to clarify if 0 is a placeholder or a valid default. If it's a placeholder, consider indicating that these need to be replaced with actual values. 🧐
  3. Documentation Clarity:

    • Consider providing a brief description or example of what a valid KUBECHECKS_GITHUB_PRIVATE_KEY looks like, especially if it has a specific format. This can help users avoid common mistakes. 📄
  4. Consistency:

    • Ensure that the new entries are consistent with the existing documentation style, both in terms of formatting and the level of detail provided. This helps maintain a professional and cohesive document. 📚

😼 Mergecat review of pkg/vcs/github_client/client.go

@@ -9,7 +9,8 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/chainguard-dev/git-urls"
+	"github.com/bradleyfalzon/ghinstallation/v2"
+	giturls "github.com/chainguard-dev/git-urls"
 	"github.com/google/go-github/v62/github"
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
@@ -48,37 +49,26 @@ func CreateGithubClient(cfg config.ServerConfig) (*Client, error) {
 		shurcoolClient *githubv4.Client
 	)
 
-	// Initialize the GitLab client with access token
-	t := cfg.VcsToken
-	if t == "" {
-		log.Fatal().Msg("github token needs to be set")
-	}
-	log.Debug().Msgf("Token Length - %d", len(t))
 	ctx := context.Background()
-	ts := oauth2.StaticTokenSource(
-		&oauth2.Token{AccessToken: t},
-	)
-	tc := oauth2.NewClient(ctx, ts)
+
+	githubClient, err := createHttpClient(ctx, cfg)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to create github http client")
+	}
 
 	githubUrl := cfg.VcsBaseUrl
 	githubUploadUrl := cfg.VcsUploadUrl
 	// we need both urls to be set for github enterprise
 	if githubUrl == "" || githubUploadUrl == "" {
-		googleClient = github.NewClient(tc) // If this has failed, we'll catch it on first call
+		googleClient = github.NewClient(githubClient) // If this has failed, we'll catch it on first call
 
-		// Use the client from shurcooL's githubv4 library for queries.
-		shurcoolClient = githubv4.NewClient(tc)
+		shurcoolClient = githubv4.NewClient(githubClient)
 	} else {
-		googleClient, err = github.NewClient(tc).WithEnterpriseURLs(githubUrl, githubUploadUrl)
+		googleClient, err = github.NewClient(githubClient).WithEnterpriseURLs(githubUrl, githubUploadUrl)
 		if err != nil {
 			log.Fatal().Err(err).Msg("failed to create github enterprise client")
 		}
-		shurcoolClient = githubv4.NewEnterpriseClient(githubUrl, tc)
-	}
-
-	user, _, err := googleClient.Users.Get(ctx, "")
-	if err != nil {
-		return nil, errors.Wrap(err, "failed to get user")
+		shurcoolClient = githubv4.NewEnterpriseClient(githubUrl, githubClient)
 	}
 
 	client := &Client{
@@ -89,13 +79,20 @@ func CreateGithubClient(cfg config.ServerConfig) (*Client, error) {
 			Issues:       IssuesService{googleClient.Issues},
 		},
 		shurcoolClient: shurcoolClient,
+		username:       cfg.VcsUsername,
+		email:          cfg.VcsEmail,
 	}
-	if user != nil {
-		if user.Login != nil {
-			client.username = *user.Login
-		}
-		if user.Email != nil {
-			client.email = *user.Email
+
+	if client.username == "" || client.email == "" {
+		user, _, err := googleClient.Users.Get(ctx, "")
+		if err == nil {
+			if user.Login != nil {
+				client.username = *user.Login
+			}
+
+			if user.Email != nil {
+				client.email = *user.Email
+			}
 		}
 	}
 
@@ -108,6 +105,32 @@ func CreateGithubClient(cfg config.ServerConfig) (*Client, error) {
 	return client, nil
 }
 
+func createHttpClient(ctx context.Context, cfg config.ServerConfig) (*http.Client, error) {
+	// Initialize the GitHub client with app key if provided
+	if cfg.GithubAppID != 0 && cfg.GithubInstallationID != 0 && cfg.GithubPrivateKey != "" {
+		appTransport, err := ghinstallation.New(
+			http.DefaultTransport, cfg.GithubAppID, cfg.GithubInstallationID, []byte(cfg.GithubPrivateKey),
+		)
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create github app transport")
+		}
+
+		return &http.Client{Transport: appTransport}, nil
+	}
+
+	// Initialize the GitHub client with access token if app key is not provided
+	vcsToken := cfg.VcsToken
+	if vcsToken != "" {
+		log.Debug().Msgf("Token Length - %d", len(vcsToken))
+		ts := oauth2.StaticTokenSource(
+			&oauth2.Token{AccessToken: vcsToken},
+		)
+		return oauth2.NewClient(ctx, ts), nil
+	}
+
+	return nil, errors.New("Either GitHub token or GitHub App credentials (App ID, Installation ID, Private Key) must be set")
+}
+
 func (c *Client) Username() string { return c.username }
 func (c *Client) Email() string    { return c.email }
 func (c *Client) GetName() string {

Feedback & Suggestions:

  1. Security Enhancement: The new createHttpClient function introduces the use of GitHub App credentials. Ensure that the private key is securely stored and accessed. Consider using environment variables or a secure vault to manage sensitive information like GithubPrivateKey. 🔐

  2. Error Handling: The error message in createHttpClient could be more descriptive. Instead of "Either GitHub token or GitHub App credentials (App ID, Installation ID, Private Key) must be set", specify which one is missing to aid debugging. 🐛

  3. Logging: The logging for token length is useful for debugging, but be cautious about logging sensitive information. Ensure that the token itself is never logged. Consider adding a log message when using GitHub App credentials for clarity. 📜

  4. Code Clarity: The function createHttpClient is a good abstraction. However, consider adding comments to explain the logic behind choosing between GitHub App credentials and a personal access token. This will help future maintainers understand the decision-making process. 📝

  5. Performance: The function createHttpClient is called every time CreateGithubClient is invoked. If the configuration does not change often, consider caching the HTTP client to avoid redundant operations. 🚀



Dependency Review

Click to read mergecats review!

No suggestions found

@djeebus djeebus merged commit c08c70b into main Nov 13, 2024
5 checks passed
@djeebus djeebus deleted the github-app branch November 13, 2024 16:57
@DrFaust92
Copy link
Contributor

Hi, can we please cut a new version with this feature? 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use KubeChecks with GitHub app
4 participants