diff --git a/app/api/controller/pullreq/check_list.go b/app/api/controller/pullreq/check_list.go index ac6c6ffd5..49b9c6ba9 100644 --- a/app/api/controller/pullreq/check_list.go +++ b/app/api/controller/pullreq/check_list.go @@ -55,10 +55,11 @@ func (c *Controller) ListChecks( } reqChecks, err := protectionRules.RequiredChecks(ctx, protection.RequiredChecksInput{ - Actor: &session.Principal, - IsRepoOwner: isRepoOwner, - Repo: repo, - PullReq: pr, + ResolveUserGroupID: c.userGroupService.ListUserIDsByGroupIDs, + Actor: &session.Principal, + IsRepoOwner: isRepoOwner, + Repo: repo, + PullReq: pr, }) if err != nil { return types.PullReqChecks{}, fmt.Errorf("failed to get identifiers of required checks: %w", err) diff --git a/app/api/controller/pullreq/merge.go b/app/api/controller/pullreq/merge.go index 86c042472..532bfc813 100644 --- a/app/api/controller/pullreq/merge.go +++ b/app/api/controller/pullreq/merge.go @@ -204,16 +204,17 @@ func (c *Controller) Merge( } ruleOut, violations, err := protectionRules.MergeVerify(ctx, protection.MergeVerifyInput{ - Actor: &session.Principal, - AllowBypass: in.BypassRules, - IsRepoOwner: isRepoOwner, - TargetRepo: targetRepo, - SourceRepo: sourceRepo, - PullReq: pr, - Reviewers: reviewers, - Method: in.Method, - CheckResults: checkResults, - CodeOwners: codeOwnerWithApproval, + ResolveUserGroupID: c.userGroupService.ListUserIDsByGroupIDs, + Actor: &session.Principal, + AllowBypass: in.BypassRules, + IsRepoOwner: isRepoOwner, + TargetRepo: targetRepo, + SourceRepo: sourceRepo, + PullReq: pr, + Reviewers: reviewers, + Method: in.Method, + CheckResults: checkResults, + CodeOwners: codeOwnerWithApproval, }) if err != nil { return nil, nil, fmt.Errorf("failed to verify protection rules: %w", err) diff --git a/app/api/controller/repo/commit.go b/app/api/controller/repo/commit.go index f6df9415a..8875ccd11 100644 --- a/app/api/controller/repo/commit.go +++ b/app/api/controller/repo/commit.go @@ -83,13 +83,14 @@ func (c *Controller) CommitFiles(ctx context.Context, } violations, err := rules.RefChangeVerify(ctx, protection.RefChangeVerifyInput{ - Actor: &session.Principal, - AllowBypass: in.BypassRules, - IsRepoOwner: isRepoOwner, - Repo: repo, - RefAction: refAction, - RefType: protection.RefTypeBranch, - RefNames: []string{branchName}, + ResolveUserGroupID: c.userGroupService.ListUserIDsByGroupIDs, + Actor: &session.Principal, + AllowBypass: in.BypassRules, + IsRepoOwner: isRepoOwner, + Repo: repo, + RefAction: refAction, + RefType: protection.RefTypeBranch, + RefNames: []string{branchName}, }) if err != nil { return types.CommitFilesResponse{}, nil, fmt.Errorf("failed to verify protection rules: %w", err) diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 61ea3c564..5e35f6b37 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -36,6 +36,7 @@ import ( "github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" + "github.com/harness/gitness/app/services/usergroup" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" "github.com/harness/gitness/audit" @@ -82,6 +83,7 @@ type Controller struct { settings *settings.Service principalInfoCache store.PrincipalInfoCache userGroupStore store.UserGroupStore + userGroupService usergroup.SearchService protectionManager *protection.Manager git git.Interface importer *importer.Repository @@ -127,6 +129,7 @@ func NewController( labelSvc *label.Service, instrumentation instrument.Service, userGroupStore store.UserGroupStore, + userGroupService usergroup.SearchService, ) *Controller { return &Controller{ defaultBranch: config.Git.DefaultBranch, @@ -156,6 +159,7 @@ func NewController( labelSvc: labelSvc, instrumentation: instrumentation, userGroupStore: userGroupStore, + userGroupService: userGroupService, } } @@ -237,12 +241,31 @@ func (c *Controller) fetchRules( return protectionRules, isRepoOwner, nil } -func (c *Controller) getRuleUsers(ctx context.Context, r *types.Rule) (map[int64]*types.PrincipalInfo, error) { - rule, err := c.protectionManager.FromJSON(r.Type, r.Definition, false) +func (c *Controller) getRuleUserAndUserGroups( + ctx context.Context, + r *types.Rule, +) (map[int64]*types.PrincipalInfo, map[int64]*types.UserGroupInfo, error) { + rule, err := c.parseRule(r) if err != nil { - return nil, fmt.Errorf("failed to parse json rule definition: %w", err) + return nil, nil, fmt.Errorf("failed to parse rule: %w", err) } + userMap, err := c.getRuleUsers(ctx, rule) + if err != nil { + return nil, nil, fmt.Errorf("failed to get rule users: %w", err) + } + userGroupMap, err := c.getRuleUserGroups(ctx, rule) + if err != nil { + return nil, nil, fmt.Errorf("failed to get rule user groups: %w", err) + } + + return userMap, userGroupMap, nil +} + +func (c *Controller) getRuleUsers( + ctx context.Context, + rule protection.Protection, +) (map[int64]*types.PrincipalInfo, error) { userIDs, err := rule.UserIDs() if err != nil { return nil, fmt.Errorf("failed to get user ID from rule: %w", err) @@ -256,12 +279,10 @@ func (c *Controller) getRuleUsers(ctx context.Context, r *types.Rule) (map[int64 return userMap, nil } -func (c *Controller) getRuleUserGroups(ctx context.Context, r *types.Rule) (map[int64]*types.UserGroupInfo, error) { - rule, err := c.protectionManager.FromJSON(r.Type, r.Definition, false) - if err != nil { - return nil, fmt.Errorf("failed to parse json rule definition: %w", err) - } - +func (c *Controller) getRuleUserGroups( + ctx context.Context, + rule protection.Protection, +) (map[int64]*types.UserGroupInfo, error) { groupIDs, err := rule.UserGroupIDs() if err != nil { return nil, fmt.Errorf("failed to get group IDs from rule: %w", err) @@ -283,3 +304,12 @@ func (c *Controller) getRuleUserGroups(ctx context.Context, r *types.Rule) (map[ } return userGroupInfoMap, nil } + +func (c *Controller) parseRule(r *types.Rule) (protection.Protection, error) { + rule, err := c.protectionManager.FromJSON(r.Type, r.Definition, false) + if err != nil { + return nil, fmt.Errorf("failed to parse json rule definition: %w", err) + } + + return rule, nil +} diff --git a/app/api/controller/repo/rebase.go b/app/api/controller/repo/rebase.go index 3dbce96f5..796d836fc 100644 --- a/app/api/controller/repo/rebase.go +++ b/app/api/controller/repo/rebase.go @@ -82,13 +82,14 @@ func (c *Controller) Rebase( } violations, err := protectionRules.RefChangeVerify(ctx, protection.RefChangeVerifyInput{ - Actor: &session.Principal, - AllowBypass: in.BypassRules, - IsRepoOwner: isRepoOwner, - Repo: repo, - RefAction: protection.RefActionUpdate, - RefType: protection.RefTypeBranch, - RefNames: []string{in.HeadBranch}, + ResolveUserGroupID: c.userGroupService.ListUserIDsByGroupIDs, + Actor: &session.Principal, + AllowBypass: in.BypassRules, + IsRepoOwner: isRepoOwner, + Repo: repo, + RefAction: protection.RefActionUpdate, + RefType: protection.RefTypeBranch, + RefNames: []string{in.HeadBranch}, }) if err != nil { return nil, nil, fmt.Errorf("failed to verify protection rules: %w", err) diff --git a/app/api/controller/repo/rule_create.go b/app/api/controller/repo/rule_create.go index 277d52569..a054c301d 100644 --- a/app/api/controller/repo/rule_create.go +++ b/app/api/controller/repo/rule_create.go @@ -142,15 +142,13 @@ func (c *Controller) RuleCreate(ctx context.Context, log.Ctx(ctx).Warn().Msgf("failed to insert instrumentation record for create branch rule operation: %s", err) } - r.Users, err = c.getRuleUsers(ctx, r) + userMap, userGroupMap, err := c.getRuleUserAndUserGroups(ctx, r) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get rule users and user groups: %w", err) } - r.UserGroups, err = c.getRuleUserGroups(ctx, r) - if err != nil { - return nil, fmt.Errorf("failed to get rule user groups: %w", err) - } + r.Users = userMap + r.UserGroups = userGroupMap return r, nil } diff --git a/app/api/controller/repo/rule_find.go b/app/api/controller/repo/rule_find.go index a80b13632..bf95a8c1f 100644 --- a/app/api/controller/repo/rule_find.go +++ b/app/api/controller/repo/rule_find.go @@ -39,15 +39,13 @@ func (c *Controller) RuleFind(ctx context.Context, return nil, fmt.Errorf("failed to find repository-level protection rule by identifier: %w", err) } - r.Users, err = c.getRuleUsers(ctx, r) + userMap, userGroupMap, err := c.getRuleUserAndUserGroups(ctx, r) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get rule users and user groups: %w", err) } - r.UserGroups, err = c.getRuleUserGroups(ctx, r) - if err != nil { - return nil, fmt.Errorf("failed to get rule user groups: %w", err) - } + r.Users = userMap + r.UserGroups = userGroupMap return r, nil } diff --git a/app/api/controller/repo/rule_list.go b/app/api/controller/repo/rule_list.go index 36a17652b..fa6c6c3be 100644 --- a/app/api/controller/repo/rule_list.go +++ b/app/api/controller/repo/rule_list.go @@ -61,7 +61,7 @@ func (c *Controller) RuleList(ctx context.Context, } for i := range list { - list[i].Users, err = c.getRuleUsers(ctx, &list[i]) + list[i].Users, list[i].UserGroups, err = c.getRuleUserAndUserGroups(ctx, &list[i]) if err != nil { return nil, 0, err } diff --git a/app/api/controller/repo/rule_update.go b/app/api/controller/repo/rule_update.go index fb666782f..68e65646d 100644 --- a/app/api/controller/repo/rule_update.go +++ b/app/api/controller/repo/rule_update.go @@ -102,14 +102,14 @@ func (c *Controller) RuleUpdate(ctx context.Context, } oldRule := r.Clone() if in.isEmpty() { - r.Users, err = c.getRuleUsers(ctx, r) + userMap, userGroupMap, err := c.getRuleUserAndUserGroups(ctx, r) if err != nil { - return nil, err - } - r.UserGroups, err = c.getRuleUserGroups(ctx, r) - if err != nil { - return nil, fmt.Errorf("failed to get rule user groups: %w", err) + return nil, fmt.Errorf("failed to get rule users and user groups: %w", err) } + + r.Users = userMap + r.UserGroups = userGroupMap + return r, nil } @@ -132,15 +132,13 @@ func (c *Controller) RuleUpdate(ctx context.Context, } } - r.Users, err = c.getRuleUsers(ctx, r) + userMap, userGroupMap, err := c.getRuleUserAndUserGroups(ctx, r) if err != nil { - return nil, fmt.Errorf("failed to get rule users: %w", err) + return nil, fmt.Errorf("failed to get rule users and user groups: %w", err) } - r.UserGroups, err = c.getRuleUserGroups(ctx, r) - if err != nil { - return nil, fmt.Errorf("failed to get rule user groups: %w", err) - } + r.Users = userMap + r.UserGroups = userGroupMap err = c.ruleStore.Update(ctx, r) if err != nil { diff --git a/app/api/controller/repo/wire.go b/app/api/controller/repo/wire.go index b4dd34d1e..bc2700a52 100644 --- a/app/api/controller/repo/wire.go +++ b/app/api/controller/repo/wire.go @@ -27,6 +27,7 @@ import ( "github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" + "github.com/harness/gitness/app/services/usergroup" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" "github.com/harness/gitness/audit" @@ -72,13 +73,14 @@ func ProvideController( labelSvc *label.Service, instrumentation instrument.Service, userGroupStore store.UserGroupStore, + userGroupService usergroup.SearchService, ) *Controller { return NewController(config, tx, urlProvider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settings, principalInfoCache, protectionManager, rpcClient, importer, codeOwners, reporeporter, indexer, limiter, locker, auditService, mtxManager, identifierCheck, - repoChecks, publicAccess, labelSvc, instrumentation, userGroupStore) + repoChecks, publicAccess, labelSvc, instrumentation, userGroupStore, userGroupService) } func ProvideRepoCheck() Check { diff --git a/app/services/protection/bypass.go b/app/services/protection/bypass.go index 991920431..bbbaf04cf 100644 --- a/app/services/protection/bypass.go +++ b/app/services/protection/bypass.go @@ -15,8 +15,10 @@ package protection import ( + "context" "fmt" + "github.com/harness/gitness/cache" "github.com/harness/gitness/types" "golang.org/x/exp/slices" @@ -28,7 +30,21 @@ type DefBypass struct { RepoOwners bool `json:"repo_owners,omitempty"` } -func (v DefBypass) matches(actor *types.Principal, isRepoOwner bool) bool { +func (v DefBypass) matches( + ctx context.Context, + actor *types.Principal, + isRepoOwner bool, + userGroupResolverFn func(context.Context, []int64) ([]int64, error), +) bool { + if userGroupResolverFn != nil { + userIDs, err := userGroupResolverFn(ctx, v.UserGroupIDs) + if err != nil { + return false + } + + v.UserIDs = append(v.UserIDs, userIDs...) + v.UserIDs = cache.Deduplicate(v.UserIDs) + } return actor != nil && (v.RepoOwners && isRepoOwner || slices.Contains(v.UserIDs, actor.ID)) diff --git a/app/services/protection/bypass_test.go b/app/services/protection/bypass_test.go index 630573de8..64806dff4 100644 --- a/app/services/protection/bypass_test.go +++ b/app/services/protection/bypass_test.go @@ -15,6 +15,7 @@ package protection import ( + "context" "testing" "github.com/harness/gitness/types" @@ -78,7 +79,7 @@ func TestBranch_matches(t *testing.T) { t.Errorf("invalid: %s", err.Error()) } - if want, got := test.exp, test.bypass.matches(test.actor, test.owner); want != got { + if want, got := test.exp, test.bypass.matches(context.TODO(), test.actor, test.owner, nil); want != got { t.Errorf("want=%t got=%t", want, got) } }) diff --git a/app/services/protection/rule_branch.go b/app/services/protection/rule_branch.go index 6b0357ef4..45857f674 100644 --- a/app/services/protection/rule_branch.go +++ b/app/services/protection/rule_branch.go @@ -41,10 +41,10 @@ func (v *Branch) MergeVerify( ) (out MergeVerifyOutput, violations []types.RuleViolations, err error) { out, violations, err = v.PullReq.MergeVerify(ctx, in) if err != nil { - return + return out, violations, fmt.Errorf("merge verify error: %w", err) } - bypassable := v.Bypass.matches(in.Actor, in.IsRepoOwner) + bypassable := v.Bypass.matches(ctx, in.Actor, in.IsRepoOwner, in.ResolveUserGroupID) bypassed := in.AllowBypass && bypassable for i := range violations { violations[i].Bypassable = bypassable @@ -73,7 +73,7 @@ func (v *Branch) RequiredChecks( bypassableIDs map[string]struct{} ) - if bypassable := v.Bypass.matches(in.Actor, in.IsRepoOwner); bypassable { + if bypassable := v.Bypass.matches(ctx, in.Actor, in.IsRepoOwner, in.ResolveUserGroupID); bypassable { bypassableIDs = ids } else { requiredIDs = ids @@ -94,8 +94,11 @@ func (v *Branch) RefChangeVerify( } violations, err = v.Lifecycle.RefChangeVerify(ctx, in) + if err != nil { + return nil, fmt.Errorf("lifecycle error: %w", err) + } - bypassable := v.Bypass.matches(in.Actor, in.IsRepoOwner) + bypassable := v.Bypass.matches(ctx, in.Actor, in.IsRepoOwner, in.ResolveUserGroupID) bypassed := in.AllowBypass && bypassable for i := range violations { violations[i].Bypassable = bypassable diff --git a/app/services/protection/rule_branch_test.go b/app/services/protection/rule_branch_test.go index 4bd1a2285..c228bdaea 100644 --- a/app/services/protection/rule_branch_test.go +++ b/app/services/protection/rule_branch_test.go @@ -182,10 +182,11 @@ func TestBranch_MergeVerify(t *testing.T) { }, }, in: MergeVerifyInput{ - Actor: user, - CodeOwners: &codeowners.Evaluation{}, - PullReq: &types.PullReq{}, - Reviewers: []*types.PullReqReviewer{}, + Actor: user, + ResolveUserGroupID: mockUserGroupResolver, + CodeOwners: &codeowners.Evaluation{}, + PullReq: &types.PullReq{}, + Reviewers: []*types.PullReqReviewer{}, }, expOut: MergeVerifyOutput{ DeleteSourceBranch: true, @@ -480,6 +481,31 @@ func TestBranch_RefChangeVerify(t *testing.T) { }, }, }, + { + name: "usergroup-bypass", + branch: Branch{ + Bypass: DefBypass{RepoOwners: true}, + Lifecycle: DefLifecycle{DeleteForbidden: true}, + }, + in: RefChangeVerifyInput{ + Actor: &types.Principal{ID: 43}, + ResolveUserGroupID: mockUserGroupResolver, + AllowBypass: true, + IsRepoOwner: false, + RefAction: RefActionDelete, + RefType: RefTypeBranch, + RefNames: []string{"abc"}, + }, + expVs: []types.RuleViolations{ + { + Bypassable: true, + Bypassed: true, + Violations: []types.Violation{ + {Code: codeLifecycleDelete}, + }, + }, + }, + }, } ctx := context.Background() @@ -527,3 +553,7 @@ func TestBranch_RefChangeVerify(t *testing.T) { }) } } + +func mockUserGroupResolver(_ context.Context, _ []int64) ([]int64, error) { + return []int64{43}, nil +} diff --git a/app/services/protection/verify_lifecycle.go b/app/services/protection/verify_lifecycle.go index bf1c27b54..ba019f03f 100644 --- a/app/services/protection/verify_lifecycle.go +++ b/app/services/protection/verify_lifecycle.go @@ -26,13 +26,14 @@ type ( } RefChangeVerifyInput struct { - Actor *types.Principal - AllowBypass bool - IsRepoOwner bool - Repo *types.Repository - RefAction RefAction - RefType RefType - RefNames []string + ResolveUserGroupID func(ctx context.Context, userGroupIDs []int64) ([]int64, error) + Actor *types.Principal + AllowBypass bool + IsRepoOwner bool + Repo *types.Repository + RefAction RefAction + RefType RefType + RefNames []string } RefType int diff --git a/app/services/protection/verify_pullreq.go b/app/services/protection/verify_pullreq.go index eabd9a7fe..64ac0adcf 100644 --- a/app/services/protection/verify_pullreq.go +++ b/app/services/protection/verify_pullreq.go @@ -35,16 +35,17 @@ type ( } MergeVerifyInput struct { - Actor *types.Principal - AllowBypass bool - IsRepoOwner bool - TargetRepo *types.Repository - SourceRepo *types.Repository - PullReq *types.PullReq - Reviewers []*types.PullReqReviewer - Method enum.MergeMethod - CheckResults []types.CheckResult - CodeOwners *codeowners.Evaluation + ResolveUserGroupID func(ctx context.Context, userGroupIDs []int64) ([]int64, error) + Actor *types.Principal + AllowBypass bool + IsRepoOwner bool + TargetRepo *types.Repository + SourceRepo *types.Repository + PullReq *types.PullReq + Reviewers []*types.PullReqReviewer + Method enum.MergeMethod + CheckResults []types.CheckResult + CodeOwners *codeowners.Evaluation } MergeVerifyOutput struct { @@ -59,10 +60,11 @@ type ( } RequiredChecksInput struct { - Actor *types.Principal - IsRepoOwner bool - Repo *types.Repository - PullReq *types.PullReq + ResolveUserGroupID func(ctx context.Context, userGroupIDs []int64) ([]int64, error) + Actor *types.Principal + IsRepoOwner bool + Repo *types.Repository + PullReq *types.PullReq } RequiredChecksOutput struct { diff --git a/app/services/usergroup/list_users.go b/app/services/usergroup/list_users.go index 55c000284..cb19b7312 100644 --- a/app/services/usergroup/list_users.go +++ b/app/services/usergroup/list_users.go @@ -29,3 +29,7 @@ func (s *searchService) ListUsers( ) ([]string, error) { return nil, fmt.Errorf("not implemented") } + +func (s *searchService) ListUserIDsByGroupIDs(_ context.Context, _ []int64) ([]int64, error) { + return nil, fmt.Errorf("not implemented") +} diff --git a/app/services/usergroup/search_interface.go b/app/services/usergroup/search_interface.go index 486303582..964f5b777 100644 --- a/app/services/usergroup/search_interface.go +++ b/app/services/usergroup/search_interface.go @@ -32,4 +32,6 @@ type SearchService interface { session *auth.Session, userGroup *types.UserGroup, ) ([]string, error) + + ListUserIDsByGroupIDs(ctx context.Context, userGroupIDs []int64) ([]int64, error) } diff --git a/cache/cache_test.go b/cache/cache_test.go index e65896e7b..5ee7eb340 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -59,7 +59,7 @@ func TestDeduplicate(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - test.input = deduplicate(test.input) + test.input = Deduplicate(test.input) if want, got := test.expected, test.input; !reflect.DeepEqual(want, got) { t.Errorf("failed - want=%v, got=%v", want, got) return diff --git a/cache/ttl_cache.go b/cache/ttl_cache.go index ece9839d2..6c82f8102 100644 --- a/cache/ttl_cache.go +++ b/cache/ttl_cache.go @@ -140,7 +140,7 @@ func (c *ExtendedTTLCache[K, V]) Map(ctx context.Context, keys []K) (map[K]V, er m := make(map[K]V) now := time.Now() - keys = deduplicate(keys) + keys = Deduplicate(keys) // Check what's already available in the cache. @@ -211,8 +211,8 @@ func (c *TTLCache[K, V]) Get(ctx context.Context, key K) (V, error) { return item, nil } -// deduplicate is a utility function that removes duplicates from slice. -func deduplicate[V constraints.Ordered](slice []V) []V { +// Deduplicate is a utility function that removes duplicates from slice. +func Deduplicate[V constraints.Ordered](slice []V) []V { if len(slice) <= 1 { return slice } diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 2c897fc3d..2c86994d7 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -245,7 +245,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro labelService := label.ProvideLabel(transactor, spaceStore, labelStore, labelValueStore, pullReqLabelAssignmentStore) instrumentService := instrument.ProvideService() userGroupStore := database.ProvideUserGroupStore(db) - repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService, labelService, instrumentService, userGroupStore) + searchService := usergroup.ProvideSearchService() + repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService, labelService, instrumentService, userGroupStore, searchService) reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, auditService) executionStore := database.ProvideExecutionStore(db) checkStore := database.ProvideCheckStore(db, principalInfoCache) @@ -332,7 +333,6 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro return nil, err } pullReq := migrate.ProvidePullReqImporter(provider, gitInterface, principalStore, repoStore, pullReqStore, pullReqActivityStore, transactor) - searchService := usergroup.ProvideSearchService() pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, userGroupStore, userGroupReviewersStore, principalInfoCache, pullReqFileViewStore, membershipStore, checkStore, gitInterface, reporter3, migrator, pullreqService, listService, protectionManager, streamer, codeownersService, lockerLocker, pullReq, labelService, instrumentService, searchService) webhookConfig := server.ProvideWebhookConfig(config) webhookStore := database.ProvideWebhookStore(db)