Update go-github library

This commit is contained in:
Luke Kysow
2018-12-12 09:55:17 -06:00
parent e001353ae9
commit 139f05ab49
170 changed files with 14305 additions and 3086 deletions

View File

@@ -27,10 +27,9 @@ import (
)
const (
libraryVersion = "12"
defaultBaseURL = "https://api.github.com/"
uploadBaseURL = "https://uploads.github.com/"
userAgent = "go-github/" + libraryVersion
userAgent = "go-github"
headerRateLimit = "X-RateLimit-Limit"
headerRateRemaining = "X-RateLimit-Remaining"
@@ -46,21 +45,18 @@ const (
// Media Type values to access preview APIs
// https://developer.github.com/changes/2015-03-09-licenses-api/
mediaTypeLicensesPreview = "application/vnd.github.drax-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-11-11-protected-branches-api/
mediaTypeProtectedBranchesPreview = "application/vnd.github.loki-preview+json"
// https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/
mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json"
// https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/
mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json"
// https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/
mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json"
// https://developer.github.com/changes/2016-02-19-source-import-preview-api/
mediaTypeImportPreview = "application/vnd.github.barred-rock-preview"
@@ -100,8 +96,41 @@ const (
// https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/
mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json"
// https://developer.github.com/changes/2017-07-26-team-review-request-thor-preview/
mediaTypeTeamReviewPreview = "application/vnd.github.thor-preview+json"
// https://developer.github.com/changes/2017-08-30-preview-nested-teams/
mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json"
// https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/
mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json"
// https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/
mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json"
// https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/
mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json"
// https://developer.github.com/changes/2018-02-22-label-description-search-preview/
mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json"
// https://developer.github.com/changes/2018-02-07-team-discussions-api/
mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json"
// https://developer.github.com/changes/2018-03-21-hovercard-api-preview/
mediaTypeHovercardPreview = "application/vnd.github.hagar-preview+json"
// https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/
mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json"
// https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/
mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json"
// https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/
mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview"
// https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/
mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json"
// https://developer.github.com/changes/2018-09-05-project-card-events/
mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json"
)
// A Client manages communication with the GitHub API.
@@ -130,19 +159,22 @@ type Client struct {
Admin *AdminService
Apps *AppsService
Authorizations *AuthorizationsService
Checks *ChecksService
Gists *GistsService
Git *GitService
Gitignores *GitignoresService
Issues *IssuesService
Licenses *LicensesService
Marketplace *MarketplaceService
Migrations *MigrationService
Organizations *OrganizationsService
Projects *ProjectsService
PullRequests *PullRequestsService
Reactions *ReactionsService
Repositories *RepositoriesService
Search *SearchService
Teams *TeamsService
Users *UsersService
Licenses *LicensesService
Migrations *MigrationService
Reactions *ReactionsService
}
type service struct {
@@ -219,11 +251,13 @@ func NewClient(httpClient *http.Client) *Client {
c.Admin = (*AdminService)(&c.common)
c.Apps = (*AppsService)(&c.common)
c.Authorizations = (*AuthorizationsService)(&c.common)
c.Checks = (*ChecksService)(&c.common)
c.Gists = (*GistsService)(&c.common)
c.Git = (*GitService)(&c.common)
c.Gitignores = (*GitignoresService)(&c.common)
c.Issues = (*IssuesService)(&c.common)
c.Licenses = (*LicensesService)(&c.common)
c.Marketplace = &MarketplaceService{client: c}
c.Migrations = (*MigrationService)(&c.common)
c.Organizations = (*OrganizationsService)(&c.common)
c.Projects = (*ProjectsService)(&c.common)
@@ -231,10 +265,42 @@ func NewClient(httpClient *http.Client) *Client {
c.Reactions = (*ReactionsService)(&c.common)
c.Repositories = (*RepositoriesService)(&c.common)
c.Search = (*SearchService)(&c.common)
c.Teams = (*TeamsService)(&c.common)
c.Users = (*UsersService)(&c.common)
return c
}
// NewEnterpriseClient returns a new GitHub API client with provided
// base URL and upload URL (often the same URL).
// If either URL does not have a trailing slash, one is added automatically.
// If a nil httpClient is provided, http.DefaultClient will be used.
//
// Note that NewEnterpriseClient is a convenience helper only;
// its behavior is equivalent to using NewClient, followed by setting
// the BaseURL and UploadURL fields.
func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) {
baseEndpoint, err := url.Parse(baseURL)
if err != nil {
return nil, err
}
if !strings.HasSuffix(baseEndpoint.Path, "/") {
baseEndpoint.Path += "/"
}
uploadEndpoint, err := url.Parse(uploadURL)
if err != nil {
return nil, err
}
if !strings.HasSuffix(uploadEndpoint.Path, "/") {
uploadEndpoint.Path += "/"
}
c := NewClient(httpClient)
c.BaseURL = baseEndpoint
c.UploadURL = uploadEndpoint
return c, nil
}
// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
@@ -252,7 +318,9 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
var buf io.ReadWriter
if body != nil {
buf = new(bytes.Buffer)
err := json.NewEncoder(buf).Encode(body)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(body)
if err != nil {
return nil, err
}
@@ -316,7 +384,9 @@ type Response struct {
FirstPage int
LastPage int
Rate
// Explicitly specify the Rate type so Rate's String() receiver doesn't
// propagate to Response.
Rate Rate
}
// newResponse creates a new Response for the provided http.Response.
@@ -431,12 +501,7 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res
return nil, err
}
defer func() {
// Drain up to 512 bytes and close the body to let the Transport reuse the connection
io.CopyN(ioutil.Discard, resp.Body, 512)
resp.Body.Close()
}()
defer resp.Body.Close()
response := newResponse(resp)
@@ -446,8 +511,22 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res
err = CheckResponse(resp)
if err != nil {
// even though there was an error, we still return the response
// in case the caller wants to inspect it further
// Special case for AcceptedErrors. If an AcceptedError
// has been encountered, the response's payload will be
// added to the AcceptedError and returned.
//
// Issue #1022
aerr, ok := err.(*AcceptedError)
if ok {
b, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
return response, readErr
}
aerr.Raw = b
return response, aerr
}
return response, err
}
@@ -455,9 +534,12 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res
if w, ok := v.(io.Writer); ok {
io.Copy(w, resp.Body)
} else {
err = json.NewDecoder(resp.Body).Decode(v)
if err == io.EOF {
err = nil // ignore EOF errors caused by empty response body
decErr := json.NewDecoder(resp.Body).Decode(v)
if decErr == io.EOF {
decErr = nil // ignore EOF errors caused by empty response body
}
if decErr != nil {
err = decErr
}
}
}
@@ -547,14 +629,17 @@ func (r *RateLimitError) Error() string {
// Technically, 202 Accepted is not a real error, it's just used to
// indicate that results are not ready yet, but should be available soon.
// The request can be repeated after some time.
type AcceptedError struct{}
type AcceptedError struct {
// Raw contains the response body.
Raw []byte
}
func (*AcceptedError) Error() string {
return "job scheduled on GitHub side; try again later"
}
// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the
// "documentation_url" field value equal to "https://developer.github.com/v3#abuse-rate-limits".
// "documentation_url" field value equal to "https://developer.github.com/v3/#abuse-rate-limits".
type AbuseRateLimitError struct {
Response *http.Response // HTTP response that caused this error
Message string `json:"message"` // error message
@@ -646,7 +731,7 @@ func CheckResponse(r *http.Response) error {
Response: errorResponse.Response,
Message: errorResponse.Message,
}
case r.StatusCode == http.StatusForbidden && errorResponse.DocumentationURL == "https://developer.github.com/v3#abuse-rate-limits":
case r.StatusCode == http.StatusForbidden && strings.HasSuffix(errorResponse.DocumentationURL, "/v3/#abuse-rate-limits"):
abuseRateLimitError := &AbuseRateLimitError{
Response: errorResponse.Response,
Message: errorResponse.Message,
@@ -812,14 +897,21 @@ func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*htt
// To set extra querystring params, we must make a copy of the Request so
// that we don't modify the Request we were given. This is required by the
// specification of http.RoundTripper.
req = cloneRequest(req)
q := req.URL.Query()
//
// Since we are going to modify only req.URL here, we only need a deep copy
// of req.URL.
req2 := new(http.Request)
*req2 = *req
req2.URL = new(url.URL)
*req2.URL = *req.URL
q := req2.URL.Query()
q.Set("client_id", t.ClientID)
q.Set("client_secret", t.ClientSecret)
req.URL.RawQuery = q.Encode()
req2.URL.RawQuery = q.Encode()
// Make the HTTP request.
return t.transport().RoundTrip(req)
return t.transport().RoundTrip(req2)
}
// Client returns an *http.Client that makes requests which are subject to the
@@ -851,12 +943,24 @@ type BasicAuthTransport struct {
// RoundTrip implements the RoundTripper interface.
func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req = cloneRequest(req) // per RoundTrip contract
req.SetBasicAuth(t.Username, t.Password)
if t.OTP != "" {
req.Header.Set(headerOTP, t.OTP)
// To set extra headers, we must make a copy of the Request so
// that we don't modify the Request we were given. This is required by the
// specification of http.RoundTripper.
//
// Since we are going to modify only req.Header here, we only need a deep copy
// of req.Header.
req2 := new(http.Request)
*req2 = *req
req2.Header = make(http.Header, len(req.Header))
for k, s := range req.Header {
req2.Header[k] = append([]string(nil), s...)
}
return t.transport().RoundTrip(req)
req2.SetBasicAuth(t.Username, t.Password)
if t.OTP != "" {
req2.Header.Set(headerOTP, t.OTP)
}
return t.transport().RoundTrip(req2)
}
// Client returns an *http.Client that makes requests that are authenticated
@@ -872,20 +976,6 @@ func (t *BasicAuthTransport) transport() http.RoundTripper {
return http.DefaultTransport
}
// cloneRequest returns a clone of the provided *http.Request. The clone is a
// shallow copy of the struct and its Header map.
func cloneRequest(r *http.Request) *http.Request {
// shallow copy of the struct
r2 := new(http.Request)
*r2 = *r
// deep copy of the Header
r2.Header = make(http.Header, len(r.Header))
for k, s := range r.Header {
r2.Header[k] = append([]string(nil), s...)
}
return r2
}
// formatRateReset formats d to look like "[rate reset in 2s]" or
// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]"
// for the negative cases.
@@ -919,6 +1009,10 @@ func Bool(v bool) *bool { return &v }
// to store v and returns a pointer to it.
func Int(v int) *int { return &v }
// Int64 is a helper routine that allocates a new int64 value
// to store v and returns a pointer to it.
func Int64(v int64) *int64 { return &v }
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string { return &v }