Skip to content

Commit 6c958ff

Browse files
committed
add support for new repository invitations
Fixes #371. Change-Id: I97f2fc28ce048442ee8af3bd11c48b5b2084e09b
1 parent 1c08387 commit 6c958ff

8 files changed

+282
-6
lines changed

github/github.go

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ const (
8181

8282
// https://developer.github.com/changes/2016-05-23-timeline-preview-api/
8383
mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json"
84+
85+
// https://developer.github.com/changes/2016-06-14-repository-invitations/
86+
mediaTypeRepositoryInvitationsPreview = "application/vnd.github.swamp-thing-preview+json"
8487
)
8588

8689
// A Client manages communication with the GitHub API.

github/repos_collaborators.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,23 @@ type RepositoryAddCollaboratorOptions struct {
5858
// push - team members can pull and push, but not administer this repository
5959
// admin - team members can pull, push and administer this repository
6060
//
61-
// Default value is "pull". This option is only valid for organization-owned repositories.
61+
// Default value is "push". This option is only valid for organization-owned repositories.
6262
Permission string `json:"permission,omitempty"`
6363
}
6464

6565
// AddCollaborator adds the specified Github user as collaborator to the given repo.
6666
//
67-
// GitHub API docs: http://developer.github.com/v3/repos/collaborators/#add-collaborator
67+
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator
6868
func (s *RepositoriesService) AddCollaborator(owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) {
6969
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
7070
req, err := s.client.NewRequest("PUT", u, opt)
7171
if err != nil {
7272
return nil, err
7373
}
7474

75+
// TODO: remove custom Accept header when this API fully launches.
76+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
77+
7578
return s.client.Do(req, nil)
7679
}
7780

