From 802160ff00f88d92b1e0a19cb35570f33124df1d Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Mon, 19 Aug 2024 16:37:45 +0300 Subject: [PATCH 1/8] update groups when creating a new project --- internal/services/groups.go | 14 ++++++++++++++ internal/services/projects.go | 35 ++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/internal/services/groups.go b/internal/services/groups.go index 7b0baae63..9a391debb 100644 --- a/internal/services/groups.go +++ b/internal/services/groups.go @@ -8,6 +8,20 @@ import ( "github.com/pkg/errors" ) +func GetGroupMap(groupsWrapper wrappers.GroupsWrapper, projectGroups string, projModel *wrappers.Project, projModelResp *wrappers.ProjectResponseModel, + featureFlagsWrapper wrappers.FeatureFlagsWrapper) ([]*wrappers.Group, error) { + groupsMap, groupErr := CreateGroupsMap(projectGroups, groupsWrapper) + if groupErr != nil { + return nil, errors.Errorf("%s: %v", failedUpdatingProj, groupErr) + } + projModel.Groups = getGroupsForRequest(groupsMap, featureFlagsWrapper) + if projModelResp != nil { + groups := append(getGroupsForRequest(groupsMap, featureFlagsWrapper), projModelResp.Groups...) + projModel.Groups = groups + } + return groupsMap, nil +} + func CreateGroupsMap(groupsStr string, groupsWrapper wrappers.GroupsWrapper) ([]*wrappers.Group, error) { groups := strings.Split(groupsStr, ",") var groupsMap []*wrappers.Group diff --git a/internal/services/projects.go b/internal/services/projects.go index fb2c4a0bb..f4db7a1c7 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -87,6 +87,10 @@ func createProject( var projModel = wrappers.Project{} projModel.Name = projectName projModel.ApplicationIds = applicationID + _, groupErr := GetGroupMap(groupsWrapper, projectGroups, &projModel, nil, featureFlagsWrapper) + if groupErr != nil { + return "", groupErr + } if projectPrivatePackage != "" { projModel.PrivatePackage, _ = strconv.ParseBool(projectPrivatePackage) @@ -108,7 +112,7 @@ func createProject( } if projectGroups != "" { - err = UpsertProjectGroups(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, nil, projectGroups, projectID, projectName, featureFlagsWrapper) + err = UpsertProjectGroupsInCreate(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, nil, projectGroups, projectID, projectName, featureFlagsWrapper) if err != nil { return projectID, err } @@ -215,7 +219,7 @@ func updateProject( } if projectGroups != "" { - err = UpsertProjectGroups(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) + err = UpsertProjectGroupsInUpdate(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) if err != nil { return projectID, err } @@ -223,17 +227,30 @@ func updateProject( return projectID, nil } -func UpsertProjectGroups(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, +func UpsertProjectGroupsInCreate(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, + accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, + projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) + +} + +func UpsertProjectGroupsInUpdate(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - groupsMap, groupErr := CreateGroupsMap(projectGroups, groupsWrapper) + _, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModel, projModelResp, featureFlagsWrapper) if groupErr != nil { - return errors.Errorf("%s: %v", failedUpdatingProj, groupErr) + return groupErr } - projModel.Groups = getGroupsForRequest(groupsMap, featureFlagsWrapper) - if projModelResp != nil { - groups := append(getGroupsForRequest(groupsMap, featureFlagsWrapper), projModelResp.Groups...) - projModel.Groups = groups + return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) + +} + +func UpsertProjectGroups(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, + accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, + projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + groupsMap, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModel, projModelResp, featureFlagsWrapper) + if groupErr != nil { + return groupErr } err := AssignGroupsToProjectNewAccessManagement(projectID, projectName, groupsMap, accessManagementWrapper, featureFlagsWrapper) From 92885f9d64b0f2f25c1504d2755d86814080e185 Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Mon, 19 Aug 2024 16:59:04 +0300 Subject: [PATCH 2/8] fix for lint --- internal/services/projects.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/services/projects.go b/internal/services/projects.go index f4db7a1c7..63a583104 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -231,7 +231,6 @@ func UpsertProjectGroupsInCreate(groupsWrapper wrappers.GroupsWrapper, projModel accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) - } func UpsertProjectGroupsInUpdate(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, @@ -242,7 +241,6 @@ func UpsertProjectGroupsInUpdate(groupsWrapper wrappers.GroupsWrapper, projModel return groupErr } return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) - } func UpsertProjectGroups(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, From 6cc19fb2a58463fdcd981d6f9ffe74647778040d Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Mon, 19 Aug 2024 17:56:34 +0300 Subject: [PATCH 3/8] fix UT --- internal/services/projects_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/services/projects_test.go b/internal/services/projects_test.go index a04378c03..70e25f273 100644 --- a/internal/services/projects_test.go +++ b/internal/services/projects_test.go @@ -114,7 +114,7 @@ func Test_createProject(t *testing.T) { accessManagementWrapper: &mock.AccessManagementMockWrapper{}, projectGroups: "grp1,grp2", featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, - }, want: "ID-new-project-name", wantErr: true}, + }, want: "", wantErr: true}, {name: "When called with mock fake error model return fake error from project create", args: args{ projectName: "mock-some-error-model", cmd: &cobra.Command{}, @@ -132,7 +132,7 @@ func Test_createProject(t *testing.T) { accessManagementWrapper: &mock.AccessManagementMockWrapper{}, projectGroups: "fake-group-error", featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, - }, want: "ID-new-project-name", wantErr: true}, + }, want: "", wantErr: true}, {name: "When called with a new project name and projectPrivatePackage set to true return the Id of the newly created project", args: args{ projectName: "new-project-name", cmd: &cobra.Command{}, From 70050fc552044cd41393657a2dce8d8e5e2d9248 Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Tue, 20 Aug 2024 08:48:53 +0300 Subject: [PATCH 4/8] change methods names --- internal/services/projects.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/services/projects.go b/internal/services/projects.go index 63a583104..0398723fb 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -112,7 +112,7 @@ func createProject( } if projectGroups != "" { - err = UpsertProjectGroupsInCreate(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, nil, projectGroups, projectID, projectName, featureFlagsWrapper) + err = UpsertProjectGroupsByCreateFlow(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, nil, projectGroups, projectID, projectName, featureFlagsWrapper) if err != nil { return projectID, err } @@ -219,7 +219,7 @@ func updateProject( } if projectGroups != "" { - err = UpsertProjectGroupsInUpdate(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) + err = UpsertProjectGroupsByUpdateFlow(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) if err != nil { return projectID, err } @@ -227,13 +227,13 @@ func updateProject( return projectID, nil } -func UpsertProjectGroupsInCreate(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, +func UpsertProjectGroupsByCreateFlow(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) } -func UpsertProjectGroupsInUpdate(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, +func UpsertProjectGroupsByUpdateFlow(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { _, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModel, projModelResp, featureFlagsWrapper) From 9a6d6007aebfa82f274cc3da12c7d9d5586cb876 Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Tue, 20 Aug 2024 09:16:25 +0300 Subject: [PATCH 5/8] add UT --- internal/services/projects.go | 8 +++++--- internal/services/projects_test.go | 9 +++++++++ internal/wrappers/mock/groups-mock.go | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/internal/services/projects.go b/internal/services/projects.go index 0398723fb..42e4063b9 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -87,9 +87,11 @@ func createProject( var projModel = wrappers.Project{} projModel.Name = projectName projModel.ApplicationIds = applicationID - _, groupErr := GetGroupMap(groupsWrapper, projectGroups, &projModel, nil, featureFlagsWrapper) - if groupErr != nil { - return "", groupErr + if projectGroups != "" { + _, groupErr := GetGroupMap(groupsWrapper, projectGroups, &projModel, nil, featureFlagsWrapper) + if groupErr != nil { + return "", groupErr + } } if projectPrivatePackage != "" { diff --git a/internal/services/projects_test.go b/internal/services/projects_test.go index 70e25f273..7f133d3f2 100644 --- a/internal/services/projects_test.go +++ b/internal/services/projects_test.go @@ -106,6 +106,15 @@ func Test_createProject(t *testing.T) { projectGroups: "", featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, }, want: "ID-new-project-name", wantErr: false}, + {name: "When called with a new project name and existing project groups return the Id of the newly created project", args: args{ + projectName: "new-project-name", + cmd: &cobra.Command{}, + projectsWrapper: &mock.ProjectsMockWrapper{}, + groupsWrapper: &mock.GroupsMockWrapper{}, + accessManagementWrapper: &mock.AccessManagementMockWrapper{}, + projectGroups: "existsGroup1,existsGroup2", + featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, + }, want: "ID-new-project-name", wantErr: false}, {name: "When called with a new project name and non existing project groups return error", args: args{ projectName: "new-project-name", cmd: &cobra.Command{}, diff --git a/internal/wrappers/mock/groups-mock.go b/internal/wrappers/mock/groups-mock.go index 624282cbd..40436672b 100644 --- a/internal/wrappers/mock/groups-mock.go +++ b/internal/wrappers/mock/groups-mock.go @@ -12,5 +12,8 @@ func (g *GroupsMockWrapper) Get(groupName string) ([]wrappers.Group, error) { if groupName == "fake-group-error" { return nil, errors.Errorf("fake grroup error") } + if groupName == "existsGroup1" || groupName == "existsGroup2" { + return []wrappers.Group{{ID: "1", Name: groupName}}, nil + } return []wrappers.Group{{ID: "1", Name: "group"}}, nil } From f5060d3b1d29e7eb4e63b2f434743caf7625f18c Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Tue, 20 Aug 2024 10:53:43 +0300 Subject: [PATCH 6/8] refactoring from CR --- internal/services/groups.go | 14 +++++++------- internal/services/projects.go | 31 ++++++++++++++++--------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/internal/services/groups.go b/internal/services/groups.go index 9a391debb..1e96a086b 100644 --- a/internal/services/groups.go +++ b/internal/services/groups.go @@ -8,18 +8,18 @@ import ( "github.com/pkg/errors" ) -func GetGroupMap(groupsWrapper wrappers.GroupsWrapper, projectGroups string, projModel *wrappers.Project, projModelResp *wrappers.ProjectResponseModel, - featureFlagsWrapper wrappers.FeatureFlagsWrapper) ([]*wrappers.Group, error) { +func GetGroupMap(groupsWrapper wrappers.GroupsWrapper, projectGroups string, projModelResp *wrappers.ProjectResponseModel, + featureFlagsWrapper wrappers.FeatureFlagsWrapper) ([]*wrappers.Group, []string, error) { groupsMap, groupErr := CreateGroupsMap(projectGroups, groupsWrapper) if groupErr != nil { - return nil, errors.Errorf("%s: %v", failedUpdatingProj, groupErr) + return nil, nil, errors.Errorf("%s: %v", failedUpdatingProj, groupErr) } - projModel.Groups = getGroupsForRequest(groupsMap, featureFlagsWrapper) + groups := getGroupsForRequest(groupsMap, featureFlagsWrapper) if projModelResp != nil { - groups := append(getGroupsForRequest(groupsMap, featureFlagsWrapper), projModelResp.Groups...) - projModel.Groups = groups + groups = append(getGroupsForRequest(groupsMap, featureFlagsWrapper), projModelResp.Groups...) + return groupsMap, groups, nil } - return groupsMap, nil + return groupsMap, groups, nil } func CreateGroupsMap(groupsStr string, groupsWrapper wrappers.GroupsWrapper) ([]*wrappers.Group, error) { diff --git a/internal/services/projects.go b/internal/services/projects.go index 42e4063b9..922d7be52 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -87,11 +87,15 @@ func createProject( var projModel = wrappers.Project{} projModel.Name = projectName projModel.ApplicationIds = applicationID + var groupsMap []*wrappers.Group if projectGroups != "" { - _, groupErr := GetGroupMap(groupsWrapper, projectGroups, &projModel, nil, featureFlagsWrapper) + var groups []string + var groupErr error + groupsMap, groups, groupErr = GetGroupMap(groupsWrapper, projectGroups, nil, featureFlagsWrapper) if groupErr != nil { return "", groupErr } + projModel.Groups = groups } if projectPrivatePackage != "" { @@ -114,7 +118,7 @@ func createProject( } if projectGroups != "" { - err = UpsertProjectGroupsByCreateFlow(groupsWrapper, &projModel, projectsWrapper, accessManagementWrapper, nil, projectGroups, projectID, projectName, featureFlagsWrapper) + err = UpsertProjectGroupsByCreateFlow(&projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) if err != nil { return projectID, err } @@ -229,29 +233,26 @@ func updateProject( return projectID, nil } -func UpsertProjectGroupsByCreateFlow(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, - accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, - projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) +func UpsertProjectGroupsByCreateFlow(projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, + accessManagementWrapper wrappers.AccessManagementWrapper, projectID string, projectName string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, groupsMap []*wrappers.Group) error { + return UpsertProjectGroups(projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) } func UpsertProjectGroupsByUpdateFlow(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - _, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModel, projModelResp, featureFlagsWrapper) + groupsMap, groups, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModelResp, featureFlagsWrapper) if groupErr != nil { return groupErr } - return UpsertProjectGroups(groupsWrapper, projModel, projectsWrapper, accessManagementWrapper, projModelResp, projectGroups, projectID, projectName, featureFlagsWrapper) + projModel.Groups = groups + return UpsertProjectGroups(projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) } -func UpsertProjectGroups(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, - accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, - projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - groupsMap, groupErr := GetGroupMap(groupsWrapper, projectGroups, projModel, projModelResp, featureFlagsWrapper) - if groupErr != nil { - return groupErr - } +func UpsertProjectGroups(projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, + accessManagementWrapper wrappers.AccessManagementWrapper, projectID string, projectName string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, groupsMap []*wrappers.Group) error { err := AssignGroupsToProjectNewAccessManagement(projectID, projectName, groupsMap, accessManagementWrapper, featureFlagsWrapper) if err != nil { From a495dcdc034121530138ba0ca5be2fd80920eaa2 Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Tue, 20 Aug 2024 10:59:04 +0300 Subject: [PATCH 7/8] fix for lint --- internal/services/projects.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/services/projects.go b/internal/services/projects.go index 922d7be52..4cffdb6d4 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -253,7 +253,6 @@ func UpsertProjectGroupsByUpdateFlow(groupsWrapper wrappers.GroupsWrapper, projM func UpsertProjectGroups(projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper, groupsMap []*wrappers.Group) error { - err := AssignGroupsToProjectNewAccessManagement(projectID, projectName, groupsMap, accessManagementWrapper, featureFlagsWrapper) if err != nil { return err From 21b5574ab743a8e6b42630364cb67e46d54738de Mon Sep 17 00:00:00 2001 From: miryamfoiferCX Date: Tue, 20 Aug 2024 11:27:53 +0300 Subject: [PATCH 8/8] fix for CR --- internal/services/projects.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/internal/services/projects.go b/internal/services/projects.go index 4cffdb6d4..cfb1b5937 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -118,7 +118,7 @@ func createProject( } if projectGroups != "" { - err = UpsertProjectGroupsByCreateFlow(&projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) + err = UpsertProjectGroups(&projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) if err != nil { return projectID, err } @@ -233,12 +233,6 @@ func updateProject( return projectID, nil } -func UpsertProjectGroupsByCreateFlow(projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, - accessManagementWrapper wrappers.AccessManagementWrapper, projectID string, projectName string, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, groupsMap []*wrappers.Group) error { - return UpsertProjectGroups(projModel, projectsWrapper, accessManagementWrapper, projectID, projectName, featureFlagsWrapper, groupsMap) -} - func UpsertProjectGroupsByUpdateFlow(groupsWrapper wrappers.GroupsWrapper, projModel *wrappers.Project, projectsWrapper wrappers.ProjectsWrapper, accessManagementWrapper wrappers.AccessManagementWrapper, projModelResp *wrappers.ProjectResponseModel, projectGroups string, projectID string, projectName string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error {