Skip to content

Commit bd1caa0

Browse files
feat: Add support for Enterprise Team APIs (#3861)
1 parent 66f826c commit bd1caa0

File tree

4 files changed

+483
-0
lines changed

4 files changed

+483
-0
lines changed

github/enterprise_team.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2025 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+
)
12+
13+
// EnterpriseTeam represent a team in a GitHub Enterprise.
14+
type EnterpriseTeam struct {
15+
ID int64 `json:"id"`
16+
URL string `json:"url"`
17+
MemberURL string `json:"member_url"`
18+
Name string `json:"name"`
19+
Description *string `json:"description,omitempty"`
20+
HTMLURL string `json:"html_url"`
21+
Slug string `json:"slug"`
22+
CreatedAt Timestamp `json:"created_at"`
23+
UpdatedAt Timestamp `json:"updated_at"`
24+
GroupID string `json:"group_id"`
25+
OrganizationSelectionType *string `json:"organization_selection_type,omitempty"`
26+
}
27+
28+
// EnterpriseTeamCreateOrUpdateRequest is used to create or update an enterprise team.
29+
type EnterpriseTeamCreateOrUpdateRequest struct {
30+
// The name of the team.
31+
Name string `json:"name"`
32+
// A description of the team.
33+
Description *string `json:"description,omitempty"`
34+
// Specifies which organizations in the enterprise should have access to this team.
35+
// Possible values are "disabled" , "all" and "selected". If not specified, the default is "disabled".
36+
OrganizationSelectionType *string `json:"organization_selection_type,omitempty"`
37+
// The ID of the IdP group to assign team membership with.
38+
GroupID *string `json:"group_id,omitempty"`
39+
}
40+
41+
// ListTeams lists all teams in an enterprise.
42+
//
43+
// GitHub API docs: https://docs.github.com/rest/enterprise-teams/enterprise-teams#list-enterprise-teams
44+
//
45+
//meta:operation GET /enterprises/{enterprise}/teams
46+
func (s *EnterpriseService) ListTeams(ctx context.Context, enterprise string, opt *ListOptions) ([]*EnterpriseTeam, *Response, error) {
47+
u := fmt.Sprintf("enterprises/%v/teams", enterprise)
48+
u, err := addOptions(u, opt)
49+
if err != nil {
50+
return nil, nil, err
51+
}
52+
53+
req, err := s.client.NewRequest("GET", u, nil)
54+
if err != nil {
55+
return nil, nil, err
56+
}
57+
58+
var teams []*EnterpriseTeam
59+
resp, err := s.client.Do(ctx, req, &teams)
60+
if err != nil {
61+
return nil, resp, err
62+
}
63+
64+
return teams, resp, nil
65+
}
66+
67+
// CreateTeam creates a new team in an enterprise.
68+
//
69+
// GitHub API docs: https://docs.github.com/rest/enterprise-teams/enterprise-teams#create-an-enterprise-team
70+
//
71+
//meta:operation POST /enterprises/{enterprise}/teams
72+
func (s *EnterpriseService) CreateTeam(ctx context.Context, enterprise string, team EnterpriseTeamCreateOrUpdateRequest) (*EnterpriseTeam, *Response, error) {
73+
u := fmt.Sprintf("enterprises/%v/teams", enterprise)
74+
75+
req, err := s.client.NewRequest("POST", u, team)
76+
if err != nil {
77+
return nil, nil, err
78+
}
79+
80+
var createdTeam *EnterpriseTeam
81+
resp, err := s.client.Do(ctx, req, &createdTeam)
82+
if err != nil {
83+
return nil, resp, err
84+
}
85+
86+
return createdTeam, resp, nil
87+
}
88+
89+
// GetTeam retrieves a team in an enterprise.
90+
//
91+
// GitHub API docs: https://docs.github.com/rest/enterprise-teams/enterprise-teams#get-an-enterprise-team
92+
//
93+
//meta:operation GET /enterprises/{enterprise}/teams/{team_slug}
94+
func (s *EnterpriseService) GetTeam(ctx context.Context, enterprise, teamSlug string) (*EnterpriseTeam, *Response, error) {
95+
u := fmt.Sprintf("enterprises/%v/teams/%v", enterprise, teamSlug)
96+
97+
req, err := s.client.NewRequest("GET", u, nil)
98+
if err != nil {
99+
return nil, nil, err
100+
}
101+
102+
var team *EnterpriseTeam
103+
resp, err := s.client.Do(ctx, req, &team)
104+
if err != nil {
105+
return nil, resp, err
106+
}
107+
108+
return team, resp, nil
109+
}
110+
111+
// UpdateTeam updates a team in an enterprise.
112+
//
113+
// GitHub API docs: https://docs.github.com/rest/enterprise-teams/enterprise-teams#update-an-enterprise-team
114+
//
115+
//meta:operation PATCH /enterprises/{enterprise}/teams/{team_slug}
116+
func (s *EnterpriseService) UpdateTeam(ctx context.Context, enterprise, teamSlug string, team EnterpriseTeamCreateOrUpdateRequest) (*EnterpriseTeam, *Response, error) {
117+
u := fmt.Sprintf("enterprises/%v/teams/%v", enterprise, teamSlug)
118+
119+
req, err := s.client.NewRequest("PATCH", u, team)
120+
if err != nil {
121+
return nil, nil, err
122+
}
123+
124+
var updatedTeam *EnterpriseTeam
125+
resp, err := s.client.Do(ctx, req, &updatedTeam)
126+
if err != nil {
127+
return nil, resp, err
128+
}
129+
130+
return updatedTeam, resp, nil
131+
}
132+
133+
// DeleteTeam deletes a team in an enterprise.
134+
//
135+
// GitHub API docs: https://docs.github.com/rest/enterprise-teams/enterprise-teams#delete-an-enterprise-team
136+
//
137+
//meta:operation DELETE /enterprises/{enterprise}/teams/{team_slug}
138+
func (s *EnterpriseService) DeleteTeam(ctx context.Context, enterprise, teamSlug string) (*Response, error) {
139+
u := fmt.Sprintf("enterprises/%v/teams/%v", enterprise, teamSlug)
140+
141+
req, err := s.client.NewRequest("DELETE", u, nil)
142+
if err != nil {
143+
return nil, err
144+
}
145+
146+
resp, err := s.client.Do(ctx, req, nil)
147+
if err != nil {
148+
return resp, err
149+
}
150+
151+
return resp, nil
152+
}