github/repos_collaborators_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ func TestRepositoriesService_AddCollaborator(t *testing.T) {
9494
json.NewDecoder(r.Body).Decode(v)
9595

9696
testMethod(t, r, "PUT")
97+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
9798
if !reflect.DeepEqual(v, opt) {
9899
t.Errorf("Request body = %+v, want %+v", v, opt)
99100
}

github/repos_invitations.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2016 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 "fmt"
9+
10+
// RepositoryInvitation represents an invitation to collaborate on a repo.
11+
type RepositoryInvitation struct {
12+
ID *int `json:"id,omitempty"`
13+
Repo *Repository `json:"repository,omitempty"`
14+
Invitee *User `json:"invitee,omitempty"`
15+
Inviter *User `json:"inviter,omitempty"`
16+
17+
// Permissions represents the permissions that the associated user will have
18+
// on the repository. Possible values are: "read", "write", "admin".
19+
Permissions *string `json:"permissions,omitempty"`
20+
CreatedAt *Timestamp `json:"created_at,omitempty"`
21+
URL *string `json:"url,omitempty"`
22+
HTMLURL *string `json:"html_url,omitempty"`
23+
}
24+
25+
// ListInvitations lists all currently-open repository invitations.
26+
//
27+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository
28+
func (s *RepositoriesService) ListInvitations(repoID int, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) {
29+
u := fmt.Sprintf("repositories/%v/invitations", repoID)
30+
u, err := addOptions(u, opt)
31+
if err != nil {
32+
return nil, nil, err
33+
}
34+
35+
req, err := s.client.NewRequest("GET", u, nil)
36+
if err != nil {
37+
return nil, nil, err
38+
}
39+
40+
// TODO: remove custom Accept header when this API fully launches.
41+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
42+
43+
invites := []*RepositoryInvitation{}
44+
resp, err := s.client.Do(req, &invites)
45+
if err != nil {
46+
return nil, resp, err
47+
}
48+
49+
return invites, resp, err
50+
}
51+
52+
// DeleteInvitation deletes a repository invitation.
53+
//
54+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation
55+
func (s *RepositoriesService) DeleteInvitation(repoID, invitationID int) (*Response, error) {
56+
u := fmt.Sprintf("repositories/%v/invitations/%v", repoID, invitationID)
57+
req, err := s.client.NewRequest("DELETE", u, nil)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
// TODO: remove custom Accept header when this API fully launches.
63+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
64+
65+
return s.client.Do(req, nil)
66+
}
67+
68+
// UpdateInvitation updates the permissions associated with a repository
69+
// invitation.
70+
//
71+
// permissions represents the permissions that the associated user will have
72+
// on the repository. Possible values are: "read", "write", "admin".
73+
//
74+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation
75+
func (s *RepositoriesService) UpdateInvitation(repoID, invitationID int, permissions string) (*RepositoryInvitation, *Response, error) {
76+
opts := &struct {
77+
Permissions string `json:"permissions"`
78+
}{Permissions: permissions}
79+
u := fmt.Sprintf("repositories/%v/invitations/%v", repoID, invitationID)
80+
req, err := s.client.NewRequest("PATCH", u, opts)
81+
if err != nil {
82+
return nil, nil, err
83+
}
84+
85+
// TODO: remove custom Accept header when this API fully launches.
86+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
87+
88+
invite := &RepositoryInvitation{}
89+
resp, err := s.client.Do(req, invite)
90+
return invite, resp, err
91+
}

github/repos_invitations_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2016 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+
"reflect"
12+
"testing"
13+
)
14+
15+
func TestRepositoriesService_ListInvitations(t *testing.T) {
16+
setup()
17+
defer teardown()
18+
19+
mux.HandleFunc("/repositories/1/invitations", func(w http.ResponseWriter, r *http.Request) {
20+
testMethod(t, r, "GET")
21+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
22+
testFormValues(t, r, values{"page": "2"})
23+
fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
24+
})
25+
26+
opt := &ListOptions{Page: 2}
27+
got, _, err := client.Repositories.ListInvitations(1, opt)
28+
if err != nil {
29+
t.Errorf("Repositories.ListInvitations returned error: %v", err)
30+
}
31+
32+
want := []*RepositoryInvitation{{ID: Int(1)}, {ID: Int(2)}}
33+
if !reflect.DeepEqual(got, want) {
34+
t.Errorf("Repositories.ListInvitations = %+v, want %+v", got, want)
35+
}
36+
}
37+
38+
func TestRepositoriesService_DeleteInvitation(t *testing.T) {
39+
setup()
40+
defer teardown()
41+
42+
mux.HandleFunc("/repositories/1/invitations/2", func(w http.ResponseWriter, r *http.Request) {
43+
testMethod(t, r, "DELETE")
44+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
45+
w.WriteHeader(http.StatusNoContent)
46+
})
47+
48+
_, err := client.Repositories.DeleteInvitation(1, 2)
49+
if err != nil {
50+
t.Errorf("Repositories.DeleteInvitation returned error: %v", err)
51+
}
52+
}
53+
54+
func TestRepositoriesService_UpdateInvitation(t *testing.T) {
55+
setup()
56+
defer teardown()
57+
58+
mux.HandleFunc("/repositories/1/invitations/2", func(w http.ResponseWriter, r *http.Request) {
59+
testMethod(t, r, "PATCH")
60+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
61+
fmt.Fprintf(w, `{"id":1}`)
62+
})
63+
64+
got, _, err := client.Repositories.UpdateInvitation(1, 2, "write")
65+
if err != nil {
66+
t.Errorf("Repositories.UpdateInvitation returned error: %v", err)
67+
}
68+
69+
want := &RepositoryInvitation{ID: Int(1)}
70+
if !reflect.DeepEqual(got, want) {
71+
t.Errorf("Repositories.UpdateInvitation = %+v, want %+v", got, want)
72+
}
73+
}

github/users.go

+56
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,59 @@ func (s *UsersService) ListAll(opt *UserListOptions) ([]User, *Response, error)
166166

