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