github.com/google/go-github/v68@v68.0.0/github/teams.go (about)

     1  // Copyright 2018 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"net/http"
    12  )
    13  
    14  // TeamsService provides access to the team-related functions
    15  // in the GitHub API.
    16  //
    17  // GitHub API docs: https://docs.github.com/rest/teams/
    18  type TeamsService service
    19  
    20  // Team represents a team within a GitHub organization. Teams are used to
    21  // manage access to an organization's repositories.
    22  type Team struct {
    23  	ID          *int64  `json:"id,omitempty"`
    24  	NodeID      *string `json:"node_id,omitempty"`
    25  	Name        *string `json:"name,omitempty"`
    26  	Description *string `json:"description,omitempty"`
    27  	URL         *string `json:"url,omitempty"`
    28  	Slug        *string `json:"slug,omitempty"`
    29  
    30  	// Permission specifies the default permission for repositories owned by the team.
    31  	Permission *string `json:"permission,omitempty"`
    32  
    33  	// Privacy identifies the level of privacy this team should have.
    34  	// Possible values are:
    35  	//     secret - only visible to organization owners and members of this team
    36  	//     closed - visible to all members of this organization
    37  	// Default is "secret".
    38  	Privacy *string `json:"privacy,omitempty"`
    39  
    40  	MembersCount    *int          `json:"members_count,omitempty"`
    41  	ReposCount      *int          `json:"repos_count,omitempty"`
    42  	Organization    *Organization `json:"organization,omitempty"`
    43  	HTMLURL         *string       `json:"html_url,omitempty"`
    44  	MembersURL      *string       `json:"members_url,omitempty"`
    45  	RepositoriesURL *string       `json:"repositories_url,omitempty"`
    46  	Parent          *Team         `json:"parent,omitempty"`
    47  
    48  	// LDAPDN is only available in GitHub Enterprise and when the team
    49  	// membership is synchronized with LDAP.
    50  	LDAPDN *string `json:"ldap_dn,omitempty"`
    51  
    52  	// Permissions identifies the permissions that a team has on a given
    53  	// repository. This is only populated when calling Repositories.ListTeams.
    54  	Permissions map[string]bool `json:"permissions,omitempty"`
    55  
    56  	// Assignment identifies how a team was assigned to an organization role. Its
    57  	// possible values are: "direct", "indirect", "mixed". This is only populated when
    58  	// calling the ListTeamsAssignedToOrgRole method.
    59  	Assignment *string `json:"assignment,omitempty"`
    60  }
    61  
    62  func (t Team) String() string {
    63  	return Stringify(t)
    64  }
    65  
    66  // Invitation represents a team member's invitation status.
    67  type Invitation struct {
    68  	ID     *int64  `json:"id,omitempty"`
    69  	NodeID *string `json:"node_id,omitempty"`
    70  	Login  *string `json:"login,omitempty"`
    71  	Email  *string `json:"email,omitempty"`
    72  	// Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'.
    73  	Role              *string    `json:"role,omitempty"`
    74  	CreatedAt         *Timestamp `json:"created_at,omitempty"`
    75  	Inviter           *User      `json:"inviter,omitempty"`
    76  	TeamCount         *int       `json:"team_count,omitempty"`
    77  	InvitationTeamURL *string    `json:"invitation_team_url,omitempty"`
    78  	FailedAt          *Timestamp `json:"failed_at,omitempty"`
    79  	FailedReason      *string    `json:"failed_reason,omitempty"`
    80  }
    81  
    82  func (i Invitation) String() string {
    83  	return Stringify(i)
    84  }
    85  
    86  // ListTeams lists all of the teams for an organization.
    87  //
    88  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams
    89  //
    90  //meta:operation GET /orgs/{org}/teams
    91  func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) {
    92  	u := fmt.Sprintf("orgs/%v/teams", org)
    93  	u, err := addOptions(u, opts)
    94  	if err != nil {
    95  		return nil, nil, err
    96  	}
    97  
    98  	req, err := s.client.NewRequest("GET", u, nil)
    99  	if err != nil {
   100  		return nil, nil, err
   101  	}
   102  
   103  	var teams []*Team
   104  	resp, err := s.client.Do(ctx, req, &teams)
   105  	if err != nil {
   106  		return nil, resp, err
   107  	}
   108  
   109  	return teams, resp, nil
   110  }
   111  
   112  // GetTeamByID fetches a team, given a specified organization ID, by ID.
   113  //
   114  // Deprecated: Use GetTeamBySlug instead.
   115  //
   116  // GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name
   117  //
   118  //meta:operation GET /orgs/{org}/teams/{team_slug}
   119  func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) {
   120  	u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
   121  	req, err := s.client.NewRequest("GET", u, nil)
   122  	if err != nil {
   123  		return nil, nil, err
   124  	}
   125  
   126  	t := new(Team)
   127  	resp, err := s.client.Do(ctx, req, t)
   128  	if err != nil {
   129  		return nil, resp, err
   130  	}
   131  
   132  	return t, resp, nil
   133  }
   134  
   135  // GetTeamBySlug fetches a team, given a specified organization name, by slug.
   136  //
   137  // GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name
   138  //
   139  //meta:operation GET /orgs/{org}/teams/{team_slug}
   140  func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) {
   141  	u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
   142  	req, err := s.client.NewRequest("GET", u, nil)
   143  	if err != nil {
   144  		return nil, nil, err
   145  	}
   146  
   147  	t := new(Team)
   148  	resp, err := s.client.Do(ctx, req, t)
   149  	if err != nil {
   150  		return nil, resp, err
   151  	}
   152  
   153  	return t, resp, nil
   154  }
   155  
   156  // NewTeam represents a team to be created or modified.
   157  type NewTeam struct {
   158  	Name         string   `json:"name"` // Name of the team. (Required.)
   159  	Description  *string  `json:"description,omitempty"`
   160  	Maintainers  []string `json:"maintainers,omitempty"`
   161  	RepoNames    []string `json:"repo_names,omitempty"`
   162  	ParentTeamID *int64   `json:"parent_team_id,omitempty"`
   163  
   164  	// NotificationSetting can be one of: "notifications_enabled", "notifications_disabled".
   165  	NotificationSetting *string `json:"notification_setting,omitempty"`
   166  
   167  	// Deprecated: Permission is deprecated when creating or editing a team in an org
   168  	// using the new GitHub permission model. It no longer identifies the
   169  	// permission a team has on its repos, but only specifies the default
   170  	// permission a repo is initially added with. Avoid confusion by
   171  	// specifying a permission value when calling AddTeamRepo.
   172  	Permission *string `json:"permission,omitempty"`
   173  
   174  	// Privacy identifies the level of privacy this team should have.
   175  	// Possible values are:
   176  	//     secret - only visible to organization owners and members of this team
   177  	//     closed - visible to all members of this organization
   178  	// Default is "secret".
   179  	Privacy *string `json:"privacy,omitempty"`
   180  
   181  	// LDAPDN may be used in GitHub Enterprise when the team membership
   182  	// is synchronized with LDAP.
   183  	LDAPDN *string `json:"ldap_dn,omitempty"`
   184  }
   185  
   186  func (s NewTeam) String() string {
   187  	return Stringify(s)
   188  }
   189  
   190  // CreateTeam creates a new team within an organization.
   191  //
   192  // GitHub API docs: https://docs.github.com/rest/teams/teams#create-a-team
   193  //
   194  //meta:operation POST /orgs/{org}/teams
   195  func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) {
   196  	u := fmt.Sprintf("orgs/%v/teams", org)
   197  	req, err := s.client.NewRequest("POST", u, team)
   198  	if err != nil {
   199  		return nil, nil, err
   200  	}
   201  
   202  	t := new(Team)
   203  	resp, err := s.client.Do(ctx, req, t)
   204  	if err != nil {
   205  		return nil, resp, err
   206  	}
   207  
   208  	return t, resp, nil
   209  }
   210  
   211  // newTeamNoParent is the same as NewTeam but ensures that the
   212  // "parent_team_id" field will be null. It is for internal use
   213  // only and should not be exported.
   214  type newTeamNoParent struct {
   215  	Name                string   `json:"name"`
   216  	Description         *string  `json:"description,omitempty"`
   217  	Maintainers         []string `json:"maintainers,omitempty"`
   218  	RepoNames           []string `json:"repo_names,omitempty"`
   219  	ParentTeamID        *int64   `json:"parent_team_id"` // This will be "null"
   220  	NotificationSetting *string  `json:"notification_setting,omitempty"`
   221  	Privacy             *string  `json:"privacy,omitempty"`
   222  	LDAPDN              *string  `json:"ldap_dn,omitempty"`
   223  }
   224  
   225  // copyNewTeamWithoutParent is used to set the "parent_team_id"
   226  // field to "null" after copying the other fields from a NewTeam.
   227  // It is for internal use only and should not be exported.
   228  func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent {
   229  	return &newTeamNoParent{
   230  		Name:                team.Name,
   231  		Description:         team.Description,
   232  		Maintainers:         team.Maintainers,
   233  		RepoNames:           team.RepoNames,
   234  		NotificationSetting: team.NotificationSetting,
   235  		Privacy:             team.Privacy,
   236  		LDAPDN:              team.LDAPDN,
   237  	}
   238  }
   239  
   240  // EditTeamByID edits a team, given an organization ID, selected by ID.
   241  //
   242  // Deprecated: Use EditTeamBySlug instead.
   243  //
   244  // GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team
   245  //
   246  //meta:operation PATCH /orgs/{org}/teams/{team_slug}
   247  func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) {
   248  	u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
   249  
   250  	var req *http.Request
   251  	var err error
   252  	if removeParent {
   253  		teamRemoveParent := copyNewTeamWithoutParent(&team)
   254  		req, err = s.client.NewRequest("PATCH", u, teamRemoveParent)
   255  	} else {
   256  		req, err = s.client.NewRequest("PATCH", u, team)
   257  	}
   258  	if err != nil {
   259  		return nil, nil, err
   260  	}
   261  
   262  	t := new(Team)
   263  	resp, err := s.client.Do(ctx, req, t)
   264  	if err != nil {
   265  		return nil, resp, err
   266  	}
   267  
   268  	return t, resp, nil
   269  }
   270  
   271  // EditTeamBySlug edits a team, given an organization name, by slug.
   272  //
   273  // GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team
   274  //
   275  //meta:operation PATCH /orgs/{org}/teams/{team_slug}
   276  func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) {
   277  	u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
   278  
   279  	var req *http.Request
   280  	var err error
   281  	if removeParent {
   282  		teamRemoveParent := copyNewTeamWithoutParent(&team)
   283  		req, err = s.client.NewRequest("PATCH", u, teamRemoveParent)
   284  	} else {
   285  		req, err = s.client.NewRequest("PATCH", u, team)
   286  	}
   287  	if err != nil {
   288  		return nil, nil, err
   289  	}
   290  
   291  	t := new(Team)
   292  	resp, err := s.client.Do(ctx, req, t)
   293  	if err != nil {
   294  		return nil, resp, err
   295  	}
   296  
   297  	return t, resp, nil
   298  }
   299  
   300  // DeleteTeamByID deletes a team referenced by ID.
   301  //
   302  // Deprecated: Use DeleteTeamBySlug instead.
   303  //
   304  // GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team
   305  //
   306  //meta:operation DELETE /orgs/{org}/teams/{team_slug}
   307  func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) {
   308  	u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID)
   309  	req, err := s.client.NewRequest("DELETE", u, nil)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  
   314  	return s.client.Do(ctx, req, nil)
   315  }
   316  
   317  // DeleteTeamBySlug deletes a team reference by slug.
   318  //
   319  // GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team
   320  //
   321  //meta:operation DELETE /orgs/{org}/teams/{team_slug}
   322  func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) {
   323  	u := fmt.Sprintf("orgs/%v/teams/%v", org, slug)
   324  	req, err := s.client.NewRequest("DELETE", u, nil)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	return s.client.Do(ctx, req, nil)
   330  }
   331  
   332  // ListChildTeamsByParentID lists child teams for a parent team given parent ID.
   333  //
   334  // Deprecated: Use ListChildTeamsByParentSlug instead.
   335  //
   336  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams
   337  //
   338  //meta:operation GET /orgs/{org}/teams/{team_slug}/teams
   339  func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) {
   340  	u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID)
   341  	u, err := addOptions(u, opts)
   342  	if err != nil {
   343  		return nil, nil, err
   344  	}
   345  
   346  	req, err := s.client.NewRequest("GET", u, nil)
   347  	if err != nil {
   348  		return nil, nil, err
   349  	}
   350  
   351  	var teams []*Team
   352  	resp, err := s.client.Do(ctx, req, &teams)
   353  	if err != nil {
   354  		return nil, resp, err
   355  	}
   356  
   357  	return teams, resp, nil
   358  }
   359  
   360  // ListChildTeamsByParentSlug lists child teams for a parent team given parent slug.
   361  //
   362  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams
   363  //
   364  //meta:operation GET /orgs/{org}/teams/{team_slug}/teams
   365  func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) {
   366  	u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug)
   367  	u, err := addOptions(u, opts)
   368  	if err != nil {
   369  		return nil, nil, err
   370  	}
   371  
   372  	req, err := s.client.NewRequest("GET", u, nil)
   373  	if err != nil {
   374  		return nil, nil, err
   375  	}
   376  
   377  	var teams []*Team
   378  	resp, err := s.client.Do(ctx, req, &teams)
   379  	if err != nil {
   380  		return nil, resp, err
   381  	}
   382  
   383  	return teams, resp, nil
   384  }
   385  
   386  // ListTeamReposByID lists the repositories given a team ID that the specified team has access to.
   387  //
   388  // Deprecated: Use ListTeamReposBySlug instead.
   389  //
   390  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories
   391  //
   392  //meta:operation GET /orgs/{org}/teams/{team_slug}/repos
   393  func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) {
   394  	u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID)
   395  	u, err := addOptions(u, opts)
   396  	if err != nil {
   397  		return nil, nil, err
   398  	}
   399  
   400  	req, err := s.client.NewRequest("GET", u, nil)
   401  	if err != nil {
   402  		return nil, nil, err
   403  	}
   404  
   405  	// TODO: remove custom Accept header when topics API fully launches.
   406  	req.Header.Set("Accept", mediaTypeTopicsPreview)
   407  
   408  	var repos []*Repository
   409  	resp, err := s.client.Do(ctx, req, &repos)
   410  	if err != nil {
   411  		return nil, resp, err
   412  	}
   413  
   414  	return repos, resp, nil
   415  }
   416  
   417  // ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to.
   418  //
   419  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories
   420  //
   421  //meta:operation GET /orgs/{org}/teams/{team_slug}/repos
   422  func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) {
   423  	u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug)
   424  	u, err := addOptions(u, opts)
   425  	if err != nil {
   426  		return nil, nil, err
   427  	}
   428  
   429  	req, err := s.client.NewRequest("GET", u, nil)
   430  	if err != nil {
   431  		return nil, nil, err
   432  	}
   433  
   434  	// TODO: remove custom Accept header when topics API fully launches.
   435  	req.Header.Set("Accept", mediaTypeTopicsPreview)
   436  
   437  	var repos []*Repository
   438  	resp, err := s.client.Do(ctx, req, &repos)
   439  	if err != nil {
   440  		return nil, resp, err
   441  	}
   442  
   443  	return repos, resp, nil
   444  }
   445  
   446  // IsTeamRepoByID checks if a team, given its ID, manages the specified repository. If the
   447  // repository is managed by team, a Repository is returned which includes the
   448  // permissions team has for that repo.
   449  //
   450  // Deprecated: Use IsTeamRepoBySlug instead.
   451  //
   452  // GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository
   453  //
   454  //meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   455  func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) {
   456  	u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
   457  	req, err := s.client.NewRequest("GET", u, nil)
   458  	if err != nil {
   459  		return nil, nil, err
   460  	}
   461  
   462  	req.Header.Set("Accept", mediaTypeOrgPermissionRepo)
   463  
   464  	repository := new(Repository)
   465  	resp, err := s.client.Do(ctx, req, repository)
   466  	if err != nil {
   467  		return nil, resp, err
   468  	}
   469  
   470  	return repository, resp, nil
   471  }
   472  
   473  // IsTeamRepoBySlug checks if a team, given its slug, manages the specified repository. If the
   474  // repository is managed by team, a Repository is returned which includes the
   475  // permissions team has for that repo.
   476  //
   477  // GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository
   478  //
   479  //meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   480  func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) {
   481  	u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
   482  	req, err := s.client.NewRequest("GET", u, nil)
   483  	if err != nil {
   484  		return nil, nil, err
   485  	}
   486  
   487  	req.Header.Set("Accept", mediaTypeOrgPermissionRepo)
   488  
   489  	repository := new(Repository)
   490  	resp, err := s.client.Do(ctx, req, repository)
   491  	if err != nil {
   492  		return nil, resp, err
   493  	}
   494  
   495  	return repository, resp, nil
   496  }
   497  
   498  // TeamAddTeamRepoOptions specifies the optional parameters to the
   499  // TeamsService.AddTeamRepoByID and TeamsService.AddTeamRepoBySlug methods.
   500  type TeamAddTeamRepoOptions struct {
   501  	// Permission specifies the permission to grant the team on this repository.
   502  	// Possible values are:
   503  	//     pull - team members can pull, but not push to or administer this repository
   504  	//     push - team members can pull and push, but not administer this repository
   505  	//     admin - team members can pull, push and administer this repository
   506  	//     maintain - team members can manage the repository without access to sensitive or destructive actions.
   507  	//     triage - team members can proactively manage issues and pull requests without write access.
   508  	//
   509  	// If not specified, the team's permission attribute will be used.
   510  	Permission string `json:"permission,omitempty"`
   511  }
   512  
   513  // AddTeamRepoByID adds a repository to be managed by the specified team given the team ID.
   514  // The specified repository must be owned by the organization to which the team
   515  // belongs, or a direct fork of a repository owned by the organization.
   516  //
   517  // Deprecated: Use AddTeamRepoBySlug instead.
   518  //
   519  // GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions
   520  //
   521  //meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   522  func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) {
   523  	u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
   524  	req, err := s.client.NewRequest("PUT", u, opts)
   525  	if err != nil {
   526  		return nil, err
   527  	}
   528  
   529  	return s.client.Do(ctx, req, nil)
   530  }
   531  
   532  // AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug.
   533  // The specified repository must be owned by the organization to which the team
   534  // belongs, or a direct fork of a repository owned by the organization.
   535  //
   536  // GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions
   537  //
   538  //meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   539  func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) {
   540  	u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
   541  	req, err := s.client.NewRequest("PUT", u, opts)
   542  	if err != nil {
   543  		return nil, err
   544  	}
   545  
   546  	return s.client.Do(ctx, req, nil)
   547  }
   548  
   549  // RemoveTeamRepoByID removes a repository from being managed by the specified
   550  // team given the team ID. Note that this does not delete the repository, it
   551  // just removes it from the team.
   552  //
   553  // Deprecated: Use RemoveTeamRepoBySlug instead.
   554  //
   555  // GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team
   556  //
   557  //meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   558  func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) {
   559  	u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo)
   560  	req, err := s.client.NewRequest("DELETE", u, nil)
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  
   565  	return s.client.Do(ctx, req, nil)
   566  }
   567  
   568  // RemoveTeamRepoBySlug removes a repository from being managed by the specified
   569  // team given the team slug. Note that this does not delete the repository, it
   570  // just removes it from the team.
   571  //
   572  // GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team
   573  //
   574  //meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}
   575  func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) {
   576  	u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo)
   577  	req, err := s.client.NewRequest("DELETE", u, nil)
   578  	if err != nil {
   579  		return nil, err
   580  	}
   581  
   582  	return s.client.Do(ctx, req, nil)
   583  }
   584  
   585  // ListUserTeams lists a user's teams
   586  //
   587  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams-for-the-authenticated-user
   588  //
   589  //meta:operation GET /user/teams
   590  func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) {
   591  	u := "user/teams"
   592  	u, err := addOptions(u, opts)
   593  	if err != nil {
   594  		return nil, nil, err
   595  	}
   596  
   597  	req, err := s.client.NewRequest("GET", u, nil)
   598  	if err != nil {
   599  		return nil, nil, err
   600  	}
   601  
   602  	var teams []*Team
   603  	resp, err := s.client.Do(ctx, req, &teams)
   604  	if err != nil {
   605  		return nil, resp, err
   606  	}
   607  
   608  	return teams, resp, nil
   609  }
   610  
   611  // ListTeamProjectsByID lists the organization projects for a team given the team ID.
   612  //
   613  // Deprecated: Use ListTeamProjectsBySlug instead.
   614  //
   615  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects
   616  //
   617  //meta:operation GET /orgs/{org}/teams/{team_slug}/projects
   618  func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*ProjectV2, *Response, error) {
   619  	u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID)
   620  
   621  	req, err := s.client.NewRequest("GET", u, nil)
   622  	if err != nil {
   623  		return nil, nil, err
   624  	}
   625  
   626  	// TODO: remove custom Accept header when this API fully launches.
   627  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   628  
   629  	var projects []*ProjectV2
   630  	resp, err := s.client.Do(ctx, req, &projects)
   631  	if err != nil {
   632  		return nil, resp, err
   633  	}
   634  
   635  	return projects, resp, nil
   636  }
   637  
   638  // ListTeamProjectsBySlug lists the organization projects for a team given the team slug.
   639  //
   640  // GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects
   641  //
   642  //meta:operation GET /orgs/{org}/teams/{team_slug}/projects
   643  func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*ProjectV2, *Response, error) {
   644  	u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug)
   645  
   646  	req, err := s.client.NewRequest("GET", u, nil)
   647  	if err != nil {
   648  		return nil, nil, err
   649  	}
   650  
   651  	// TODO: remove custom Accept header when this API fully launches.
   652  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   653  
   654  	var projects []*ProjectV2
   655  	resp, err := s.client.Do(ctx, req, &projects)
   656  	if err != nil {
   657  		return nil, resp, err
   658  	}
   659  
   660  	return projects, resp, nil
   661  }
   662  
   663  // ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin
   664  // permissions for an organization project.
   665  //
   666  // Deprecated: Use ReviewTeamProjectsBySlug instead.
   667  //
   668  // GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project
   669  //
   670  //meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id}
   671  func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*ProjectV2, *Response, error) {
   672  	u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
   673  	req, err := s.client.NewRequest("GET", u, nil)
   674  	if err != nil {
   675  		return nil, nil, err
   676  	}
   677  
   678  	// TODO: remove custom Accept header when this API fully launches.
   679  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   680  
   681  	projects := &ProjectV2{}
   682  	resp, err := s.client.Do(ctx, req, &projects)
   683  	if err != nil {
   684  		return nil, resp, err
   685  	}
   686  
   687  	return projects, resp, nil
   688  }
   689  
   690  // ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin
   691  // permissions for an organization project.
   692  //
   693  // GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project
   694  //
   695  //meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id}
   696  func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*ProjectV2, *Response, error) {
   697  	u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
   698  	req, err := s.client.NewRequest("GET", u, nil)
   699  	if err != nil {
   700  		return nil, nil, err
   701  	}
   702  
   703  	// TODO: remove custom Accept header when this API fully launches.
   704  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   705  
   706  	projects := &ProjectV2{}
   707  	resp, err := s.client.Do(ctx, req, &projects)
   708  	if err != nil {
   709  		return nil, resp, err
   710  	}
   711  
   712  	return projects, resp, nil
   713  }
   714  
   715  // TeamProjectOptions specifies the optional parameters to the
   716  // TeamsService.AddTeamProject method.
   717  type TeamProjectOptions struct {
   718  	// Permission specifies the permission to grant to the team for this project.
   719  	// Possible values are:
   720  	//     "read" - team members can read, but not write to or administer this project.
   721  	//     "write" - team members can read and write, but not administer this project.
   722  	//     "admin" - team members can read, write and administer this project.
   723  	//
   724  	Permission *string `json:"permission,omitempty"`
   725  }
   726  
   727  // AddTeamProjectByID adds an organization project to a team given the team ID.
   728  // To add a project to a team or update the team's permission on a project, the
   729  // authenticated user must have admin permissions for the project.
   730  //
   731  // Deprecated: Use AddTeamProjectBySlug instead.
   732  //
   733  // GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions
   734  //
   735  //meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}
   736  func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) {
   737  	u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
   738  	req, err := s.client.NewRequest("PUT", u, opts)
   739  	if err != nil {
   740  		return nil, err
   741  	}
   742  
   743  	// TODO: remove custom Accept header when this API fully launches.
   744  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   745  
   746  	return s.client.Do(ctx, req, nil)
   747  }
   748  
   749  // AddTeamProjectBySlug adds an organization project to a team given the team slug.
   750  // To add a project to a team or update the team's permission on a project, the
   751  // authenticated user must have admin permissions for the project.
   752  //
   753  // GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions
   754  //
   755  //meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}
   756  func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) {
   757  	u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
   758  	req, err := s.client.NewRequest("PUT", u, opts)
   759  	if err != nil {
   760  		return nil, err
   761  	}
   762  
   763  	// TODO: remove custom Accept header when this API fully launches.
   764  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   765  
   766  	return s.client.Do(ctx, req, nil)
   767  }
   768  
   769  // RemoveTeamProjectByID removes an organization project from a team given team ID.
   770  // An organization owner or a team maintainer can remove any project from the team.
   771  // To remove a project from a team as an organization member, the authenticated user
   772  // must have "read" access to both the team and project, or "admin" access to the team
   773  // or project.
   774  // Note: This endpoint removes the project from the team, but does not delete it.
   775  //
   776  // Deprecated: Use RemoveTeamProjectBySlug instead.
   777  //
   778  // GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team
   779  //
   780  //meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}
   781  func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) {
   782  	u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID)
   783  	req, err := s.client.NewRequest("DELETE", u, nil)
   784  	if err != nil {
   785  		return nil, err
   786  	}
   787  
   788  	// TODO: remove custom Accept header when this API fully launches.
   789  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   790  
   791  	return s.client.Do(ctx, req, nil)
   792  }
   793  
   794  // RemoveTeamProjectBySlug removes an organization project from a team given team slug.
   795  // An organization owner or a team maintainer can remove any project from the team.
   796  // To remove a project from a team as an organization member, the authenticated user
   797  // must have "read" access to both the team and project, or "admin" access to the team
   798  // or project.
   799  // Note: This endpoint removes the project from the team, but does not delete it.
   800  //
   801  // GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team
   802  //
   803  //meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}
   804  func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) {
   805  	u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID)
   806  	req, err := s.client.NewRequest("DELETE", u, nil)
   807  	if err != nil {
   808  		return nil, err
   809  	}
   810  
   811  	// TODO: remove custom Accept header when this API fully launches.
   812  	req.Header.Set("Accept", mediaTypeProjectsPreview)
   813  
   814  	return s.client.Do(ctx, req, nil)
   815  }
   816  
   817  // ListIDPGroupsOptions specifies the optional parameters to the ListIDPGroupsInOrganization method.
   818  type ListIDPGroupsOptions struct {
   819  	// Filters the results to return only those that begin with the value specified by this parameter.
   820  	Query string `url:"q,omitempty"`
   821  
   822  	ListCursorOptions
   823  }
   824  
   825  // IDPGroupList represents a list of external identity provider (IDP) groups.
   826  type IDPGroupList struct {
   827  	Groups []*IDPGroup `json:"groups"`
   828  }
   829  
   830  // IDPGroup represents an external identity provider (IDP) group.
   831  type IDPGroup struct {
   832  	GroupID          *string `json:"group_id,omitempty"`
   833  	GroupName        *string `json:"group_name,omitempty"`
   834  	GroupDescription *string `json:"group_description,omitempty"`
   835  }
   836  
   837  // ListIDPGroupsInOrganization lists IDP groups available in an organization.
   838  //
   839  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-an-organization
   840  //
   841  //meta:operation GET /orgs/{org}/team-sync/groups
   842  func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListIDPGroupsOptions) (*IDPGroupList, *Response, error) {
   843  	u := fmt.Sprintf("orgs/%v/team-sync/groups", org)
   844  	u, err := addOptions(u, opts)
   845  	if err != nil {
   846  		return nil, nil, err
   847  	}
   848  
   849  	req, err := s.client.NewRequest("GET", u, nil)
   850  	if err != nil {
   851  		return nil, nil, err
   852  	}
   853  
   854  	groups := new(IDPGroupList)
   855  	resp, err := s.client.Do(ctx, req, groups)
   856  	if err != nil {
   857  		return nil, resp, err
   858  	}
   859  
   860  	return groups, resp, nil
   861  }
   862  
   863  // ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub
   864  // given organization and team IDs.
   865  //
   866  // Deprecated: Use ListIDPGroupsForTeamBySlug instead.
   867  //
   868  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team
   869  //
   870  //meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings
   871  func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) {
   872  	u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
   873  
   874  	req, err := s.client.NewRequest("GET", u, nil)
   875  	if err != nil {
   876  		return nil, nil, err
   877  	}
   878  
   879  	groups := new(IDPGroupList)
   880  	resp, err := s.client.Do(ctx, req, groups)
   881  	if err != nil {
   882  		return nil, resp, err
   883  	}
   884  
   885  	return groups, resp, nil
   886  }
   887  
   888  // ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub
   889  // given organization name and team slug.
   890  //
   891  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team
   892  //
   893  //meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings
   894  func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) {
   895  	u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
   896  
   897  	req, err := s.client.NewRequest("GET", u, nil)
   898  	if err != nil {
   899  		return nil, nil, err
   900  	}
   901  
   902  	groups := new(IDPGroupList)
   903  	resp, err := s.client.Do(ctx, req, groups)
   904  	if err != nil {
   905  		return nil, resp, err
   906  	}
   907  
   908  	return groups, resp, nil
   909  }
   910  
   911  // CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection
   912  // between a team and an IDP group given organization and team IDs.
   913  //
   914  // Deprecated: Use CreateOrUpdateIDPGroupConnectionsBySlug instead.
   915  //
   916  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections
   917  //
   918  //meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings
   919  func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) {
   920  	u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID)
   921  
   922  	req, err := s.client.NewRequest("PATCH", u, opts)
   923  	if err != nil {
   924  		return nil, nil, err
   925  	}
   926  
   927  	groups := new(IDPGroupList)
   928  	resp, err := s.client.Do(ctx, req, groups)
   929  	if err != nil {
   930  		return nil, resp, err
   931  	}
   932  
   933  	return groups, resp, nil
   934  }
   935  
   936  // CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection
   937  // between a team and an IDP group given organization name and team slug.
   938  //
   939  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections
   940  //
   941  //meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings
   942  func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) {
   943  	u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug)
   944  
   945  	req, err := s.client.NewRequest("PATCH", u, opts)
   946  	if err != nil {
   947  		return nil, nil, err
   948  	}
   949  
   950  	groups := new(IDPGroupList)
   951  	resp, err := s.client.Do(ctx, req, groups)
   952  	if err != nil {
   953  		return nil, resp, err
   954  	}
   955  
   956  	return groups, resp, nil
   957  }
   958  
   959  // ExternalGroupMember represents a member of an external group.
   960  type ExternalGroupMember struct {
   961  	MemberID    *int64  `json:"member_id,omitempty"`
   962  	MemberLogin *string `json:"member_login,omitempty"`
   963  	MemberName  *string `json:"member_name,omitempty"`
   964  	MemberEmail *string `json:"member_email,omitempty"`
   965  }
   966  
   967  // ExternalGroupTeam represents a team connected to an external group.
   968  type ExternalGroupTeam struct {
   969  	TeamID   *int64  `json:"team_id,omitempty"`
   970  	TeamName *string `json:"team_name,omitempty"`
   971  }
   972  
   973  // ExternalGroup represents an external group.
   974  type ExternalGroup struct {
   975  	GroupID   *int64                 `json:"group_id,omitempty"`
   976  	GroupName *string                `json:"group_name,omitempty"`
   977  	UpdatedAt *Timestamp             `json:"updated_at,omitempty"`
   978  	Teams     []*ExternalGroupTeam   `json:"teams,omitempty"`
   979  	Members   []*ExternalGroupMember `json:"members,omitempty"`
   980  }
   981  
   982  // ExternalGroupList represents a list of external groups.
   983  type ExternalGroupList struct {
   984  	Groups []*ExternalGroup `json:"groups"`
   985  }
   986  
   987  // GetExternalGroup fetches an external group.
   988  //
   989  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group
   990  //
   991  //meta:operation GET /orgs/{org}/external-group/{group_id}
   992  func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) {
   993  	u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID)
   994  	req, err := s.client.NewRequest("GET", u, nil)
   995  	if err != nil {
   996  		return nil, nil, err
   997  	}
   998  
   999  	externalGroup := new(ExternalGroup)
  1000  	resp, err := s.client.Do(ctx, req, externalGroup)
  1001  	if err != nil {
  1002  		return nil, resp, err
  1003  	}
  1004  
  1005  	return externalGroup, resp, nil
  1006  }
  1007  
  1008  // ListExternalGroupsOptions specifies the optional parameters to the
  1009  // TeamsService.ListExternalGroups method.
  1010  type ListExternalGroupsOptions struct {
  1011  	DisplayName *string `url:"display_name,omitempty"`
  1012  
  1013  	ListOptions
  1014  }
  1015  
  1016  // ListExternalGroups lists external groups in an organization on GitHub.
  1017  //
  1018  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization
  1019  //
  1020  //meta:operation GET /orgs/{org}/external-groups
  1021  func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) {
  1022  	u := fmt.Sprintf("orgs/%v/external-groups", org)
  1023  	u, err := addOptions(u, opts)
  1024  	if err != nil {
  1025  		return nil, nil, err
  1026  	}
  1027  
  1028  	req, err := s.client.NewRequest("GET", u, nil)
  1029  	if err != nil {
  1030  		return nil, nil, err
  1031  	}
  1032  
  1033  	externalGroups := new(ExternalGroupList)
  1034  	resp, err := s.client.Do(ctx, req, externalGroups)
  1035  	if err != nil {
  1036  		return nil, resp, err
  1037  	}
  1038  
  1039  	return externalGroups, resp, nil
  1040  }
  1041  
  1042  // ListExternalGroupsForTeamBySlug lists external groups connected to a team on GitHub.
  1043  //
  1044  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team
  1045  //
  1046  //meta:operation GET /orgs/{org}/teams/{team_slug}/external-groups
  1047  func (s *TeamsService) ListExternalGroupsForTeamBySlug(ctx context.Context, org, slug string) (*ExternalGroupList, *Response, error) {
  1048  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
  1049  
  1050  	req, err := s.client.NewRequest("GET", u, nil)
  1051  	if err != nil {
  1052  		return nil, nil, err
  1053  	}
  1054  
  1055  	externalGroups := new(ExternalGroupList)
  1056  	resp, err := s.client.Do(ctx, req, externalGroups)
  1057  	if err != nil {
  1058  		return nil, resp, err
  1059  	}
  1060  
  1061  	return externalGroups, resp, nil
  1062  }
  1063  
  1064  // UpdateConnectedExternalGroup updates the connection between an external group and a team.
  1065  //
  1066  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#update-the-connection-between-an-external-group-and-a-team
  1067  //
  1068  //meta:operation PATCH /orgs/{org}/teams/{team_slug}/external-groups
  1069  func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) {
  1070  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
  1071  
  1072  	req, err := s.client.NewRequest("PATCH", u, eg)
  1073  	if err != nil {
  1074  		return nil, nil, err
  1075  	}
  1076  
  1077  	externalGroup := new(ExternalGroup)
  1078  	resp, err := s.client.Do(ctx, req, externalGroup)
  1079  	if err != nil {
  1080  		return nil, resp, err
  1081  	}
  1082  
  1083  	return externalGroup, resp, nil
  1084  }
  1085  
  1086  // RemoveConnectedExternalGroup removes the connection between an external group and a team.
  1087  //
  1088  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#remove-the-connection-between-an-external-group-and-a-team
  1089  //
  1090  //meta:operation DELETE /orgs/{org}/teams/{team_slug}/external-groups
  1091  func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) {
  1092  	u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug)
  1093  
  1094  	req, err := s.client.NewRequest("DELETE", u, nil)
  1095  	if err != nil {
  1096  		return nil, err
  1097  	}
  1098  
  1099  	return s.client.Do(ctx, req, nil)
  1100  }