github/enterprise_team_test.go

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
// Copyright 2025 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+
"fmt"
10+
"net/http"
11+
"testing"
12+
"time"
13+
14+
"github.com/google/go-cmp/cmp"
15+
)
16+
17+
func TestEnterpriseService_ListTeams(t *testing.T) {
18+
t.Parallel()
19+
client, mux, _ := setup(t)
20+
21+
mux.HandleFunc("/enterprises/e/teams", func(w http.ResponseWriter, r *http.Request) {
22+
testMethod(t, r, "GET")
23+
fmt.Fprint(w, `[{
24+
"id": 1,
25+
"url": "https://example.com/team1",
26+
"member_url": "https://example.com/members",
27+
"name": "Team One",
28+
"html_url": "https://example.com/html",
29+
"slug": "team-one",
30+
"created_at": "2020-01-01T00:00:00Z",
31+
"updated_at": "2020-01-02T00:00:00Z",
32+
"group_id": "99"
33+
}]`)
34+
})
35+
36+
ctx := t.Context()
37+
opts := &ListOptions{Page: 1, PerPage: 10}
38+
got, _, err := client.Enterprise.ListTeams(ctx, "e", opts)
39+
if err != nil {
40+
t.Fatalf("Enterprise.ListTeams returned error: %v", err)
41+
}
42+
43+
want := []*EnterpriseTeam{
44+
{
45+
ID: 1,
46+
URL: "https://example.com/team1",
47+
MemberURL: "https://example.com/members",
48+
Name: "Team One",
49+
HTMLURL: "https://example.com/html",
50+
Slug: "team-one",
51+
GroupID: "99",
52+
CreatedAt: Timestamp{Time: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)},
53+
UpdatedAt: Timestamp{Time: time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC)},
54+
},
55+
}
56+
57+
if !cmp.Equal(got, want) {
58+
t.Errorf("Enterprise.ListTeams = %+v, want %+v", got, want)
59+
}
60+
61+
const methodName = "ListTeams"
62+
testBadOptions(t, methodName, func() error {
63+
_, _, err := client.Enterprise.ListTeams(ctx, "\n", opts)
64+
return err
65+
})
66+
67+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
68+
got, resp, err := client.Enterprise.ListTeams(ctx, "e", opts)
69+
if got != nil {
70+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
71+
}
72+
return resp, err
73+
})
74+
}
75+
76+
func TestEnterpriseService_CreateTeam(t *testing.T) {
77+
t.Parallel()
78+
client, mux, _ := setup(t)
79+
80+
input := EnterpriseTeamCreateOrUpdateRequest{
81+
Name: "New Team",
82+
}
83+
84+
mux.HandleFunc("/enterprises/e/teams", func(w http.ResponseWriter, r *http.Request) {
85+
testMethod(t, r, "POST")
86+
testBody(t, r, `{"name":"New Team"}`+"\n")
87+
fmt.Fprint(w, `{
88+
"id": 10,
89+
"name": "New Team",
90+
"slug": "new-team",
91+
"url": "https://example.com/team"
92+
}`)
93+
})
94+
95+
ctx := t.Context()
96+
got, _, err := client.Enterprise.CreateTeam(ctx, "e", input)
97+
if err != nil {
98+
t.Fatalf("Enterprise.CreateTeam returned error: %v", err)
99+
}
100+
101+
want := &EnterpriseTeam{
102+
ID: 10,
103+
Name: "New Team",
104+
Slug: "new-team",
105+
URL: "https://example.com/team",
106+
}
107+
108+
if !cmp.Equal(got, want) {
109+
t.Errorf("Enterprise.CreateTeam = %+v, want %+v", got, want)
110+
}
111+
112+
const methodName = "CreateTeam"
113+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
114+
got, resp, err := client.Enterprise.CreateTeam(ctx, "e", input)
115+
if got != nil {
116+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
117+
}
118+
return resp, err
119+
})
120+
}
121+
122+
func TestEnterpriseService_GetTeam(t *testing.T) {
123+
t.Parallel()
124+
client, mux, _ := setup(t)
125+
126+
mux.HandleFunc("/enterprises/e/teams/t1", func(w http.ResponseWriter, r *http.Request) {
127+
testMethod(t, r, "GET")
128+
fmt.Fprint(w, `{
129+
"id": 2,
130+
"name": "Team One",
131+
"slug": "t1"
132+
}`)
133+
})
134+
135+
ctx := t.Context()
136+
got, _, err := client.Enterprise.GetTeam(ctx, "e", "t1")
137+
if err != nil {
138+
t.Fatalf("Enterprise.GetTeam returned error: %v", err)
139+
}
140+
141+
want := &EnterpriseTeam{
142+
ID: 2,
143+
Name: "Team One",
144+
Slug: "t1",
145+
}
146+
147+
if !cmp.Equal(got, want) {
148+
t.Errorf("Enterprise.GetTeam = %+v, want %+v", got, want)
149+
}
150+
151+
const methodName = "GetTeam"
152+
testBadOptions(t, methodName, func() error {
153+
_, _, err := client.Enterprise.GetTeam(ctx, "\n", "t1")
154+
return err
155+
})
156+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
157+
got, resp, err := client.Enterprise.GetTeam(ctx, "e", "t1")
158+
if got != nil {
159+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
160+
}
161+
return resp, err
162+
})
163+
}
164+
165+
func TestEnterpriseService_UpdateTeam(t *testing.T) {
166+
t.Parallel()
167+
client, mux, _ := setup(t)
168+
169+
input := EnterpriseTeamCreateOrUpdateRequest{
170+
Name: "Updated Team",
171+
}
172+
173+
mux.HandleFunc("/enterprises/e/teams/t1", func(w http.ResponseWriter, r *http.Request) {
174+
testMethod(t, r, "PATCH")
175+
testBody(t, r, `{"name":"Updated Team"}`+"\n")
176+
fmt.Fprint(w, `{
177+
"id": 3,
178+
"name": "Updated Team",
179+
"slug": "t1"
180+
}`)
181+
})
182+
183+
ctx := t.Context()
184+
got, _, err := client.Enterprise.UpdateTeam(ctx, "e", "t1", input)
185+
if err != nil {
186+
t.Fatalf("Enterprise.UpdateTeam returned error: %v", err)
187+
}
188+
189+
want := &EnterpriseTeam{
190+
ID: 3,
191+
Name: "Updated Team",
192+
Slug: "t1",
193+
}
194+
195+
if !cmp.Equal(got, want) {
196+
t.Errorf("Enterprise.UpdateTeam = %+v, want %+v", got, want)
197+
}
198+
199+
const methodName = "UpdateTeam"
200+
testBadOptions(t, methodName, func() error {
201+
_, _, err := client.Enterprise.UpdateTeam(ctx, "\n", "t1", input)
202+
return err
203+
})
204+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
205+
got, resp, err := client.Enterprise.UpdateTeam(ctx, "e", "t1", input)
206+
if got != nil {
207+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
208+
}
209+
return resp, err
210+
})
211+
}
212+
213+
func TestEnterpriseService_DeleteTeam(t *testing.T) {
214+
t.Parallel()
215+
client, mux, _ := setup(t)
216+
217+
mux.HandleFunc("/enterprises/e/teams/t1", func(w http.ResponseWriter, r *http.Request) {
218+
testMethod(t, r, "DELETE")
219+
w.WriteHeader(http.StatusNoContent)
220+
})
221+
222+
ctx := t.Context()
223+
_, err := client.Enterprise.DeleteTeam(ctx, "e", "t1")
224+
if err != nil {
225+
t.Fatalf("Enterprise.DeleteTeam returned error: %v", err)
226+
}
227+
228+
const methodName = "DeleteTeam"
229+
testBadOptions(t, methodName, func() error {
230+
_, err := client.Enterprise.DeleteTeam(ctx, "\n", "t1")
231+
return err
232+
})
233+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
234+
return client.Enterprise.DeleteTeam(ctx, "e", "t1")
235+
})
236+
}

0 commit comments

Comments
 (0)