@@ -4,32 +4,56 @@ import (
44 "context"
55 "errors"
66 "fmt"
7+ "reflect"
78 "strconv"
89
910 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1011 "github.com/shurcooL/githubv4"
1112)
1213
13- // getUserNodeId retrieves the GraphQL node ID for a given username
14- func getUserNodeId (ctx context.Context , meta interface {}, username string ) (string , error ) {
14+ // getBatchUserNodeIds retrieves the GraphQL node IDs for multiple usernames in a single request.
15+ func getBatchUserNodeIds (ctx context.Context , meta any , usernames []string ) (map [string ]string , error ) {
16+ if len (usernames ) == 0 {
17+ return make (map [string ]string ), nil
18+ }
19+
1520 client := meta .(* Owner ).v4client
1621
17- var query struct {
18- User struct {
19- ID githubv4.ID `graphql:"id"`
20- } `graphql:"user(login: $username)"`
22+ // Create GraphQL variables and query struct using reflection (similar to data_source_github_users.go)
23+ type UserFragment struct {
24+ ID githubv4.ID `graphql:"id"`
2125 }
2226
23- variables := map [string ]interface {}{
24- "username" : githubv4 .String (username ),
27+ var fields []reflect.StructField
28+ variables := make (map [string ]any )
29+
30+ for idx , username := range usernames {
31+ label := fmt .Sprintf ("User%d" , idx )
32+ variables [label ] = githubv4 .String (username )
33+ fields = append (fields , reflect.StructField {
34+ Name : label ,
35+ Type : reflect .TypeFor [UserFragment ](),
36+ Tag : reflect .StructTag (fmt .Sprintf ("graphql:\" %[1]s: user(login: $%[1]s)\" " , label )),
37+ })
2538 }
2639
27- err := client .Query (ctx , & query , variables )
40+ query := reflect .New (reflect .StructOf (fields )).Elem ()
41+
42+ err := client .Query (ctx , query .Addr ().Interface (), variables )
2843 if err != nil {
29- return "" , fmt .Errorf ("failed to query user %s: %v" , username , err )
44+ return nil , fmt .Errorf ("failed to query users in batch: %w" , err )
45+ }
46+
47+ result := make (map [string ]string )
48+ for idx , username := range usernames {
49+ label := fmt .Sprintf ("User%d" , idx )
50+ user := query .FieldByName (label ).Interface ().(UserFragment )
51+ if user .ID != "" {
52+ result [username ] = string (user .ID .(githubv4.String ))
53+ }
3054 }
3155
32- return string ( query . User . ID .(githubv4. String )) , nil
56+ return result , nil
3357}
3458
3559func resourceGithubTeamSettings () * schema.Resource {
@@ -212,14 +236,29 @@ func resourceGithubTeamSettingsUpdate(d *schema.ResourceData, meta any) error {
212236
213237 exclusionList := make ([]githubv4.ID , 0 )
214238 if excludedMembers , ok := settings ["excluded_team_members" ]; ok && excludedMembers != nil {
239+ // Collect all usernames first
240+ usernames := make ([]string , 0 )
215241 for _ , v := range excludedMembers .(* schema.Set ).List () {
216242 if v != nil {
217243 username := v .(string )
218- nodeId , err := getUserNodeId (ctx , meta , username )
219- if err != nil {
220- return fmt .Errorf ("failed to get node ID for user %s: %v" , username , err )
244+ usernames = append (usernames , username )
245+ }
246+ }
247+
248+ // Get all node IDs in a single batch request
249+ if len (usernames ) > 0 {
250+ nodeIds , err := getBatchUserNodeIds (ctx , meta , usernames )
251+ if err != nil {
252+ return fmt .Errorf ("failed to get node IDs for excluded members: %w" , err )
253+ }
254+
255+ // Convert to the exclusion list
256+ for _ , username := range usernames {
257+ if nodeId , exists := nodeIds [username ]; exists {
258+ exclusionList = append (exclusionList , githubv4 .ID (nodeId ))
259+ } else {
260+ return fmt .Errorf ("failed to get node ID for user %s: user not found" , username )
221261 }
222- exclusionList = append (exclusionList , githubv4 .ID (nodeId ))
223262 }
224263 }
225264 }
0 commit comments