167167
return *users, resp, err
168168
}
169+
170+
// ListInvitations lists all currently-open repository invitations for the
171+
// authenticated user.
172+
//
173+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository
174+
func (s *UsersService) ListInvitations() ([]*RepositoryInvitation, *Response, error) {
175+
req, err := s.client.NewRequest("GET", "user/repository_invitations", nil)
176+
if err != nil {
177+
return nil, nil, err
178+
}
179+
180+
// TODO: remove custom Accept header when this API fully launches.
181+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
182+
183+
invites := []*RepositoryInvitation{}
184+
resp, err := s.client.Do(req, &invites)
185+
if err != nil {
186+
return nil, resp, err
187+
}
188+
189+
return invites, resp, err
190+
}
191+
192+
// AcceptInvitation accepts the currently-open repository invitation for the
193+
// authenticated user.
194+
//
195+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation
196+
func (s *UsersService) AcceptInvitation(invitationID int) (*Response, error) {
197+
u := fmt.Sprintf("user/repository_invitations/%v", invitationID)
198+
req, err := s.client.NewRequest("PATCH", u, nil)
199+
if err != nil {
200+
return nil, err
201+
}
202+
203+
// TODO: remove custom Accept header when this API fully launches.
204+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
205+
206+
return s.client.Do(req, nil)
207+
}
208+
209+
// DeclineInvitation declines the currently-open repository invitation for the
210+
// authenticated user.
211+
//
212+
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation
213+
func (s *UsersService) DeclineInvitation(invitationID int) (*Response, error) {
214+
u := fmt.Sprintf("user/repository_invitations/%v", invitationID)
215+
req, err := s.client.NewRequest("DELETE", u, nil)
216+
if err != nil {
217+
return nil, err
218+
}
219+
220+
// TODO: remove custom Accept header when this API fully launches.
221+
req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview)
222+
223+
return s.client.Do(req, nil)
224+
}

github/users_gpg_keys.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,8 @@ func (s *UsersService) GetGPGKey(id int) (*GPGKey, *Response, error) {
9090
// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key
9191
func (s *UsersService) CreateGPGKey(armoredPublicKey string) (*GPGKey, *Response, error) {
9292
gpgKey := &struct {
93-
ArmoredPublicKey *string `json:"armored_public_key,omitempty"`
94-
}{
95-
ArmoredPublicKey: String(armoredPublicKey),
96-
}
93+
ArmoredPublicKey string `json:"armored_public_key"`
94+
}{ArmoredPublicKey: armoredPublicKey}
9795
req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey)
9896
if err != nil {
9997
return nil, nil, err

github/users_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,54 @@ func TestUsersService_ListAll(t *testing.T) {
170170
t.Errorf("Users.ListAll returned %+v, want %+v", users, want)
171171
}
172172
}
173+
174+
func TestUsersService_ListInvitations(t *testing.T) {
175+
setup()
176+
defer teardown()
177+
178+
mux.HandleFunc("/user/repository_invitations", func(w http.ResponseWriter, r *http.Request) {
179+
testMethod(t, r, "GET")
180+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
181+
fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
182+
})
183+
184+
got, _, err := client.Users.ListInvitations()
185+
if err != nil {
186+
t.Errorf("Users.ListInvitations returned error: %v", err)
187+
}
188+
189+
want := []*RepositoryInvitation{{ID: Int(1)}, {ID: Int(2)}}
190+
if !reflect.DeepEqual(got, want) {
191+
t.Errorf("Users.ListInvitations = %+v, want %+v", got, want)
192+
}
193+
}
194+
195+
func TestUsersService_AcceptInvitation(t *testing.T) {
196+
setup()
197+
defer teardown()
198+
199+
mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) {
200+
testMethod(t, r, "PATCH")
201+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
202+
w.WriteHeader(http.StatusNoContent)
203+
})
204+
205+
if _, err := client.Users.AcceptInvitation(1); err != nil {
206+
t.Errorf("Users.AcceptInvitation returned error: %v", err)
207+
}
208+
}
209+
210+
func TestUsersService_DeclineInvitation(t *testing.T) {
211+
setup()
212+
defer teardown()
213+
214+
mux.HandleFunc("/user/repository_invitations/1", func(w http.ResponseWriter, r *http.Request) {
215+
testMethod(t, r, "DELETE")
216+
testHeader(t, r, "Accept", mediaTypeRepositoryInvitationsPreview)
217+
w.WriteHeader(http.StatusNoContent)
218+
})
219+
220+
if _, err := client.Users.DeclineInvitation(1); err != nil {
221+
t.Errorf("Users.DeclineInvitation returned error: %v", err)
222+
}
223+
}

0 commit comments

Comments
 (0)