Skip to content

Commit 0419c6b

Browse files
authored
feat: Updated repo collaborators to support ignoring teams (integrations#2481)
Signed-off-by: Steve Hipwell <[email protected]>
1 parent 4b77944 commit 0419c6b

3 files changed

+259
-74
lines changed

github/resource_github_repository_collaborators.go

+84-33
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func resourceGithubRepositoryCollaborators() *schema.Resource {
3232
"user": {
3333
Type: schema.TypeSet,
3434
Optional: true,
35-
Description: "List of users",
35+
Description: "List of users.",
3636
Elem: &schema.Resource{
3737
Schema: map[string]*schema.Schema{
3838
"permission": {
@@ -52,7 +52,7 @@ func resourceGithubRepositoryCollaborators() *schema.Resource {
5252
"team": {
5353
Type: schema.TypeSet,
5454
Optional: true,
55-
Description: "List of teams",
55+
Description: "List of teams.",
5656
Elem: &schema.Resource{
5757
Schema: map[string]*schema.Schema{
5858
"permission": {
@@ -76,6 +76,20 @@ func resourceGithubRepositoryCollaborators() *schema.Resource {
7676
},
7777
Computed: true,
7878
},
79+
"ignore_team": {
80+
Type: schema.TypeSet,
81+
Optional: true,
82+
Description: "List of teams to ignore.",
83+
Elem: &schema.Resource{
84+
Schema: map[string]*schema.Schema{
85+
"team_id": {
86+
Type: schema.TypeString,
87+
Description: "ID or slug of the team to ignore.",
88+
Required: true,
89+
},
90+
},
91+
},
92+
},
7993
},
8094

8195
CustomizeDiff: customdiff.Sequence(
@@ -145,16 +159,16 @@ func (c teamCollaborator) Empty() bool {
145159
return c == teamCollaborator{}
146160
}
147161

148-
func flattenTeamCollaborator(obj teamCollaborator, teamIDs []int64) interface{} {
162+
func flattenTeamCollaborator(obj teamCollaborator, teamSlugs []string) interface{} {
149163
if obj.Empty() {
150164
return nil
151165
}
152166

153167
var teamIDString string
154-
if slices.Contains(teamIDs, obj.teamID) {
155-
teamIDString = strconv.FormatInt(obj.teamID, 10)
156-
} else {
168+
if slices.Contains(teamSlugs, obj.teamSlug) {
157169
teamIDString = obj.teamSlug
170+
} else {
171+
teamIDString = strconv.FormatInt(obj.teamID, 10)
158172
}
159173

160174
transformed := map[string]interface{}{
@@ -165,7 +179,7 @@ func flattenTeamCollaborator(obj teamCollaborator, teamIDs []int64) interface{}
165179
return transformed
166180
}
167181

168-
func flattenTeamCollaborators(objs []teamCollaborator, teamIDs []int64) []interface{} {
182+
func flattenTeamCollaborators(objs []teamCollaborator, teamSlugs []string) []interface{} {
169183
if objs == nil {
170184
return nil
171185
}
@@ -176,14 +190,14 @@ func flattenTeamCollaborators(objs []teamCollaborator, teamIDs []int64) []interf
176190

177191
items := make([]interface{}, len(objs))
178192
for i, obj := range objs {
179-
items[i] = flattenTeamCollaborator(obj, teamIDs)
193+
items[i] = flattenTeamCollaborator(obj, teamSlugs)
180194
}
181195

182196
return items
183197
}
184198

185199
func listUserCollaborators(client *github.Client, isOrg bool, ctx context.Context, owner, repoName string) ([]userCollaborator, error) {
186-
var userCollaborators []userCollaborator
200+
userCollaborators := make([]userCollaborator, 0)
187201
affiliations := []string{"direct", "outside"}
188202
for _, affiliation := range affiliations {
189203
opt := &github.ListCollaboratorsOptions{ListOptions: github.ListOptions{
@@ -217,7 +231,7 @@ func listUserCollaborators(client *github.Client, isOrg bool, ctx context.Contex
217231
}
218232

219233
func listInvitations(client *github.Client, ctx context.Context, owner, repoName string) ([]invitedCollaborator, error) {
220-
var invitedCollaborators []invitedCollaborator
234+
invitedCollaborators := make([]invitedCollaborator, 0)
221235

222236
opt := &github.ListOptions{PerPage: maxPerPage}
223237
for {
@@ -230,7 +244,8 @@ func listInvitations(client *github.Client, ctx context.Context, owner, repoName
230244
permissionName := getPermission(i.GetPermissions())
231245

232246
invitedCollaborators = append(invitedCollaborators, invitedCollaborator{
233-
userCollaborator{permissionName, i.GetInvitee().GetLogin()}, i.GetID()})
247+
userCollaborator{permissionName, i.GetInvitee().GetLogin()}, i.GetID(),
248+
})
234249
}
235250

236251
if resp.NextPage == 0 {
@@ -241,11 +256,11 @@ func listInvitations(client *github.Client, ctx context.Context, owner, repoName
241256
return invitedCollaborators, nil
242257
}
243258

244-
func listTeams(client *github.Client, isOrg bool, ctx context.Context, owner, repoName string) ([]teamCollaborator, error) {
245-
var teamCollaborators []teamCollaborator
259+
func listTeams(client *github.Client, isOrg bool, ctx context.Context, owner, repoName string, ignoreTeamIds []int64) ([]teamCollaborator, error) {
260+
allTeams := make([]teamCollaborator, 0)
246261

247262
if !isOrg {
248-
return teamCollaborators, nil
263+
return allTeams, nil
249264
}
250265

251266
opt := &github.ListOptions{PerPage: maxPerPage}
@@ -256,20 +271,23 @@ func listTeams(client *github.Client, isOrg bool, ctx context.Context, owner, re
256271
}
257272

258273
for _, t := range repoTeams {
259-
permissionName := getPermission(t.GetPermission())
274+
if slices.Contains(ignoreTeamIds, t.GetID()) {
275+
continue
276+
}
260277

261-
teamCollaborators = append(teamCollaborators, teamCollaborator{permissionName, t.GetID(), t.GetSlug()})
278+
allTeams = append(allTeams, teamCollaborator{permission: getPermission(t.GetPermission()), teamID: t.GetID(), teamSlug: t.GetSlug()})
262279
}
263280

264281
if resp.NextPage == 0 {
265282
break
266283
}
267284
opt.Page = resp.NextPage
268285
}
269-
return teamCollaborators, nil
286+
287+
return allTeams, nil
270288
}
271289

272-
func listAllCollaborators(client *github.Client, isOrg bool, ctx context.Context, owner, repoName string) ([]userCollaborator, []invitedCollaborator, []teamCollaborator, error) {
290+
func listAllCollaborators(client *github.Client, isOrg bool, ctx context.Context, owner, repoName string, ignoreTeamIds []int64) ([]userCollaborator, []invitedCollaborator, []teamCollaborator, error) {
273291
userCollaborators, err := listUserCollaborators(client, isOrg, ctx, owner, repoName)
274292
if err != nil {
275293
return nil, nil, nil, err
@@ -278,16 +296,14 @@ func listAllCollaborators(client *github.Client, isOrg bool, ctx context.Context
278296
if err != nil {
279297
return nil, nil, nil, err
280298
}
281-
teamCollaborators, err := listTeams(client, isOrg, ctx, owner, repoName)
299+
teamCollaborators, err := listTeams(client, isOrg, ctx, owner, repoName, ignoreTeamIds)
282300
if err != nil {
283301
return nil, nil, nil, err
284302
}
285303
return userCollaborators, invitations, teamCollaborators, err
286304
}
287305

288-
func matchUserCollaboratorsAndInvites(
289-
repoName string, want []interface{}, hasUsers []userCollaborator, hasInvites []invitedCollaborator,
290-
meta interface{}) error {
306+
func matchUserCollaboratorsAndInvites(repoName string, want []interface{}, hasUsers []userCollaborator, hasInvites []invitedCollaborator, meta interface{}) error {
291307
client := meta.(*Owner).v3client
292308

293309
owner := meta.(*Owner).name
@@ -383,8 +399,7 @@ func matchUserCollaboratorsAndInvites(
383399
return nil
384400
}
385401

386-
func matchTeamCollaborators(
387-
repoName string, want []interface{}, has []teamCollaborator, meta interface{}) error {
402+
func matchTeamCollaborators(repoName string, want []interface{}, has []teamCollaborator, meta interface{}) error {
388403
client := meta.(*Owner).v3client
389404
orgID := meta.(*Owner).id
390405
owner := meta.(*Owner).name
@@ -471,15 +486,15 @@ func resourceGithubRepositoryCollaboratorsCreate(d *schema.ResourceData, meta in
471486
repoName := d.Get("repository").(string)
472487
ctx := context.Background()
473488

474-
teamsMap := make(map[string]struct{})
489+
teamsMap := make(map[string]struct{}, len(teams))
475490
for _, team := range teams {
476491
teamIDString := team.(map[string]interface{})["team_id"].(string)
477492
if _, found := teamsMap[teamIDString]; found {
478493
return fmt.Errorf("duplicate set member: %s", teamIDString)
479494
}
480495
teamsMap[teamIDString] = struct{}{}
481496
}
482-
usersMap := make(map[string]struct{})
497+
usersMap := make(map[string]struct{}, len(users))
483498
for _, user := range users {
484499
username := user.(map[string]interface{})["username"].(string)
485500
if _, found := usersMap[username]; found {
@@ -488,7 +503,12 @@ func resourceGithubRepositoryCollaboratorsCreate(d *schema.ResourceData, meta in
488503
usersMap[username] = struct{}{}
489504
}
490505

491-
userCollaborators, invitations, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName)
506+
ignoreTeamIds, err := getIgnoreTeamIds(d, meta)
507+
if err != nil {
508+
return err
509+
}
510+
511+
userCollaborators, invitations, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName, ignoreTeamIds)
492512
if err != nil {
493513
return deleteResourceOn404AndSwallow304OtherwiseReturnError(err, d, "repository collaborators (%s/%s)", owner, repoName)
494514
}
@@ -516,7 +536,12 @@ func resourceGithubRepositoryCollaboratorsRead(d *schema.ResourceData, meta inte
516536
repoName := d.Id()
517537
ctx := context.WithValue(context.Background(), ctxId, d.Id())
518538

519-
userCollaborators, invitedCollaborators, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName)
539+
ignoreTeamIds, err := getIgnoreTeamIds(d, meta)
540+
if err != nil {
541+
return err
542+
}
543+
544+
userCollaborators, invitedCollaborators, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName, ignoreTeamIds)
520545
if err != nil {
521546
return deleteResourceOn404AndSwallow304OtherwiseReturnError(err, d, "repository collaborators (%s/%s)", owner, repoName)
522547
}
@@ -526,9 +551,14 @@ func resourceGithubRepositoryCollaboratorsRead(d *schema.ResourceData, meta inte
526551
invitationIds[i.username] = strconv.FormatInt(i.invitationID, 10)
527552
}
528553

529-
teamIDs := make([]int64, len(teamCollaborators))
530-
for i, t := range teamCollaborators {
531-
teamIDs[i] = t.teamID
554+
sourceTeams := d.Get("team").(*schema.Set).List()
555+
teamSlugs := make([]string, len(sourceTeams))
556+
for i, t := range sourceTeams {
557+
teamIdString := t.(map[string]interface{})["team_id"].(string)
558+
_, parseIntErr := strconv.ParseInt(teamIdString, 10, 64)
559+
if parseIntErr != nil {
560+
teamSlugs[i] = teamIdString
561+
}
532562
}
533563

534564
err = d.Set("repository", repoName)
@@ -539,7 +569,7 @@ func resourceGithubRepositoryCollaboratorsRead(d *schema.ResourceData, meta inte
539569
if err != nil {
540570
return err
541571
}
542-
err = d.Set("team", flattenTeamCollaborators(teamCollaborators, teamIDs))
572+
err = d.Set("team", flattenTeamCollaborators(teamCollaborators, teamSlugs))
543573
if err != nil {
544574
return err
545575
}
@@ -563,7 +593,12 @@ func resourceGithubRepositoryCollaboratorsDelete(d *schema.ResourceData, meta in
563593
repoName := d.Get("repository").(string)
564594
ctx := context.Background()
565595

566-
userCollaborators, invitations, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName)
596+
ignoreTeamIds, err := getIgnoreTeamIds(d, meta)
597+
if err != nil {
598+
return err
599+
}
600+
601+
userCollaborators, invitations, teamCollaborators, err := listAllCollaborators(client, isOrg, ctx, owner, repoName, ignoreTeamIds)
567602
if err != nil {
568603
return deleteResourceOn404AndSwallow304OtherwiseReturnError(err, d, "repository collaborators (%s/%s)", owner, repoName)
569604
}
@@ -580,3 +615,19 @@ func resourceGithubRepositoryCollaboratorsDelete(d *schema.ResourceData, meta in
580615
err = matchTeamCollaborators(repoName, nil, teamCollaborators, meta)
581616
return err
582617
}
618+
619+
func getIgnoreTeamIds(d *schema.ResourceData, meta interface{}) ([]int64, error) {
620+
ignoreTeams := d.Get("ignore_team").(*schema.Set).List()
621+
ignoreTeamIds := make([]int64, len(ignoreTeams))
622+
623+
for i, t := range ignoreTeams {
624+
s := t.(map[string]interface{})["team_id"].(string)
625+
id, err := getTeamID(s, meta)
626+
if err != nil {
627+
return nil, err
628+
}
629+
ignoreTeamIds[i] = id
630+
}
631+
632+
return ignoreTeamIds, nil
633+
}

0 commit comments

Comments
 (0)