From 8c68b0cd5166454c3a3f178a2d21c8af26abf14b Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Fri, 10 Nov 2023 01:51:02 +0000 Subject: [PATCH] feat: codeowners multi location (#785) --- app/services/codeowners/service.go | 42 +++++++++++++++++++++--------- cli/server/config.go | 2 +- types/config.go | 2 +- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/app/services/codeowners/service.go b/app/services/codeowners/service.go index e94956506..e267d689a 100644 --- a/app/services/codeowners/service.go +++ b/app/services/codeowners/service.go @@ -67,7 +67,7 @@ func (e *TooLargeError) Is(target error) bool { } type Config struct { - FilePath string + FilePaths []string } type Service struct { @@ -130,10 +130,6 @@ func (s *Service) get( ref string, ) (*CodeOwners, error) { codeOwnerFile, err := s.getCodeOwnerFile(ctx, repo, ref) - // no codeowner file - if gitrpc.ErrorStatus(err) == gitrpc.StatusPathNotFound { - return nil, ErrNotFound - } if err != nil { return nil, fmt.Errorf("unable to get codeowner file: %w", err) } @@ -193,15 +189,10 @@ func (s *Service) getCodeOwnerFile( if ref == "" { ref = "refs/heads/" + repo.DefaultBranch } - node, err := s.git.GetTreeNode(ctx, &gitrpc.GetTreeNodeParams{ - ReadParams: params, - GitREF: ref, - Path: s.config.FilePath, - }) + node, err := s.getCodeOwnerFileNode(ctx, params, ref) if err != nil { - return nil, fmt.Errorf("unable to retrieve codeowner file %w", err) + return nil, fmt.Errorf("cannot get codeowner file : %w", err) } - if node.Node.Mode != gitrpc.TreeNodeModeFile { return nil, fmt.Errorf( "codeowner file is of format '%s' but expected to be of format '%s'", @@ -231,6 +222,33 @@ func (s *Service) getCodeOwnerFile( }, nil } +func (s *Service) getCodeOwnerFileNode( + ctx context.Context, + params gitrpc.ReadParams, + ref string, +) (*gitrpc.GetTreeNodeOutput, error) { + // iterating over multiple possible codeowner file path to get the file + // todo: once we have api to get multi file we can simplify + for _, path := range s.config.FilePaths { + node, err := s.git.GetTreeNode(ctx, &gitrpc.GetTreeNodeParams{ + ReadParams: params, + GitREF: ref, + Path: path, + }) + + if gitrpc.ErrorStatus(err) == gitrpc.StatusPathNotFound { + continue + } + if err != nil { + return nil, fmt.Errorf("error encountered retrieving codeowner : %w", err) + } + log.Ctx(ctx).Debug().Msgf("using codeowner file from path %s", path) + return node, nil + } + // get of codeowner file gives err at all the location then returning one of the error + return nil, fmt.Errorf("no codeowner file found: %w", ErrNotFound) +} + func (s *Service) getApplicableCodeOwnersForPR( ctx context.Context, repo *types.Repository, diff --git a/cli/server/config.go b/cli/server/config.go index 5fce1b5e8..9f7f8575e 100644 --- a/cli/server/config.go +++ b/cli/server/config.go @@ -339,6 +339,6 @@ func ProvideCleanupConfig(config *types.Config) cleanup.Config { // ProvideCodeOwnerConfig loads the codeowner config from the main config. func ProvideCodeOwnerConfig(config *types.Config) codeowners.Config { return codeowners.Config{ - FilePath: config.CodeOwners.FilePath, + FilePaths: config.CodeOwners.FilePaths, } } diff --git a/types/config.go b/types/config.go index c52de59ad..adb1e2a70 100644 --- a/types/config.go +++ b/types/config.go @@ -283,7 +283,7 @@ type Config struct { } CodeOwners struct { - FilePath string `envconfig:"GITNESS_CODEOWNERS_FILEPATH" default:".harness/CODEOWNERS"` + FilePaths []string `envconfig:"GITNESS_CODEOWNERS_FILEPATH" default:"CODEOWNERS,.harness/CODEOWNERS"` } SMTP struct {