Merge pull request #8 from zachgersh/master
Allow Github Resource to Fetch Private Assets
This commit is contained in:
8
Godeps/Godeps.json
generated
8
Godeps/Godeps.json
generated
@@ -15,10 +15,6 @@
|
||||
"Comment": "v3.0.0",
|
||||
"Rev": "2f3112b6f8f18f9df8743cc75ed51da08094ef6a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/go-github/github",
|
||||
"Rev": "7ea4ee6d222607c11ea86e99a6f6723beeae785d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/go-querystring/query",
|
||||
"Rev": "d8840cbb2baa915f4836edda4750050a2c0b7aea"
|
||||
@@ -36,6 +32,10 @@
|
||||
"ImportPath": "github.com/onsi/gomega",
|
||||
"Comment": "v1.0-28-g8adf9e1",
|
||||
"Rev": "8adf9e1730c55cdc590de7d49766cb2acc88d8f2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/zachgersh/go-github/github",
|
||||
"Rev": "f47a8b33261f10482dfede3cc839c4fcf34da04f"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -7,6 +7,12 @@ package github
|
||||
|
||||
import "fmt"
|
||||
|
||||
// StarredRepository is returned by ListStarred.
|
||||
type StarredRepository struct {
|
||||
StarredAt *Timestamp `json:"starred_at,omitempty"`
|
||||
Repository *Repository `json:"repo,omitempty"`
|
||||
}
|
||||
|
||||
// ListStargazers lists people who have starred the specified repo.
|
||||
//
|
||||
// GitHub API Docs: https://developer.github.com/v3/activity/starring/#list-stargazers
|
||||
@@ -49,7 +55,7 @@ type ActivityListStarredOptions struct {
|
||||
// will list the starred repositories for the authenticated user.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/activity/starring/#list-repositories-being-starred
|
||||
func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptions) ([]Repository, *Response, error) {
|
||||
func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptions) ([]StarredRepository, *Response, error) {
|
||||
var u string
|
||||
if user != "" {
|
||||
u = fmt.Sprintf("users/%v/starred", user)
|
||||
@@ -66,7 +72,10 @@ func (s *ActivityService) ListStarred(user string, opt *ActivityListStarredOptio
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repos := new([]Repository)
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeStarringPreview)
|
||||
|
||||
repos := new([]StarredRepository)
|
||||
resp, err := s.client.Do(req, repos)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestActivityService_ListStargazers(t *testing.T) {
|
||||
@@ -42,7 +43,8 @@ func TestActivityService_ListStarred_authenticatedUser(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/user/starred", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[{"id":1}]`)
|
||||
testHeader(t, r, "Accept", mediaTypeStarringPreview)
|
||||
fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":1}}]`)
|
||||
})
|
||||
|
||||
repos, _, err := client.Activity.ListStarred("", nil)
|
||||
@@ -50,7 +52,7 @@ func TestActivityService_ListStarred_authenticatedUser(t *testing.T) {
|
||||
t.Errorf("Activity.ListStarred returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []Repository{{ID: Int(1)}}
|
||||
want := []StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int(1)}}}
|
||||
if !reflect.DeepEqual(repos, want) {
|
||||
t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want)
|
||||
}
|
||||
@@ -62,12 +64,13 @@ func TestActivityService_ListStarred_specifiedUser(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/users/u/starred", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeStarringPreview)
|
||||
testFormValues(t, r, values{
|
||||
"sort": "created",
|
||||
"direction": "asc",
|
||||
"page": "2",
|
||||
})
|
||||
fmt.Fprint(w, `[{"id":2}]`)
|
||||
fmt.Fprint(w, `[{"starred_at":"2002-02-10T15:30:00Z","repo":{"id":2}}]`)
|
||||
})
|
||||
|
||||
opt := &ActivityListStarredOptions{"created", "asc", ListOptions{Page: 2}}
|
||||
@@ -76,7 +79,7 @@ func TestActivityService_ListStarred_specifiedUser(t *testing.T) {
|
||||
t.Errorf("Activity.ListStarred returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []Repository{{ID: Int(2)}}
|
||||
want := []StarredRepository{{StarredAt: &Timestamp{time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)}, Repository: &Repository{ID: Int(2)}}}
|
||||
if !reflect.DeepEqual(repos, want) {
|
||||
t.Errorf("Activity.ListStarred returned %+v, want %+v", repos, want)
|
||||
}
|
@@ -28,23 +28,24 @@ Authentication
|
||||
|
||||
The go-github library does not directly handle authentication. Instead, when
|
||||
creating a new client, pass an http.Client that can handle authentication for
|
||||
you. The easiest and recommended way to do this is using the goauth2 library,
|
||||
but you can always use any other library that provides an http.Client. If you
|
||||
have an OAuth2 access token (for example, a personal API token), you can use it
|
||||
with the goauth2 using:
|
||||
you. The easiest and recommended way to do this is using the golang.org/x/oauth2
|
||||
library, but you can always use any other library that provides an http.Client.
|
||||
If you have an OAuth2 access token (for example, a personal API token), you can
|
||||
use it with the oauth2 library using:
|
||||
|
||||
import "code.google.com/p/goauth2/oauth"
|
||||
import "golang.org/x/oauth2"
|
||||
|
||||
// simple OAuth transport if you already have an access token;
|
||||
// see goauth2 library for full usage
|
||||
t := &oauth.Transport{
|
||||
Token: &oauth.Token{AccessToken: "..."},
|
||||
}
|
||||
func main() {
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: "... your access token ..."},
|
||||
)
|
||||
tc := oauth2.NewClient(oauth2.NoContext, ts)
|
||||
|
||||
client := github.NewClient(t.Client())
|
||||
client := github.NewClient(tc)
|
||||
|
||||
// list all repositories for the authenticated user
|
||||
repos, _, err := client.Repositories.List("", nil)
|
||||
}
|
||||
|
||||
Note that when using an authenticated Client, all calls made by the client will
|
||||
include the specified OAuth token. Therefore, authenticated clients should
|
@@ -157,6 +157,24 @@ func (s *GistsService) Get(id string) (*Gist, *Response, error) {
|
||||
return gist, resp, err
|
||||
}
|
||||
|
||||
// GetRevision gets a specific revision of a gist.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist
|
||||
func (s *GistsService) GetRevision(id, sha string) (*Gist, *Response, error) {
|
||||
u := fmt.Sprintf("gists/%v/%v", id, sha)
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gist := new(Gist)
|
||||
resp, err := s.client.Do(req, gist)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return gist, resp, err
|
||||
}
|
||||
|
||||
// Create a gist for authenticated user.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/gists/#create-a-gist
|
@@ -146,6 +146,32 @@ func TestGistsService_Get_invalidID(t *testing.T) {
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestGistsService_GetRevision(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/gists/1/s", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"id": "1"}`)
|
||||
})
|
||||
|
||||
gist, _, err := client.Gists.GetRevision("1", "s")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Gists.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Gist{ID: String("1")}
|
||||
if !reflect.DeepEqual(gist, want) {
|
||||
t.Errorf("Gists.Get returned %+v, want %+v", gist, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGistsService_GetRevision_invalidID(t *testing.T) {
|
||||
_, _, err := client.Gists.GetRevision("%", "%")
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestGistsService_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
@@ -37,11 +37,15 @@ const (
|
||||
|
||||
// Media Type values to access preview APIs
|
||||
|
||||
// https://developer.github.com/changes/2014-08-05-team-memberships-api/
|
||||
mediaTypeMembershipPreview = "application/vnd.github.the-wasp-preview+json"
|
||||
// https://developer.github.com/changes/2015-03-09-licenses-api/
|
||||
mediaTypeLicensesPreview = "application/vnd.github.drax-preview+json"
|
||||
|
||||
// https://developer.github.com/changes/2014-01-09-preview-the-new-deployments-api/
|
||||
mediaTypeDeploymentPreview = "application/vnd.github.cannonball-preview+json"
|
||||
// https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/
|
||||
mediaTypeStarringPreview = "application/vnd.github.v3.star+json"
|
||||
|
||||
// https://developer.github.com/changes/2015-06-24-api-enhancements-for-working-with-organization-permissions/
|
||||
mediaTypeOrgPermissionPreview = "application/vnd.github.ironman-preview+json"
|
||||
mediaTypeOrgPermissionRepoPreview = "application/vnd.github.ironman-preview.repository+json"
|
||||
)
|
||||
|
||||
// A Client manages communication with the GitHub API.
|
||||
@@ -77,6 +81,7 @@ type Client struct {
|
||||
Repositories *RepositoriesService
|
||||
Search *SearchService
|
||||
Users *UsersService
|
||||
Licenses *LicensesService
|
||||
}
|
||||
|
||||
// ListOptions specifies the optional parameters to various List methods that
|
||||
@@ -119,7 +124,7 @@ func addOptions(s string, opt interface{}) (string, error) {
|
||||
// NewClient returns a new GitHub API client. If a nil httpClient is
|
||||
// provided, http.DefaultClient will be used. To use API methods which require
|
||||
// authentication, provide an http.Client that will perform the authentication
|
||||
// for you (such as that provided by the goauth2 library).
|
||||
// for you (such as that provided by the golang.org/x/oauth2 library).
|
||||
func NewClient(httpClient *http.Client) *Client {
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
@@ -138,6 +143,7 @@ func NewClient(httpClient *http.Client) *Client {
|
||||
c.Repositories = &RepositoriesService{client: c}
|
||||
c.Search = &SearchService{client: c}
|
||||
c.Users = &UsersService{client: c}
|
||||
c.Licenses = &LicensesService{client: c}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -219,7 +225,7 @@ type Response struct {
|
||||
Rate
|
||||
}
|
||||
|
||||
// newResponse creats a new Response for the provided http.Response.
|
||||
// newResponse creates a new Response for the provided http.Response.
|
||||
func newResponse(r *http.Response) *Response {
|
||||
response := &Response{Response: r}
|
||||
response.populatePageValues()
|
||||
@@ -333,10 +339,24 @@ type ErrorResponse struct {
|
||||
|
||||
func (r *ErrorResponse) Error() string {
|
||||
return fmt.Sprintf("%v %v: %d %v %+v",
|
||||
r.Response.Request.Method, r.Response.Request.URL,
|
||||
r.Response.Request.Method, sanitizeURL(r.Response.Request.URL),
|
||||
r.Response.StatusCode, r.Message, r.Errors)
|
||||
}
|
||||
|
||||
// sanitizeURL redacts the client_id and client_secret tokens from the URL which
|
||||
// may be exposed to the user, specifically in the ErrorResponse error message.
|
||||
func sanitizeURL(uri *url.URL) *url.URL {
|
||||
if uri == nil {
|
||||
return nil
|
||||
}
|
||||
params := uri.Query()
|
||||
if len(params.Get("client_secret")) > 0 {
|
||||
params.Set("client_secret", "REDACTED")
|
||||
uri.RawQuery = params.Encode()
|
||||
}
|
||||
return uri
|
||||
}
|
||||
|
||||
/*
|
||||
An Error reports more details on an individual error in an ErrorResponse.
|
||||
These are the possible validation error codes:
|
@@ -430,6 +430,25 @@ func TestDo_rateLimit_errorResponse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSanitizeURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"/?a=b", "/?a=b"},
|
||||
{"/?a=b&client_secret=secret", "/?a=b&client_secret=REDACTED"},
|
||||
{"/?a=b&client_id=id&client_secret=secret", "/?a=b&client_id=id&client_secret=REDACTED"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
inURL, _ := url.Parse(tt.in)
|
||||
want, _ := url.Parse(tt.want)
|
||||
|
||||
if got := sanitizeURL(inURL); !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("sanitizeURL(%v) returned %v, want %v", tt.in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckResponse(t *testing.T) {
|
||||
res := &http.Response{
|
||||
Request: &http.Request{},
|
@@ -51,7 +51,7 @@ func (i Issue) String() string {
|
||||
type IssueRequest struct {
|
||||
Title *string `json:"title,omitempty"`
|
||||
Body *string `json:"body,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
Labels *[]string `json:"labels,omitempty"`
|
||||
Assignee *string `json:"assignee,omitempty"`
|
||||
State *string `json:"state,omitempty"`
|
||||
Milestone *int `json:"milestone,omitempty"`
|
||||
@@ -72,7 +72,7 @@ type IssueListOptions struct {
|
||||
Labels []string `url:"labels,comma,omitempty"`
|
||||
|
||||
// Sort specifies how to sort issues. Possible values are: created, updated,
|
||||
// and comments. Default value is "assigned".
|
||||
// and comments. Default value is "created".
|
||||
Sort string `url:"sort,omitempty"`
|
||||
|
||||
// Direction in which to sort issues. Possible values are: asc, desc.
|
||||
@@ -166,7 +166,7 @@ type IssueListByRepoOptions struct {
|
||||
Labels []string `url:"labels,omitempty,comma"`
|
||||
|
||||
// Sort specifies how to sort issues. Possible values are: created, updated,
|
||||
// and comments. Default value is "assigned".
|
||||
// and comments. Default value is "created".
|
||||
Sort string `url:"sort,omitempty"`
|
||||
|
||||
// Direction in which to sort issues. Possible values are: asc, desc.
|
@@ -7,7 +7,7 @@ package github
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Label represents a GitHib label on an Issue
|
||||
// Label represents a GitHub label on an Issue
|
||||
type Label struct {
|
||||
URL *string `json:"url,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
@@ -176,7 +176,7 @@ func TestIssuesService_Create(t *testing.T) {
|
||||
Title: String("t"),
|
||||
Body: String("b"),
|
||||
Assignee: String("a"),
|
||||
Labels: []string{"l1", "l2"},
|
||||
Labels: &[]string{"l1", "l2"},
|
||||
}
|
||||
|
||||
mux.HandleFunc("/repos/o/r/issues", func(w http.ResponseWriter, r *http.Request) {
|
81
Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses.go
generated
vendored
Normal file
81
Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2013 The go-github AUTHORS. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package github
|
||||
|
||||
import "fmt"
|
||||
|
||||
// LicensesService handles communication with the license related
|
||||
// methods of the GitHub API.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/pulls/
|
||||
type LicensesService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// License represents an open source license.
|
||||
type License struct {
|
||||
Key *string `json:"key,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
|
||||
HTMLURL *string `json:"html_url,omitempty"`
|
||||
Featured *bool `json:"featured,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Category *string `json:"category,omitempty"`
|
||||
Implementation *string `json:"implementation,omitempty"`
|
||||
Required *[]string `json:"required,omitempty"`
|
||||
Permitted *[]string `json:"permitted,omitempty"`
|
||||
Forbidden *[]string `json:"forbidden,omitempty"`
|
||||
Body *string `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
func (l License) String() string {
|
||||
return Stringify(l)
|
||||
}
|
||||
|
||||
// List popular open source licenses.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses
|
||||
func (s *LicensesService) List() ([]License, *Response, error) {
|
||||
req, err := s.client.NewRequest("GET", "licenses", nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeLicensesPreview)
|
||||
|
||||
licenses := new([]License)
|
||||
resp, err := s.client.Do(req, licenses)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return *licenses, resp, err
|
||||
}
|
||||
|
||||
// Get extended metadata for one license.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license
|
||||
func (s *LicensesService) Get(licenseName string) (*License, *Response, error) {
|
||||
u := fmt.Sprintf("licenses/%s", licenseName)
|
||||
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeLicensesPreview)
|
||||
|
||||
license := new(License)
|
||||
resp, err := s.client.Do(req, license)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return license, resp, err
|
||||
}
|
64
Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses_test.go
generated
vendored
Normal file
64
Godeps/_workspace/src/github.com/zachgersh/go-github/github/licenses_test.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2013 The go-github AUTHORS. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package github
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLicensesService_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/licenses", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeLicensesPreview)
|
||||
fmt.Fprint(w, `[{"key":"mit","name":"MIT","url":"https://api.github.com/licenses/mit"}]`)
|
||||
})
|
||||
|
||||
licenses, _, err := client.Licenses.List()
|
||||
if err != nil {
|
||||
t.Errorf("Licenses.List returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []License{{
|
||||
Key: String("mit"),
|
||||
Name: String("MIT"),
|
||||
URL: String("https://api.github.com/licenses/mit"),
|
||||
}}
|
||||
if !reflect.DeepEqual(licenses, want) {
|
||||
t.Errorf("Licenses.List returned %+v, want %+v", licenses, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicensesService_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/licenses/mit", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeLicensesPreview)
|
||||
fmt.Fprint(w, `{"key":"mit","name":"MIT"}`)
|
||||
})
|
||||
|
||||
license, _, err := client.Licenses.Get("mit")
|
||||
if err != nil {
|
||||
t.Errorf("Licenses.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &License{Key: String("mit"), Name: String("MIT")}
|
||||
if !reflect.DeepEqual(license, want) {
|
||||
t.Errorf("Licenses.Get returned %+v, want %+v", license, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicensesService_Get_invalidTemplate(t *testing.T) {
|
||||
_, _, err := client.Licenses.Get("%")
|
||||
testURLParseError(t, err)
|
||||
}
|
@@ -98,6 +98,10 @@ type APIMeta struct {
|
||||
// username and password, sudo mode, and two-factor authentication are
|
||||
// not supported on these servers.)
|
||||
VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"`
|
||||
|
||||
// An array of IP addresses in CIDR format specifying the addresses
|
||||
// which serve GitHub Pages websites.
|
||||
Pages []string `json:"pages,omitempty"`
|
||||
}
|
||||
|
||||
// APIMeta returns information about GitHub.com, the service. Or, if you access
|
||||
@@ -159,3 +163,35 @@ func (c *Client) Zen() (string, *Response, error) {
|
||||
|
||||
return buf.String(), resp, nil
|
||||
}
|
||||
|
||||
// ServiceHook represents a hook that has configuration settings, a list of
|
||||
// available events, and default events.
|
||||
type ServiceHook struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Events []string `json:"events,omitempty"`
|
||||
SupportedEvents []string `json:"supported_events,omitempty"`
|
||||
Schema [][]string `json:"schema,omitempty"`
|
||||
}
|
||||
|
||||
func (s *ServiceHook) String() string {
|
||||
return Stringify(s)
|
||||
}
|
||||
|
||||
// ListServiceHooks lists all of the available service hooks.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/webhooks/#services
|
||||
func (c *Client) ListServiceHooks() ([]ServiceHook, *Response, error) {
|
||||
u := "hooks"
|
||||
req, err := c.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
hooks := new([]ServiceHook)
|
||||
resp, err := c.Do(req, hooks)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return *hooks, resp, err
|
||||
}
|
@@ -72,7 +72,7 @@ func TestAPIMeta(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "verifiable_password_authentication": true}`)
|
||||
fmt.Fprint(w, `{"hooks":["h"], "git":["g"], "pages":["p"], "verifiable_password_authentication": true}`)
|
||||
})
|
||||
|
||||
meta, _, err := client.APIMeta()
|
||||
@@ -83,6 +83,7 @@ func TestAPIMeta(t *testing.T) {
|
||||
want := &APIMeta{
|
||||
Hooks: []string{"h"},
|
||||
Git: []string{"g"},
|
||||
Pages: []string{"p"},
|
||||
VerifiablePasswordAuthentication: Bool(true),
|
||||
}
|
||||
if !reflect.DeepEqual(want, meta) {
|
||||
@@ -135,3 +136,35 @@ func TestZen(t *testing.T) {
|
||||
t.Errorf("Zen returned %+v, want %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_ListServiceHooks(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[{
|
||||
"name":"n",
|
||||
"events":["e"],
|
||||
"supported_events":["s"],
|
||||
"schema":[
|
||||
["a", "b"]
|
||||
]
|
||||
}]`)
|
||||
})
|
||||
|
||||
hooks, _, err := client.Repositories.ListServiceHooks()
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.ListHooks returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []ServiceHook{{
|
||||
Name: String("n"),
|
||||
Events: []string{"e"},
|
||||
SupportedEvents: []string{"s"},
|
||||
Schema: [][]string{{"a", "b"}},
|
||||
}}
|
||||
if !reflect.DeepEqual(hooks, want) {
|
||||
t.Errorf("Repositories.ListServiceHooks returned %+v, want %+v", hooks, want)
|
||||
}
|
||||
}
|
104
Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks.go
generated
vendored
Normal file
104
Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2015 The go-github AUTHORS. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package github
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ListHooks lists all Hooks for the specified organization.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks
|
||||
func (s *OrganizationsService) ListHooks(org string, opt *ListOptions) ([]Hook, *Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks", org)
|
||||
u, err := addOptions(u, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
hooks := new([]Hook)
|
||||
resp, err := s.client.Do(req, hooks)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return *hooks, resp, err
|
||||
}
|
||||
|
||||
// GetHook returns a single specified Hook.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook
|
||||
func (s *OrganizationsService) GetHook(org string, id int) (*Hook, *Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
hook := new(Hook)
|
||||
resp, err := s.client.Do(req, hook)
|
||||
return hook, resp, err
|
||||
}
|
||||
|
||||
// CreateHook creates a Hook for the specified org.
|
||||
// Name and Config are required fields.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook
|
||||
func (s *OrganizationsService) CreateHook(org string, hook *Hook) (*Hook, *Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks", org)
|
||||
req, err := s.client.NewRequest("POST", u, hook)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
h := new(Hook)
|
||||
resp, err := s.client.Do(req, h)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return h, resp, err
|
||||
}
|
||||
|
||||
// EditHook updates a specified Hook.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook
|
||||
func (s *OrganizationsService) EditHook(org string, id int, hook *Hook) (*Hook, *Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
|
||||
req, err := s.client.NewRequest("PATCH", u, hook)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
h := new(Hook)
|
||||
resp, err := s.client.Do(req, h)
|
||||
return h, resp, err
|
||||
}
|
||||
|
||||
// PingHook triggers a 'ping' event to be sent to the Hook.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook
|
||||
func (s *OrganizationsService) PingHook(org string, id int) (*Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id)
|
||||
req, err := s.client.NewRequest("POST", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// DeleteHook deletes a specified Hook.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook
|
||||
func (s *OrganizationsService) DeleteHook(org string, id int) (*Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
|
||||
req, err := s.client.NewRequest("DELETE", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.client.Do(req, nil)
|
||||
}
|
134
Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks_test.go
generated
vendored
Normal file
134
Godeps/_workspace/src/github.com/zachgersh/go-github/github/orgs_hooks_test.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2015 The go-github AUTHORS. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package github
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOrganizationsService_ListHooks(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testFormValues(t, r, values{"page": "2"})
|
||||
fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
|
||||
hooks, _, err := client.Organizations.ListHooks("o", opt)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.ListHooks returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []Hook{{ID: Int(1)}, {ID: Int(2)}}
|
||||
if !reflect.DeepEqual(hooks, want) {
|
||||
t.Errorf("Organizations.ListHooks returned %+v, want %+v", hooks, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_ListHooks_invalidOrg(t *testing.T) {
|
||||
_, _, err := client.Organizations.ListHooks("%", nil)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_GetHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"id":1}`)
|
||||
})
|
||||
|
||||
hook, _, err := client.Organizations.GetHook("o", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.GetHook returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Hook{ID: Int(1)}
|
||||
if !reflect.DeepEqual(hook, want) {
|
||||
t.Errorf("Organizations.GetHook returned %+v, want %+v", hook, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_GetHook_invalidOrg(t *testing.T) {
|
||||
_, _, err := client.Organizations.GetHook("%", 1)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_EditHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
input := &Hook{Name: String("t")}
|
||||
|
||||
mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(Hook)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PATCH")
|
||||
if !reflect.DeepEqual(v, input) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, input)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, `{"id":1}`)
|
||||
})
|
||||
|
||||
hook, _, err := client.Organizations.EditHook("o", 1, input)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.EditHook returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Hook{ID: Int(1)}
|
||||
if !reflect.DeepEqual(hook, want) {
|
||||
t.Errorf("Organizations.EditHook returned %+v, want %+v", hook, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_EditHook_invalidOrg(t *testing.T) {
|
||||
_, _, err := client.Organizations.EditHook("%", 1, nil)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_PingHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
})
|
||||
|
||||
_, err := client.Organizations.PingHook("o", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.PingHook returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_DeleteHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/hooks/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Organizations.DeleteHook("o", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.DeleteHook returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_DeleteHook_invalidOrg(t *testing.T) {
|
||||
_, err := client.Organizations.DeleteHook("%", 1)
|
||||
testURLParseError(t, err)
|
||||
}
|
@@ -15,7 +15,16 @@ type Membership struct {
|
||||
// Possible values are: "active", "pending"
|
||||
State *string `json:"state,omitempty"`
|
||||
|
||||
// TODO(willnorris): add docs
|
||||
// Role identifies the user's role within the organization or team.
|
||||
// Possible values for organization membership:
|
||||
// member - non-owner organization member
|
||||
// admin - organization owner
|
||||
//
|
||||
// Possible values for team membership are:
|
||||
// member - a normal member of the team
|
||||
// maintainer - a team maintainer. Able to add/remove other team
|
||||
// members, promote other team members to team
|
||||
// maintainer, and edit the team’s name and description
|
||||
Role *string `json:"role,omitempty"`
|
||||
|
||||
// For organization membership, the API URL of the organization.
|
||||
@@ -43,6 +52,15 @@ type ListMembersOptions struct {
|
||||
// 2fa_disabled, all. Default is "all".
|
||||
Filter string `url:"filter,omitempty"`
|
||||
|
||||
// Role filters memebers returned by their role in the organization.
|
||||
// Possible values are:
|
||||
// all - all members of the organization, regardless of role
|
||||
// admin - organization owners
|
||||
// member - non-organization members
|
||||
//
|
||||
// Default is "all".
|
||||
Role string `url:"role,omitempty"`
|
||||
|
||||
ListOptions
|
||||
}
|
||||
|
||||
@@ -68,6 +86,10 @@ func (s *OrganizationsService) ListMembers(org string, opt *ListMembersOptions)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if opt != nil && opt.Role != "" {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
members := new([]User)
|
||||
resp, err := s.client.Do(req, members)
|
||||
if err != nil {
|
||||
@@ -120,7 +142,8 @@ func (s *OrganizationsService) RemoveMember(org, user string) (*Response, error)
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// PublicizeMembership publicizes a user's membership in an organization.
|
||||
// PublicizeMembership publicizes a user's membership in an organization. (A
|
||||
// user cannot publicize the membership for another user.)
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/members/#publicize-a-users-membership
|
||||
func (s *OrganizationsService) PublicizeMembership(org, user string) (*Response, error) {
|
||||
@@ -171,9 +194,6 @@ func (s *OrganizationsService) ListOrgMemberships(opt *ListOrgMembershipsOptions
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
|
||||
var memberships []Membership
|
||||
resp, err := s.client.Do(req, &memberships)
|
||||
if err != nil {
|
||||
@@ -183,20 +203,25 @@ func (s *OrganizationsService) ListOrgMemberships(opt *ListOrgMembershipsOptions
|
||||
return memberships, resp, err
|
||||
}
|
||||
|
||||
// GetOrgMembership gets the membership for the authenticated user for the
|
||||
// specified organization.
|
||||
// GetOrgMembership gets the membership for a user in a specified organization.
|
||||
// Passing an empty string for user will get the membership for the
|
||||
// authenticated user.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-organization-membership
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/members/#get-your-organization-membership
|
||||
func (s *OrganizationsService) GetOrgMembership(org string) (*Membership, *Response, error) {
|
||||
u := fmt.Sprintf("user/memberships/orgs/%v", org)
|
||||
func (s *OrganizationsService) GetOrgMembership(user, org string) (*Membership, *Response, error) {
|
||||
var u string
|
||||
if user != "" {
|
||||
u = fmt.Sprintf("orgs/%v/memberships/%v", org, user)
|
||||
} else {
|
||||
u = fmt.Sprintf("user/memberships/orgs/%v", org)
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
|
||||
membership := new(Membership)
|
||||
resp, err := s.client.Do(req, membership)
|
||||
if err != nil {
|
||||
@@ -206,20 +231,25 @@ func (s *OrganizationsService) GetOrgMembership(org string) (*Membership, *Respo
|
||||
return membership, resp, err
|
||||
}
|
||||
|
||||
// EditOrgMembership edits the membership for the authenticated user for the
|
||||
// specified organization.
|
||||
// EditOrgMembership edits the membership for user in specified organization.
|
||||
// Passing an empty string for user will edit the membership for the
|
||||
// authenticated user.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership
|
||||
func (s *OrganizationsService) EditOrgMembership(org string, membership *Membership) (*Membership, *Response, error) {
|
||||
u := fmt.Sprintf("user/memberships/orgs/%v", org)
|
||||
func (s *OrganizationsService) EditOrgMembership(user, org string, membership *Membership) (*Membership, *Response, error) {
|
||||
var u string
|
||||
if user != "" {
|
||||
u = fmt.Sprintf("orgs/%v/memberships/%v", org, user)
|
||||
} else {
|
||||
u = fmt.Sprintf("user/memberships/orgs/%v", org)
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("PATCH", u, membership)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
|
||||
m := new(Membership)
|
||||
resp, err := s.client.Do(req, m)
|
||||
if err != nil {
|
||||
@@ -228,3 +258,17 @@ func (s *OrganizationsService) EditOrgMembership(org string, membership *Members
|
||||
|
||||
return m, resp, err
|
||||
}
|
||||
|
||||
// RemoveOrgMembership removes user from the specified organization. If the
|
||||
// user has been invited to the organization, this will cancel their invitation.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership
|
||||
func (s *OrganizationsService) RemoveOrgMembership(user, org string) (*Response, error) {
|
||||
u := fmt.Sprintf("orgs/%v/memberships/%v", org, user)
|
||||
req, err := s.client.NewRequest("DELETE", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
@@ -19,8 +19,10 @@ func TestOrganizationsService_ListMembers(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
testFormValues(t, r, values{
|
||||
"filter": "2fa_disabled",
|
||||
"role": "admin",
|
||||
"page": "2",
|
||||
})
|
||||
fmt.Fprint(w, `[{"id":1}]`)
|
||||
@@ -29,6 +31,7 @@ func TestOrganizationsService_ListMembers(t *testing.T) {
|
||||
opt := &ListMembersOptions{
|
||||
PublicOnly: false,
|
||||
Filter: "2fa_disabled",
|
||||
Role: "admin",
|
||||
ListOptions: ListOptions{Page: 2},
|
||||
}
|
||||
members, _, err := client.Organizations.ListMembers("o", opt)
|
||||
@@ -217,7 +220,6 @@ func TestOrganizationsService_ListOrgMemberships(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
testFormValues(t, r, values{
|
||||
"state": "active",
|
||||
"page": "2",
|
||||
@@ -240,17 +242,16 @@ func TestOrganizationsService_ListOrgMemberships(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_GetOrgMembership(t *testing.T) {
|
||||
func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
fmt.Fprint(w, `{"url":"u"}`)
|
||||
})
|
||||
|
||||
membership, _, err := client.Organizations.GetOrgMembership("o")
|
||||
membership, _, err := client.Organizations.GetOrgMembership("", "o")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.GetOrgMembership returned error: %v", err)
|
||||
}
|
||||
@@ -261,7 +262,27 @@ func TestOrganizationsService_GetOrgMembership(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_EditOrgMembership(t *testing.T) {
|
||||
func TestOrganizationsService_GetOrgMembership_SpecifiedUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"url":"u"}`)
|
||||
})
|
||||
|
||||
membership, _, err := client.Organizations.GetOrgMembership("u", "o")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.GetOrgMembership returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Membership{URL: String("u")}
|
||||
if !reflect.DeepEqual(membership, want) {
|
||||
t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_EditOrgMembership_AuthenticatedUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
@@ -272,7 +293,6 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) {
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PATCH")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
if !reflect.DeepEqual(v, input) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, input)
|
||||
}
|
||||
@@ -280,7 +300,7 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) {
|
||||
fmt.Fprint(w, `{"url":"u"}`)
|
||||
})
|
||||
|
||||
membership, _, err := client.Organizations.EditOrgMembership("o", input)
|
||||
membership, _, err := client.Organizations.EditOrgMembership("", "o", input)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.EditOrgMembership returned error: %v", err)
|
||||
}
|
||||
@@ -290,3 +310,47 @@ func TestOrganizationsService_EditOrgMembership(t *testing.T) {
|
||||
t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_EditOrgMembership_SpecifiedUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
input := &Membership{State: String("active")}
|
||||
|
||||
mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(Membership)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PATCH")
|
||||
if !reflect.DeepEqual(v, input) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, input)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, `{"url":"u"}`)
|
||||
})
|
||||
|
||||
membership, _, err := client.Organizations.EditOrgMembership("u", "o", input)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.EditOrgMembership returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Membership{URL: String("u")}
|
||||
if !reflect.DeepEqual(membership, want) {
|
||||
t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_RemoveOrgMembership(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
_, err := client.Organizations.RemoveOrgMembership("u", "o")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err)
|
||||
}
|
||||
}
|
@@ -14,7 +14,21 @@ type Team struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
Slug *string `json:"slug,omitempty"`
|
||||
|
||||
// Permission is deprecated when creating or editing a team in an org
|
||||
// using the new GitHub permission model. It no longer identifies the
|
||||
// permission a team has on its repos, but only specifies the default
|
||||
// permission a repo is initially added with. Avoid confusion by
|
||||
// specifying a permission value when calling AddTeamRepo.
|
||||
Permission *string `json:"permission,omitempty"`
|
||||
|
||||
// Privacy identifies the level of privacy this team should have.
|
||||
// Possible values are:
|
||||
// secret - only visible to organization owners and members of this team
|
||||
// closed - visible to all members of this organization
|
||||
// Default is "secret".
|
||||
Privacy *string `json:"privacy,omitempty"`
|
||||
|
||||
MembersCount *int `json:"members_count,omitempty"`
|
||||
ReposCount *int `json:"repos_count,omitempty"`
|
||||
Organization *Organization `json:"organization,omitempty"`
|
||||
@@ -77,6 +91,10 @@ func (s *OrganizationsService) CreateTeam(org string, team *Team) (*Team, *Respo
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if team.Privacy != nil {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
t := new(Team)
|
||||
resp, err := s.client.Do(req, t)
|
||||
if err != nil {
|
||||
@@ -96,6 +114,10 @@ func (s *OrganizationsService) EditTeam(id int, team *Team) (*Team, *Response, e
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if team.Privacy != nil {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
t := new(Team)
|
||||
resp, err := s.client.Do(req, t)
|
||||
if err != nil {
|
||||
@@ -118,11 +140,21 @@ func (s *OrganizationsService) DeleteTeam(team int) (*Response, error) {
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// OrganizationListTeamMembersOptions specifies the optional parameters to the
|
||||
// OrganizationsService.ListTeamMembers method.
|
||||
type OrganizationListTeamMembersOptions struct {
|
||||
// Role filters members returned by their role in the team. Possible
|
||||
// values are "all", "member", "maintainer". Default is "all".
|
||||
Role string `url:"role,omitempty"`
|
||||
|
||||
ListOptions
|
||||
}
|
||||
|
||||
// ListTeamMembers lists all of the users who are members of the specified
|
||||
// team.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#list-team-members
|
||||
func (s *OrganizationsService) ListTeamMembers(team int, opt *ListOptions) ([]User, *Response, error) {
|
||||
func (s *OrganizationsService) ListTeamMembers(team int, opt *OrganizationListTeamMembersOptions) ([]User, *Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/members", team)
|
||||
u, err := addOptions(u, opt)
|
||||
if err != nil {
|
||||
@@ -134,6 +166,10 @@ func (s *OrganizationsService) ListTeamMembers(team int, opt *ListOptions) ([]Us
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if opt != nil && opt.Role != "" {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
members := new([]User)
|
||||
resp, err := s.client.Do(req, members)
|
||||
if err != nil {
|
||||
@@ -158,32 +194,6 @@ func (s *OrganizationsService) IsTeamMember(team int, user string) (bool, *Respo
|
||||
return member, resp, err
|
||||
}
|
||||
|
||||
// AddTeamMember adds a user to a team.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#add-team-member
|
||||
func (s *OrganizationsService) AddTeamMember(team int, user string) (*Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/members/%v", team, user)
|
||||
req, err := s.client.NewRequest("PUT", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// RemoveTeamMember removes a user from a team.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#remove-team-member
|
||||
func (s *OrganizationsService) RemoveTeamMember(team int, user string) (*Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/members/%v", team, user)
|
||||
req, err := s.client.NewRequest("DELETE", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// ListTeamRepos lists the repositories that the specified team has access to.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#list-team-repos
|
||||
@@ -208,19 +218,40 @@ func (s *OrganizationsService) ListTeamRepos(team int, opt *ListOptions) ([]Repo
|
||||
return *repos, resp, err
|
||||
}
|
||||
|
||||
// IsTeamRepo checks if a team manages the specified repository.
|
||||
// IsTeamRepo checks if a team manages the specified repository. If the
|
||||
// repository is managed by team, a Repository is returned which includes the
|
||||
// permissions team has for that repo.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#get-team-repo
|
||||
func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (bool, *Response, error) {
|
||||
func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (*Repository, *Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
manages, err := parseBoolResponse(err)
|
||||
return manages, resp, err
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionRepoPreview)
|
||||
|
||||
repository := new(Repository)
|
||||
resp, err := s.client.Do(req, repository)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return repository, resp, err
|
||||
}
|
||||
|
||||
// OrganizationAddTeamRepoOptions specifies the optional parameters to the
|
||||
// OrganizationsService.AddTeamRepo method.
|
||||
type OrganizationAddTeamRepoOptions struct {
|
||||
// Permission specifies the permission to grant the team on this repository.
|
||||
// Possible values are:
|
||||
// pull - team members can pull, but not push to or administer this repository
|
||||
// push - team members can pull and push, but not administer this repository
|
||||
// admin - team members can pull, push and administer this repository
|
||||
//
|
||||
// If not specified, the team's permission attribute will be used.
|
||||
Permission string `json:"permission,omitempty"`
|
||||
}
|
||||
|
||||
// AddTeamRepo adds a repository to be managed by the specified team. The
|
||||
@@ -228,13 +259,17 @@ func (s *OrganizationsService) IsTeamRepo(team int, owner string, repo string) (
|
||||
// belongs, or a direct fork of a repository owned by the organization.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/orgs/teams/#add-team-repo
|
||||
func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string) (*Response, error) {
|
||||
func (s *OrganizationsService) AddTeamRepo(team int, owner string, repo string, opt *OrganizationAddTeamRepoOptions) (*Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo)
|
||||
req, err := s.client.NewRequest("PUT", u, nil)
|
||||
req, err := s.client.NewRequest("PUT", u, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opt != nil {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
@@ -286,9 +321,6 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
|
||||
t := new(Membership)
|
||||
resp, err := s.client.Do(req, t)
|
||||
if err != nil {
|
||||
@@ -298,6 +330,20 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member
|
||||
return t, resp, err
|
||||
}
|
||||
|
||||
// OrganizationAddTeamMembershipOptions does stuff specifies the optional
|
||||
// parameters to the OrganizationsService.AddTeamMembership method.
|
||||
type OrganizationAddTeamMembershipOptions struct {
|
||||
// Role specifies the role the user should have in the team. Possible
|
||||
// values are:
|
||||
// member - a normal member of the team
|
||||
// maintainer - a team maintainer. Able to add/remove other team
|
||||
// members, promote other team members to team
|
||||
// maintainer, and edit the team’s name and description
|
||||
//
|
||||
// Default value is "member".
|
||||
Role string `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
// AddTeamMembership adds or invites a user to a team.
|
||||
//
|
||||
// In order to add a membership between a user and a team, the authenticated
|
||||
@@ -316,15 +362,16 @@ func (s *OrganizationsService) GetTeamMembership(team int, user string) (*Member
|
||||
// added as a member of the team.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/orgs/teams/#add-team-membership
|
||||
func (s *OrganizationsService) AddTeamMembership(team int, user string) (*Membership, *Response, error) {
|
||||
func (s *OrganizationsService) AddTeamMembership(team int, user string, opt *OrganizationAddTeamMembershipOptions) (*Membership, *Response, error) {
|
||||
u := fmt.Sprintf("teams/%v/memberships/%v", team, user)
|
||||
req, err := s.client.NewRequest("PUT", u, nil)
|
||||
req, err := s.client.NewRequest("PUT", u, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
if opt != nil {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
t := new(Membership)
|
||||
resp, err := s.client.Do(req, t)
|
||||
@@ -345,8 +392,5 @@ func (s *OrganizationsService) RemoveTeamMembership(team int, user string) (*Res
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeMembershipPreview)
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
@@ -64,13 +64,14 @@ func TestOrganizationsService_CreateTeam(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
input := &Team{Name: String("n")}
|
||||
input := &Team{Name: String("n"), Privacy: String("closed")}
|
||||
|
||||
mux.HandleFunc("/orgs/o/teams", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(Team)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
if !reflect.DeepEqual(v, input) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, input)
|
||||
}
|
||||
@@ -98,13 +99,14 @@ func TestOrganizationsService_EditTeam(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
input := &Team{Name: String("n")}
|
||||
input := &Team{Name: String("n"), Privacy: String("closed")}
|
||||
|
||||
mux.HandleFunc("/teams/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(Team)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PATCH")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
if !reflect.DeepEqual(v, input) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, input)
|
||||
}
|
||||
@@ -143,11 +145,12 @@ func TestOrganizationsService_ListTeamMembers(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/teams/1/members", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testFormValues(t, r, values{"page": "2"})
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
testFormValues(t, r, values{"role": "member", "page": "2"})
|
||||
fmt.Fprint(w, `[{"id":1}]`)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
opt := &OrganizationListTeamMembersOptions{Role: "member", ListOptions: ListOptions{Page: 2}}
|
||||
members, _, err := client.Organizations.ListTeamMembers(1, opt)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.ListTeamMembers returned error: %v", err)
|
||||
@@ -220,46 +223,6 @@ func TestOrganizationsService_IsTeamMember_invalidUser(t *testing.T) {
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_AddTeamMember(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "PUT")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
_, err := client.Organizations.AddTeamMember(1, "u")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.AddTeamMember returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_AddTeamMember_invalidUser(t *testing.T) {
|
||||
_, err := client.Organizations.AddTeamMember(1, "%")
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_RemoveTeamMember(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/teams/1/members/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
_, err := client.Organizations.RemoveTeamMember(1, "u")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.RemoveTeamMember returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_RemoveTeamMember_invalidUser(t *testing.T) {
|
||||
_, err := client.Organizations.RemoveTeamMember(1, "%")
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestOrganizationsService_PublicizeMembership(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
@@ -328,15 +291,18 @@ func TestOrganizationsService_IsTeamRepo_true(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionRepoPreview)
|
||||
fmt.Fprint(w, `{"id":1}`)
|
||||
})
|
||||
|
||||
managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
repo, _, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.IsTeamRepo returned error: %v", err)
|
||||
}
|
||||
if want := true; managed != want {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want)
|
||||
|
||||
want := &Repository{ID: Int(1)}
|
||||
if !reflect.DeepEqual(repo, want) {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", repo, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,12 +315,15 @@ func TestOrganizationsService_IsTeamRepo_false(t *testing.T) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
|
||||
managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.IsTeamRepo returned error: %v", err)
|
||||
repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
if err == nil {
|
||||
t.Errorf("Expected HTTP 404 response")
|
||||
}
|
||||
if want := false; managed != want {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want)
|
||||
if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want {
|
||||
t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want)
|
||||
}
|
||||
if repo != nil {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,12 +336,15 @@ func TestOrganizationsService_IsTeamRepo_error(t *testing.T) {
|
||||
http.Error(w, "BadRequest", http.StatusBadRequest)
|
||||
})
|
||||
|
||||
managed, _, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
repo, resp, err := client.Organizations.IsTeamRepo(1, "o", "r")
|
||||
if err == nil {
|
||||
t.Errorf("Expected HTTP 400 response")
|
||||
}
|
||||
if want := false; managed != want {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want %+v", managed, want)
|
||||
if got, want := resp.Response.StatusCode, http.StatusBadRequest; got != want {
|
||||
t.Errorf("Organizations.IsTeamRepo returned status %d, want %d", got, want)
|
||||
}
|
||||
if repo != nil {
|
||||
t.Errorf("Organizations.IsTeamRepo returned %+v, want nil", repo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,12 +357,22 @@ func TestOrganizationsService_AddTeamRepo(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
opt := &OrganizationAddTeamRepoOptions{Permission: "admin"}
|
||||
|
||||
mux.HandleFunc("/teams/1/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(OrganizationAddTeamRepoOptions)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PUT")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
if !reflect.DeepEqual(v, opt) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, opt)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
_, err := client.Organizations.AddTeamRepo(1, "o", "r")
|
||||
_, err := client.Organizations.AddTeamRepo(1, "o", "r", opt)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.AddTeamRepo returned error: %v", err)
|
||||
}
|
||||
@@ -405,14 +387,14 @@ func TestOrganizationsService_AddTeamRepo_noAccess(t *testing.T) {
|
||||
w.WriteHeader(422)
|
||||
})
|
||||
|
||||
_, err := client.Organizations.AddTeamRepo(1, "o", "r")
|
||||
_, err := client.Organizations.AddTeamRepo(1, "o", "r", nil)
|
||||
if err == nil {
|
||||
t.Errorf("Expcted error to be returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrganizationsService_AddTeamRepo_invalidOwner(t *testing.T) {
|
||||
_, err := client.Organizations.AddTeamRepo(1, "%", "r")
|
||||
_, err := client.Organizations.AddTeamRepo(1, "%", "r", nil)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
@@ -442,7 +424,6 @@ func TestOrganizationsService_GetTeamMembership(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
fmt.Fprint(w, `{"url":"u", "state":"active"}`)
|
||||
})
|
||||
|
||||
@@ -461,13 +442,22 @@ func TestOrganizationsService_AddTeamMembership(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
opt := &OrganizationAddTeamMembershipOptions{Role: "maintainer"}
|
||||
|
||||
mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(OrganizationAddTeamMembershipOptions)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PUT")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
if !reflect.DeepEqual(v, opt) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, opt)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, `{"url":"u", "state":"pending"}`)
|
||||
})
|
||||
|
||||
membership, _, err := client.Organizations.AddTeamMembership(1, "u")
|
||||
membership, _, err := client.Organizations.AddTeamMembership(1, "u", opt)
|
||||
if err != nil {
|
||||
t.Errorf("Organizations.AddTeamMembership returned error: %v", err)
|
||||
}
|
||||
@@ -484,7 +474,6 @@ func TestOrganizationsService_RemoveTeamMembership(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/teams/1/memberships/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
testHeader(t, r, "Accept", mediaTypeMembershipPreview)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
@@ -41,6 +41,8 @@ type PullRequest struct {
|
||||
HTMLURL *string `json:"html_url,omitempty"`
|
||||
IssueURL *string `json:"issue_url,omitempty"`
|
||||
StatusesURL *string `json:"statuses_url,omitempty"`
|
||||
DiffURL *string `json:"diff_url,omitempty"`
|
||||
PatchURL *string `json:"patch_url,omitempty"`
|
||||
|
||||
Head *PullRequestBranch `json:"head,omitempty"`
|
||||
Base *PullRequestBranch `json:"base,omitempty"`
|
||||
@@ -73,6 +75,15 @@ type PullRequestListOptions struct {
|
||||
// Base filters pull requests by base branch name.
|
||||
Base string `url:"base,omitempty"`
|
||||
|
||||
// Sort specifies how to sort pull requests. Possible values are: created,
|
||||
// updated, popularity, long-running. Default is "created".
|
||||
Sort string `url:"sort,omitempty"`
|
||||
|
||||
// Direction in which to sort pull requests. Possible values are: asc, desc.
|
||||
// If Sort is "created" or not specified, Default is "desc", otherwise Default
|
||||
// is "asc"
|
||||
Direction string `url:"direction,omitempty"`
|
||||
|
||||
ListOptions
|
||||
}
|
||||
|
@@ -93,7 +93,7 @@ func (s *PullRequestsService) GetComment(owner string, repo string, number int)
|
||||
|
||||
// CreateComment creates a new comment on the specified pull request.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment
|
||||
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment
|
||||
func (s *PullRequestsService) CreateComment(owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
|
||||
u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
|
||||
req, err := s.client.NewRequest("POST", u, comment)
|
@@ -23,12 +23,14 @@ func TestPullRequestsService_List(t *testing.T) {
|
||||
"state": "closed",
|
||||
"head": "h",
|
||||
"base": "b",
|
||||
"sort": "created",
|
||||
"direction": "desc",
|
||||
"page": "2",
|
||||
})
|
||||
fmt.Fprint(w, `[{"number":1}]`)
|
||||
})
|
||||
|
||||
opt := &PullRequestListOptions{"closed", "h", "b", ListOptions{Page: 2}}
|
||||
opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}}
|
||||
pulls, _, err := client.PullRequests.List("o", "r", opt)
|
||||
|
||||
if err != nil {
|
||||
@@ -98,6 +100,29 @@ func TestPullRequestsService_Get_headAndBase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPullRequestService_Get_DiffURLAndPatchURL(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"number":1,
|
||||
"diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff",
|
||||
"patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch"}`)
|
||||
})
|
||||
|
||||
pull, _, err := client.PullRequests.Get("o", "r", 1)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("PullRequests.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &PullRequest{Number: Int(1), DiffURL: String("https://github.com/octocat/Hello-World/pull/1347.diff"), PatchURL: String("https://github.com/octocat/Hello-World/pull/1347.patch")}
|
||||
if !reflect.DeepEqual(pull, want) {
|
||||
t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPullRequestsService_Get_invalidOwner(t *testing.T) {
|
||||
_, _, err := client.PullRequests.Get("%", "r", 1)
|
||||
testURLParseError(t, err)
|
@@ -49,6 +49,9 @@ type Repository struct {
|
||||
Organization *Organization `json:"organization,omitempty"`
|
||||
Permissions *map[string]bool `json:"permissions,omitempty"`
|
||||
|
||||
// Only provided when using RepositoriesService.Get while in preview
|
||||
License *License `json:"license,omitempty"`
|
||||
|
||||
// Additional mutable fields when creating and editing a repository
|
||||
Private *bool `json:"private"`
|
||||
HasIssues *bool `json:"has_issues"`
|
||||
@@ -255,6 +258,10 @@ func (s *RepositoriesService) Get(owner, repo string) (*Repository, *Response, e
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when the license support fully launches
|
||||
// https://developer.github.com/v3/licenses/#get-a-repositorys-license
|
||||
req.Header.Set("Accept", mediaTypeLicensesPreview)
|
||||
|
||||
repository := new(Repository)
|
||||
resp, err := s.client.Do(req, repository)
|
||||
if err != nil {
|
@@ -22,6 +22,8 @@ func (s *RepositoriesService) ListCollaborators(owner, repo string, opt *ListOpt
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
|
||||
users := new([]User)
|
||||
resp, err := s.client.Do(req, users)
|
||||
if err != nil {
|
||||
@@ -49,15 +51,33 @@ func (s *RepositoriesService) IsCollaborator(owner, repo, user string) (bool, *R
|
||||
return isCollab, resp, err
|
||||
}
|
||||
|
||||
// RepositoryAddCollaboratorOptions specifies the optional parameters to the
|
||||
// RepositoriesService.AddCollaborator method.
|
||||
type RepositoryAddCollaboratorOptions struct {
|
||||
// Permission specifies the permission to grant the user on this repository.
|
||||
// Possible values are:
|
||||
// pull - team members can pull, but not push to or administer this repository
|
||||
// push - team members can pull and push, but not administer this repository
|
||||
// admin - team members can pull, push and administer this repository
|
||||
//
|
||||
// Default value is "pull". This option is only valid for organization-owned repositories.
|
||||
Permission string `json:"permission,omitempty"`
|
||||
}
|
||||
|
||||
// AddCollaborator adds the specified Github user as collaborator to the given repo.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/repos/collaborators/#add-collaborator
|
||||
func (s *RepositoriesService) AddCollaborator(owner, repo, user string) (*Response, error) {
|
||||
func (s *RepositoriesService) AddCollaborator(owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) {
|
||||
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
|
||||
req, err := s.client.NewRequest("PUT", u, nil)
|
||||
req, err := s.client.NewRequest("PUT", u, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opt != nil {
|
||||
req.Header.Set("Accept", mediaTypeOrgPermissionPreview)
|
||||
}
|
||||
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
@@ -18,6 +19,7 @@ func TestRepositoriesService_ListCollaborators(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/repos/o/r/collaborators", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
testFormValues(t, r, values{"page": "2"})
|
||||
fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
|
||||
})
|
||||
@@ -86,19 +88,29 @@ func TestRepositoriesService_AddCollaborator(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
opt := &RepositoryAddCollaboratorOptions{Permission: "admin"}
|
||||
|
||||
mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(RepositoryAddCollaboratorOptions)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PUT")
|
||||
testHeader(t, r, "Accept", mediaTypeOrgPermissionPreview)
|
||||
if !reflect.DeepEqual(v, opt) {
|
||||
t.Errorf("Request body = %+v, want %+v", v, opt)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
_, err := client.Repositories.AddCollaborator("o", "r", "u")
|
||||
_, err := client.Repositories.AddCollaborator("o", "r", "u", opt)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.AddCollaborator returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_AddCollaborator_invalidUser(t *testing.T) {
|
||||
_, err := client.Repositories.AddCollaborator("%", "%", "%")
|
||||
_, err := client.Repositories.AddCollaborator("%", "%", "%", nil)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
@@ -62,6 +62,7 @@ func (c CommitFile) String() string {
|
||||
// See CompareCommits() for details.
|
||||
type CommitsComparison struct {
|
||||
BaseCommit *RepositoryCommit `json:"base_commit,omitempty"`
|
||||
MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"`
|
||||
|
||||
// Head can be 'behind' or 'ahead'
|
||||
Status *string `json:"status,omitempty"`
|
@@ -13,8 +13,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
)
|
||||
|
||||
// RepositoryContent represents a file or directory in a github repository.
|
||||
@@ -27,8 +29,9 @@ type RepositoryContent struct {
|
||||
Content *string `json:"content,omitempty"`
|
||||
SHA *string `json:"sha,omitempty"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
GitURL *string `json:"giturl,omitempty"`
|
||||
HTMLURL *string `json:"htmlurl,omitempty"`
|
||||
GitURL *string `json:"git_url,omitempty"`
|
||||
HTMLURL *string `json:"html_url,omitempty"`
|
||||
DownloadURL *string `json:"download_url,omitempty"`
|
||||
}
|
||||
|
||||
// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile.
|
||||
@@ -90,6 +93,32 @@ func (s *RepositoriesService) GetReadme(owner, repo string, opt *RepositoryConte
|
||||
return readme, resp, err
|
||||
}
|
||||
|
||||
// DownloadContents returns an io.ReadCloser that reads the contents of the
|
||||
// specified file. This function will work with files of any size, as opposed
|
||||
// to GetContents which is limited to 1 Mb files. It is the caller's
|
||||
// responsibility to close the ReadCloser.
|
||||
func (s *RepositoriesService) DownloadContents(owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) {
|
||||
dir := path.Dir(filepath)
|
||||
filename := path.Base(filepath)
|
||||
_, dirContents, _, err := s.GetContents(owner, repo, dir, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, contents := range dirContents {
|
||||
if *contents.Name == filename {
|
||||
if contents.DownloadURL == nil || *contents.DownloadURL == "" {
|
||||
return nil, fmt.Errorf("No download link found for %s", filepath)
|
||||
}
|
||||
resp, err := s.client.client.Get(*contents.DownloadURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("No file named %s found in %s", filename, dir)
|
||||
}
|
||||
|
||||
// GetContents can return either the metadata and content of a single file
|
||||
// (when path references a file) or the metadata of all the files and/or
|
||||
// subdirectories of a directory (when path references a directory). To make it
|
@@ -2,6 +2,7 @@ package github
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -54,7 +55,70 @@ func TestRepositoriesService_GetReadme(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_GetContent_File(t *testing.T) {
|
||||
func TestRepositoriesService_DownloadContents_Success(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[{
|
||||
"type": "file",
|
||||
"name": "f",
|
||||
"download_url": "`+server.URL+`/download/f"
|
||||
}]`)
|
||||
})
|
||||
mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, "foo")
|
||||
})
|
||||
|
||||
r, err := client.Repositories.DownloadContents("o", "r", "d/f", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.DownloadContents returned error: %v", err)
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading response body: %v", err)
|
||||
}
|
||||
r.Close()
|
||||
|
||||
if got, want := string(bytes), "foo"; got != want {
|
||||
t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[{
|
||||
"type": "file",
|
||||
"name": "f",
|
||||
}]`)
|
||||
})
|
||||
|
||||
_, err := client.Repositories.DownloadContents("o", "r", "d/f", nil)
|
||||
if err == nil {
|
||||
t.Errorf("Repositories.DownloadContents did not return expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[]`)
|
||||
})
|
||||
|
||||
_, err := client.Repositories.DownloadContents("o", "r", "d/f", nil)
|
||||
if err == nil {
|
||||
t.Errorf("Repositories.DownloadContents did not return expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_GetContents_File(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -69,7 +133,7 @@ func TestRepositoriesService_GetContent_File(t *testing.T) {
|
||||
})
|
||||
fileContents, _, _, err := client.Repositories.GetContents("o", "r", "p", &RepositoryContentGetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.GetContents_File returned error: %v", err)
|
||||
t.Errorf("Repositories.GetContents returned error: %v", err)
|
||||
}
|
||||
want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")}
|
||||
if !reflect.DeepEqual(fileContents, want) {
|
||||
@@ -77,7 +141,7 @@ func TestRepositoriesService_GetContent_File(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_GetContent_Directory(t *testing.T) {
|
||||
func TestRepositoriesService_GetContents_Directory(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -96,7 +160,7 @@ func TestRepositoriesService_GetContent_Directory(t *testing.T) {
|
||||
})
|
||||
_, directoryContents, _, err := client.Repositories.GetContents("o", "r", "p", &RepositoryContentGetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.GetContents_Directory returned error: %v", err)
|
||||
t.Errorf("Repositories.GetContents returned error: %v", err)
|
||||
}
|
||||
want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")},
|
||||
{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}}
|
@@ -30,7 +30,7 @@ type DeploymentRequest struct {
|
||||
Ref *string `json:"ref,omitempty"`
|
||||
Task *string `json:"task,omitempty"`
|
||||
AutoMerge *bool `json:"auto_merge,omitempty"`
|
||||
RequiredContexts []string `json:"required_contexts,omitempty"`
|
||||
RequiredContexts *[]string `json:"required_contexts,omitempty"`
|
||||
Payload *string `json:"payload,omitempty"`
|
||||
Environment *string `json:"environment,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
@@ -69,9 +69,6 @@ func (s *RepositoriesService) ListDeployments(owner, repo string, opt *Deploymen
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeDeploymentPreview)
|
||||
|
||||
deployments := new([]Deployment)
|
||||
resp, err := s.client.Do(req, deployments)
|
||||
if err != nil {
|
||||
@@ -92,9 +89,6 @@ func (s *RepositoriesService) CreateDeployment(owner, repo string, request *Depl
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeDeploymentPreview)
|
||||
|
||||
d := new(Deployment)
|
||||
resp, err := s.client.Do(req, d)
|
||||
if err != nil {
|
||||
@@ -138,9 +132,6 @@ func (s *RepositoriesService) ListDeploymentStatuses(owner, repo string, deploym
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeDeploymentPreview)
|
||||
|
||||
statuses := new([]DeploymentStatus)
|
||||
resp, err := s.client.Do(req, statuses)
|
||||
if err != nil {
|
||||
@@ -161,9 +152,6 @@ func (s *RepositoriesService) CreateDeploymentStatus(owner, repo string, deploym
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: remove custom Accept header when this API fully launches
|
||||
req.Header.Set("Accept", mediaTypeDeploymentPreview)
|
||||
|
||||
d := new(DeploymentStatus)
|
||||
resp, err := s.client.Do(req, d)
|
||||
if err != nil {
|
@@ -164,6 +164,18 @@ func (s *RepositoriesService) DeleteHook(owner, repo string, id int) (*Response,
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// PingHook triggers a 'ping' event to be sent to the Hook.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook
|
||||
func (s *RepositoriesService) PingHook(owner, repo string, id int) (*Response, error) {
|
||||
u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id)
|
||||
req, err := s.client.NewRequest("POST", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// TestHook triggers a test Hook by github.
|
||||
//
|
||||
// GitHub API docs: http://developer.github.com/v3/repos/hooks/#test-a-push-hook
|
||||
@@ -176,34 +188,7 @@ func (s *RepositoriesService) TestHook(owner, repo string, id int) (*Response, e
|
||||
return s.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// ServiceHook represents a hook that has configuration settings, a list of
|
||||
// available events, and default events.
|
||||
type ServiceHook struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Events []string `json:"events,omitempty"`
|
||||
SupportedEvents []string `json:"supported_events,omitempty"`
|
||||
Schema [][]string `json:"schema,omitempty"`
|
||||
}
|
||||
|
||||
func (s *ServiceHook) String() string {
|
||||
return Stringify(s)
|
||||
}
|
||||
|
||||
// ListServiceHooks lists all of the available service hooks.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/webhooks/#services
|
||||
// ListServiceHooks is deprecated. Use Client.ListServiceHooks instead.
|
||||
func (s *RepositoriesService) ListServiceHooks() ([]ServiceHook, *Response, error) {
|
||||
u := "hooks"
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
hooks := new([]ServiceHook)
|
||||
resp, err := s.client.Do(req, hooks)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return *hooks, resp, err
|
||||
return s.client.ListServiceHooks()
|
||||
}
|
@@ -153,6 +153,20 @@ func TestRepositoriesService_DeleteHook_invalidOwner(t *testing.T) {
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestRepositoriesService_PingHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/hooks/1/pings", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
})
|
||||
|
||||
_, err := client.Repositories.PingHook("o", "r", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.PingHook returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_TestHook(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
@@ -171,35 +185,3 @@ func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) {
|
||||
_, err := client.Repositories.TestHook("%", "%", 1)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestRepositoriesService_ListServiceHooks(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `[{
|
||||
"name":"n",
|
||||
"events":["e"],
|
||||
"supported_events":["s"],
|
||||
"schema":[
|
||||
["a", "b"]
|
||||
]
|
||||
}]`)
|
||||
})
|
||||
|
||||
hooks, _, err := client.Repositories.ListServiceHooks()
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.ListHooks returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []ServiceHook{{
|
||||
Name: String("n"),
|
||||
Events: []string{"e"},
|
||||
SupportedEvents: []string{"s"},
|
||||
Schema: [][]string{{"a", "b"}},
|
||||
}}
|
||||
if !reflect.DeepEqual(hooks, want) {
|
||||
t.Errorf("Repositories.ListServiceHooks returned %+v, want %+v", hooks, want)
|
||||
}
|
||||
}
|
@@ -8,7 +8,9 @@ package github
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
@@ -85,8 +87,27 @@ func (s *RepositoriesService) ListReleases(owner, repo string, opt *ListOptions)
|
||||
// GitHub API docs: http://developer.github.com/v3/repos/releases/#get-a-single-release
|
||||
func (s *RepositoriesService) GetRelease(owner, repo string, id int) (*RepositoryRelease, *Response, error) {
|
||||
u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)
|
||||
return s.getSingleRelease(u)
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
// GetLatestRelease fetches the latest published release for the repository.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-the-latest-release
|
||||
func (s *RepositoriesService) GetLatestRelease(owner, repo string) (*RepositoryRelease, *Response, error) {
|
||||
u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo)
|
||||
return s.getSingleRelease(u)
|
||||
}
|
||||
|
||||
// GetReleaseByTag fetches a release with the specified tag.
|
||||
//
|
||||
// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name
|
||||
func (s *RepositoriesService) GetReleaseByTag(owner, repo, tag string) (*RepositoryRelease, *Response, error) {
|
||||
u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag)
|
||||
return s.getSingleRelease(u)
|
||||
}
|
||||
|
||||
func (s *RepositoriesService) getSingleRelease(url string) (*RepositoryRelease, *Response, error) {
|
||||
req, err := s.client.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -192,6 +213,54 @@ func (s *RepositoriesService) GetReleaseAsset(owner, repo string, id int) (*Rele
|
||||
return asset, resp, err
|
||||
}
|
||||
|
||||
// DowloadReleaseAsset downloads a release asset.
|
||||
//
|
||||
// DowloadReleaseAsset returns an io.ReadCloser that reads the contents of the
|
||||
// specified release asset. It is the caller's responsibility to close the ReadCloser.
|
||||
//
|
||||
// GitHub API docs : http://developer.github.com/v3/repos/releases/#get-a-single-release-asset
|
||||
func (s *RepositoriesService) DownloadReleaseAsset(owner, repo string, id int) (io.ReadCloser, error) {
|
||||
u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
|
||||
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Accept", defaultMediaType)
|
||||
|
||||
var resp *http.Response
|
||||
if s.client.client.Transport == nil {
|
||||
resp, err = http.DefaultTransport.RoundTrip(req)
|
||||
} else {
|
||||
resp, err = s.client.client.Transport.RoundTrip(req)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// GitHub API streamed the asset directly
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusFound {
|
||||
return nil, fmt.Errorf("Expected status code 200 or 302, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// GitHub API redirected to pre-signed S3 URL
|
||||
downloadURL, err := resp.Location()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err = http.Get(downloadURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
// EditReleaseAsset edits a repository release asset.
|
||||
//
|
||||
// GitHub API docs : http://developer.github.com/v3/repos/releases/#edit-a-release-asset
|
@@ -6,8 +6,10 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
@@ -55,6 +57,46 @@ func TestRepositoriesService_GetRelease(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_GetLatestRelease(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/releases/latest", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"id":3}`)
|
||||
})
|
||||
|
||||
release, resp, err := client.Repositories.GetLatestRelease("o", "r")
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body)
|
||||
}
|
||||
|
||||
want := &RepositoryRelease{ID: Int(3)}
|
||||
if !reflect.DeepEqual(release, want) {
|
||||
t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_GetReleaseByTag(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"id":13}`)
|
||||
})
|
||||
|
||||
release, resp, err := client.Repositories.GetReleaseByTag("o", "r", "foo")
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body)
|
||||
}
|
||||
|
||||
want := &RepositoryRelease{ID: Int(13)}
|
||||
if !reflect.DeepEqual(release, want) {
|
||||
t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_CreateRelease(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
@@ -164,6 +206,64 @@ func TestRepositoriesService_GetReleaseAsset(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", defaultMediaType)
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt")
|
||||
fmt.Fprint(w, "Hello World")
|
||||
})
|
||||
|
||||
reader, err := client.Repositories.DowloadReleaseAsset("o", "r", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned error: %v", err)
|
||||
}
|
||||
want := []byte("Hello World")
|
||||
content, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned bad reader: %v", err)
|
||||
}
|
||||
if !bytes.Equal(want, content) {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned %+v, want %+v", content, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testHeader(t, r, "Accept", defaultMediaType)
|
||||
w.Header().Set("Location", server.URL+"/github-cloud/releases/1/hello-world.txt")
|
||||
w.WriteHeader(http.StatusFound)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/github-cloud/releases/1/hello-world.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt")
|
||||
fmt.Fprint(w, "Hello World")
|
||||
})
|
||||
|
||||
reader, err := client.Repositories.DowloadReleaseAsset("o", "r", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned error: %v", err)
|
||||
}
|
||||
want := []byte("Hello World")
|
||||
content, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned bad reader: %v", err)
|
||||
}
|
||||
if !bytes.Equal(want, content) {
|
||||
t.Errorf("Repositories.DowloadReleaseAsset returned %+v, want %+v", content, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoriesService_EditReleaseAsset(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
@@ -45,7 +45,6 @@ func TestRepositoriesService_List_specifiedUser(t *testing.T) {
|
||||
"direction": "asc",
|
||||
"page": "2",
|
||||
})
|
||||
|
||||
fmt.Fprint(w, `[{"id":1}]`)
|
||||
})
|
||||
|
||||
@@ -191,7 +190,8 @@ func TestRepositoriesService_Get(t *testing.T) {
|
||||
|
||||
mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"}}`)
|
||||
testHeader(t, r, "Accept", mediaTypeLicensesPreview)
|
||||
fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
|
||||
})
|
||||
|
||||
repo, _, err := client.Repositories.Get("o", "r")
|
||||
@@ -199,7 +199,7 @@ func TestRepositoriesService_Get(t *testing.T) {
|
||||
t.Errorf("Repositories.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
want := &Repository{ID: Int(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}}
|
||||
want := &Repository{ID: Int(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}}
|
||||
if !reflect.DeepEqual(repo, want) {
|
||||
t.Errorf("Repositories.Get returned %+v, want %+v", repo, want)
|
||||
}
|
@@ -59,6 +59,10 @@ type User struct {
|
||||
// TextMatches is only populated from search results that request text matches
|
||||
// See: search.go and https://developer.github.com/v3/search/#text-match-metadata
|
||||
TextMatches []TextMatch `json:"text_matches,omitempty"`
|
||||
|
||||
// Permissions identifies the permissions that a user has on a given
|
||||
// repository. This is only populated when calling Repositories.ListCollaborators.
|
||||
Permissions *map[string]bool `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user