Repository: google/go-github
Pull request #1042 (2018-11-04 19:38:04)

Support updates to Marketplace APIs and webhook payload
Adds support for pending changes to Marketplace plans which were added to the API. (discussed here https://developer.github.com/changes/2018-10-31-improved-experience-for-marketplace-pending-changes/) and referenced here #1040.


Patch:
diff --git a/AUTHORS b/AUTHORS
index 19396ee0..53c189ed 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,9 +22,11 @@ Allen Sun <shlallen1990@gmail.com>
 Amey Sakhadeo <me@ameyms.com>
 Andreas Garnæs <https://github.com/andreas>
 Andrew Ryabchun <aryabchun@mail.ua>
+Andy Grunwald <andygrunwald@gmail.com>
 Andy Hume <andyhume@gmail.com>
 Andy Lindeman <andy@lindeman.io>
 Anshuman Bhartiya <anshuman.bhartiya@gmail.com>
+Antoine <antoine.tu@mail.mcgill.ca>
 Antoine Pelisse <apelisse@gmail.com>
 Anubha Kushwaha <anubha_bt2k14@dtu.ac.in>
 appilon <apilon@hashicorp.com>
@@ -56,6 +58,7 @@ Craig Peterson <cpeterson@stackoverflow.com>
 Cristian Maglie <c.maglie@bug.st>
 Daehyeok Mun <daehyeok@gmail.com>
 Daniel Leavitt <daniel.leavitt@gmail.com>
+Daniel Nilsson <daniel.nilsson1989@gmail.com>
 Dave Du Cros <davidducros@gmail.com>
 Dave Henderson <dhenderson@gmail.com>
 David Deng <daviddengcn@gmail.com>
@@ -85,6 +88,7 @@ George Kontridze <george.kontridze@gmail.com>
 Georgy Buranov <gburanov@gmail.com>
 Gnahz <p@oath.pl>
 Google Inc.
+Grachev Mikhail <work@mgrachev.com>
 griffin_stewie <panterathefamilyguy@gmail.com>
 Guillaume Jacquet <guillaume.jacquet@gmail.com>
 Guz Alexander <kalimatas@gmail.com>
@@ -142,6 +146,7 @@ Michael Spiegel <michael.m.spiegel@gmail.com>
 Michael Tiller <michael.tiller@gmail.com>
 Michał Glapa <michal.glapa@gmail.com>
 Nathan VanBenschoten <nvanbenschoten@gmail.com>
+Navaneeth Suresh <navaneeths1998@gmail.com>
 Neil O'Toole <neilotoole@apache.org>
 Nick Miyake <nmiyake@palantir.com>
 Nick Spragg <nick.spragg@bbc.co.uk>
@@ -184,6 +189,7 @@ Sebastian Mandrean <sebastian.mandrean@gmail.com>
 Sebastian Mæland Pedersen <sem.pedersen@stud.uis.no>
 Sevki <s@sevki.org>
 Shagun Khemka <shagun.khemka60@gmail.com>
+shakeelrao <shakeelrao79@gmail.com>
 Shawn Catanzarite <me@shawncatz.com>
 Shawn Smith <shawnpsmith@gmail.com>
 sona-tar <sona.zip@gmail.com>
diff --git a/github/apps_marketplace.go b/github/apps_marketplace.go
index 3f35b915..6dd568a2 100644
--- a/github/apps_marketplace.go
+++ b/github/apps_marketplace.go
@@ -27,36 +27,52 @@ type MarketplaceService struct {
 
 // MarketplacePlan represents a GitHub Apps Marketplace Listing Plan.
 type MarketplacePlan struct {
-	URL                 *string   `json:"url,omitempty"`
-	AccountsURL         *string   `json:"accounts_url,omitempty"`
-	ID                  *int64    `json:"id,omitempty"`
-	Name                *string   `json:"name,omitempty"`
-	Description         *string   `json:"description,omitempty"`
-	MonthlyPriceInCents *int      `json:"monthly_price_in_cents,omitempty"`
-	YearlyPriceInCents  *int      `json:"yearly_price_in_cents,omitempty"`
-	PriceModel          *string   `json:"price_model,omitempty"`
-	UnitName            *string   `json:"unit_name,omitempty"`
-	Bullets             *[]string `json:"bullets,omitempty"`
+	URL                 *string `json:"url,omitempty"`
+	AccountsURL         *string `json:"accounts_url,omitempty"`
+	ID                  *int64  `json:"id,omitempty"`
+	Name                *string `json:"name,omitempty"`
+	Description         *string `json:"description,omitempty"`
+	MonthlyPriceInCents *int    `json:"monthly_price_in_cents,omitempty"`
+	YearlyPriceInCents  *int    `json:"yearly_price_in_cents,omitempty"`
+	// The pricing model for this listing.  Can be one of "flat-rate", "per-unit", or "free".
+	PriceModel *string   `json:"price_model,omitempty"`
+	UnitName   *string   `json:"unit_name,omitempty"`
+	Bullets    *[]string `json:"bullets,omitempty"`
+	// State can be one of the values "draft" or "published".
+	State        *string `json:"state,omitempty"`
+	HasFreeTrial *bool   `json:"has_free_trial,omitempty"`
 }
 
 // MarketplacePurchase represents a GitHub Apps Marketplace Purchase.
 type MarketplacePurchase struct {
+	// BillingCycle can be one of the values "yearly", "monthly" or nil.
 	BillingCycle    *string                 `json:"billing_cycle,omitempty"`
-	NextBillingDate *string                 `json:"next_billing_date,omitempty"`
+	NextBillingDate *Timestamp              `json:"next_billing_date,omitempty"`
 	UnitCount       *int                    `json:"unit_count,omitempty"`
 	Plan            *MarketplacePlan        `json:"plan,omitempty"`
 	Account         *MarketplacePlanAccount `json:"account,omitempty"`
+	OnFreeTrial     *bool                   `json:"on_free_trial,omitempty"`
+	FreeTrialEndsOn *Timestamp              `json:"free_trial_ends_on,omitempty"`
+}
+
+// MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan.
+type MarketplacePendingChange struct {
+	EffectiveDate *Timestamp       `json:"effective_date,omitempty"`
+	UnitCount     *int             `json:"unit_count,omitempty"`
+	ID            *int64           `json:"id,omitempty"`
+	Plan          *MarketplacePlan `json:"plan,omitempty"`
 }
 
 // MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan.
 type MarketplacePlanAccount struct {
-	URL                      *string              `json:"url,omitempty"`
-	Type                     *string              `json:"type,omitempty"`
-	ID                       *int64               `json:"id,omitempty"`
-	Login                    *string              `json:"login,omitempty"`
-	Email                    *string              `json:"email,omitempty"`
-	OrganizationBillingEmail *string              `json:"organization_billing_email,omitempty"`
-	MarketplacePurchase      *MarketplacePurchase `json:"marketplace_purchase,omitempty"`
+	URL                      *string                   `json:"url,omitempty"`
+	Type                     *string                   `json:"type,omitempty"`
+	ID                       *int64                    `json:"id,omitempty"`
+	Login                    *string                   `json:"login,omitempty"`
+	Email                    *string                   `json:"email,omitempty"`
+	OrganizationBillingEmail *string                   `json:"organization_billing_email,omitempty"`
+	MarketplacePurchase      *MarketplacePurchase      `json:"marketplace_purchase,omitempty"`
+	MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"`
 }
 
 // ListPlans lists all plans for your Marketplace listing.
@@ -155,7 +171,6 @@ func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context
 	if err != nil {
 		return nil, resp, err
 	}
-
 	return purchases, resp, nil
 }
 
diff --git a/github/event_types.go b/github/event_types.go
index 1792f43c..d3f7d332 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -308,7 +308,7 @@ type LabelEvent struct {
 // Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent
 type MarketplacePurchaseEvent struct {
 	// Action is the action that was performed. Possible values are:
-	// "purchased", "cancelled", "changed".
+	// "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed".
 	Action *string `json:"action,omitempty"`
 
 	// The following fields are only populated by Webhook events.
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 62573892..776ef42e 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -1292,6 +1292,14 @@ func (c *CommitFile) GetPatch() string {
 	return *c.Patch
 }
 
+// GetPreviousFilename returns the PreviousFilename field if it's non-nil, zero value otherwise.
+func (c *CommitFile) GetPreviousFilename() string {
+	if c == nil || c.PreviousFilename == nil {
+		return ""
+	}
+	return *c.PreviousFilename
+}
+
 // GetRawURL returns the RawURL field if it's non-nil, zero value otherwise.
 func (c *CommitFile) GetRawURL() string {
 	if c == nil || c.RawURL == nil {
@@ -4644,6 +4652,38 @@ func (l *ListCheckSuiteResults) GetTotal() int {
 	return *l.Total
 }
 
+// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise.
+func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp {
+	if m == nil || m.EffectiveDate == nil {
+		return Timestamp{}
+	}
+	return *m.EffectiveDate
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (m *MarketplacePendingChange) GetID() int64 {
+	if m == nil || m.ID == nil {
+		return 0
+	}
+	return *m.ID
+}
+
+// GetPlan returns the Plan field.
+func (m *MarketplacePendingChange) GetPlan() *MarketplacePlan {
+	if m == nil {
+		return nil
+	}
+	return m.Plan
+}
+
+// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise.
+func (m *MarketplacePendingChange) GetUnitCount() int {
+	if m == nil || m.UnitCount == nil {
+		return 0
+	}
+	return *m.UnitCount
+}
+
 // GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise.
 func (m *MarketplacePlan) GetAccountsURL() string {
 	if m == nil || m.AccountsURL == nil {
@@ -4668,6 +4708,14 @@ func (m *MarketplacePlan) GetDescription() string {
 	return *m.Description
 }
 
+// GetHasFreeTrial returns the HasFreeTrial field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetHasFreeTrial() bool {
+	if m == nil || m.HasFreeTrial == nil {
+		return false
+	}
+	return *m.HasFreeTrial
+}
+
 // GetID returns the ID field if it's non-nil, zero value otherwise.
 func (m *MarketplacePlan) GetID() int64 {
 	if m == nil || m.ID == nil {
@@ -4700,6 +4748,14 @@ func (m *MarketplacePlan) GetPriceModel() string {
 	return *m.PriceModel
 }
 
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (m *MarketplacePlan) GetState() string {
+	if m == nil || m.State == nil {
+		return ""
+	}
+	return *m.State
+}
+
 // GetUnitName returns the UnitName field if it's non-nil, zero value otherwise.
 func (m *MarketplacePlan) GetUnitName() string {
 	if m == nil || m.UnitName == nil {
@@ -4748,6 +4804,14 @@ func (m *MarketplacePlanAccount) GetLogin() string {
 	return *m.Login
 }
 
+// GetMarketplacePendingChange returns the MarketplacePendingChange field.
+func (m *MarketplacePlanAccount) GetMarketplacePendingChange() *MarketplacePendingChange {
+	if m == nil {
+		return nil
+	}
+	return m.MarketplacePendingChange
+}
+
 // GetMarketplacePurchase returns the MarketplacePurchase field.
 func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase {
 	if m == nil {
@@ -4796,14 +4860,30 @@ func (m *MarketplacePurchase) GetBillingCycle() string {
 	return *m.BillingCycle
 }
 
+// GetFreeTrialEndsOn returns the FreeTrialEndsOn field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchase) GetFreeTrialEndsOn() Timestamp {
+	if m == nil || m.FreeTrialEndsOn == nil {
+		return Timestamp{}
+	}
+	return *m.FreeTrialEndsOn
+}
+
 // GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise.
-func (m *MarketplacePurchase) GetNextBillingDate() string {
+func (m *MarketplacePurchase) GetNextBillingDate() Timestamp {
 	if m == nil || m.NextBillingDate == nil {
-		return ""
+		return Timestamp{}
 	}
 	return *m.NextBillingDate
 }
 
+// GetOnFreeTrial returns the OnFreeTrial field if it's non-nil, zero value otherwise.
+func (m *MarketplacePurchase) GetOnFreeTrial() bool {
+	if m == nil || m.OnFreeTrial == nil {
+		return false
+	}
+	return *m.OnFreeTrial
+}
+
 // GetPlan returns the Plan field.
 func (m *MarketplacePurchase) GetPlan() *MarketplacePlan {
 	if m == nil {
@@ -10108,6 +10188,22 @@ func (s *ServiceHook) GetName() string {
 	return *s.Name
 }
 
+// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise.
+func (s *SignaturesProtectedBranch) GetEnabled() bool {
+	if s == nil || s.Enabled == nil {
+		return false
+	}
+	return *s.Enabled
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (s *SignaturesProtectedBranch) GetURL() string {
+	if s == nil || s.URL == nil {
+		return ""
+	}
+	return *s.URL
+}
+
 // GetPayload returns the Payload field if it's non-nil, zero value otherwise.
 func (s *SignatureVerification) GetPayload() string {
 	if s == nil || s.Payload == nil {
@@ -11572,6 +11668,14 @@ func (u *User) GetTotalPrivateRepos() int {
 	return *u.TotalPrivateRepos
 }
 
+// GetTwoFactorAuthentication returns the TwoFactorAuthentication field if it's non-nil, zero value otherwise.
+func (u *User) GetTwoFactorAuthentication() bool {
+	if u == nil || u.TwoFactorAuthentication == nil {
+		return false
+	}
+	return *u.TwoFactorAuthentication
+}
+
 // GetType returns the Type field if it's non-nil, zero value otherwise.
 func (u *User) GetType() string {
 	if u == nil || u.Type == nil {
diff --git a/github/github.go b/github/github.go
index 893ddefb..c58d7f9b 100644
--- a/github/github.go
+++ b/github/github.go
@@ -125,6 +125,9 @@ const (
 
 	// 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"
 )
 
 // A Client manages communication with the GitHub API.
diff --git a/github/projects.go b/github/projects.go
index 76ef1e0a..210e3b5c 100644
--- a/github/projects.go
+++ b/github/projects.go
@@ -366,7 +366,7 @@ type ProjectCardOptions struct {
 	// The ID (not Number) of the Issue to associate with this card.
 	// Note and ContentID are mutually exclusive.
 	ContentID int64 `json:"content_id,omitempty"`
-	// The type of content to associate with this card. Possible values are: "Issue".
+	// The type of content to associate with this card. Possible values are: "Issue" and "PullRequest".
 	ContentType string `json:"content_type,omitempty"`
 	// Use true to archive a project card.
 	// Specify false if you need to restore a previously archived project card.
diff --git a/github/repos.go b/github/repos.go
index e783ccbe..d09b5cc8 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -698,6 +698,13 @@ type DismissalRestrictionsRequest struct {
 	Teams *[]string `json:"teams,omitempty"`
 }
 
+// SignaturesProtectedBranch represents the protection status of an individual branch.
+type SignaturesProtectedBranch struct {
+	URL *string `json:"url,omitempty"`
+	// Commits pushed to matching branches must have verified signatures.
+	Enabled *bool `json:"enabled,omitempty"`
+}
+
 // ListBranches lists branches for the specified repository.
 //
 // GitHub API docs: https://developer.github.com/v3/repos/#list-branches
@@ -850,6 +857,67 @@ func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner,
 	return s.client.Do(ctx, req, nil)
 }
 
+// GetSignaturesProtectedBranch gets required signatures of protected branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-signatures-of-protected-branch
+func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	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", mediaTypeSignaturePreview)
+
+	p := new(SignaturesProtectedBranch)
+	resp, err := s.client.Do(ctx, req, p)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return p, resp, nil
+}
+
+// RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch.
+// It requires admin access and branch protection to be enabled.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-required-signatures-of-protected-branch
+func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// TODO: remove custom Accept header when this API fully launches
+	req.Header.Set("Accept", mediaTypeSignaturePreview)
+
+	r := new(SignaturesProtectedBranch)
+	resp, err := s.client.Do(ctx, req, r)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return r, resp, err
+}
+
+// OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-required-signatures-of-protected-branch
+func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// TODO: remove custom Accept header when this API fully launches
+	req.Header.Set("Accept", mediaTypeSignaturePreview)
+
+	return s.client.Do(ctx, req, nil)
+}
+
 // UpdateRequiredStatusChecks updates the required status checks for a given protected branch.
 //
 // GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch
diff --git a/github/repos_commits.go b/github/repos_commits.go
index 04faa3ea..1acfa5ad 100644
--- a/github/repos_commits.go
+++ b/github/repos_commits.go
@@ -48,16 +48,17 @@ func (c CommitStats) String() string {
 
 // CommitFile represents a file modified in a commit.
 type CommitFile struct {
-	SHA         *string `json:"sha,omitempty"`
-	Filename    *string `json:"filename,omitempty"`
-	Additions   *int    `json:"additions,omitempty"`
-	Deletions   *int    `json:"deletions,omitempty"`
-	Changes     *int    `json:"changes,omitempty"`
-	Status      *string `json:"status,omitempty"`
-	Patch       *string `json:"patch,omitempty"`
-	BlobURL     *string `json:"blob_url,omitempty"`
-	RawURL      *string `json:"raw_url,omitempty"`
-	ContentsURL *string `json:"contents_url,omitempty"`
+	SHA              *string `json:"sha,omitempty"`
+	Filename         *string `json:"filename,omitempty"`
+	Additions        *int    `json:"additions,omitempty"`
+	Deletions        *int    `json:"deletions,omitempty"`
+	Changes          *int    `json:"changes,omitempty"`
+	Status           *string `json:"status,omitempty"`
+	Patch            *string `json:"patch,omitempty"`
+	BlobURL          *string `json:"blob_url,omitempty"`
+	RawURL           *string `json:"raw_url,omitempty"`
+	ContentsURL      *string `json:"contents_url,omitempty"`
+	PreviousFilename *string `json:"previous_filename,omitempty"`
 }
 
 func (c CommitFile) String() string {
diff --git a/github/users.go b/github/users.go
index c4fd09b4..a4f74904 100644
--- a/github/users.go
+++ b/github/users.go
@@ -18,34 +18,35 @@ type UsersService service
 
 // User represents a GitHub user.
 type User struct {
-	Login             *string    `json:"login,omitempty"`
-	ID                *int64     `json:"id,omitempty"`
-	NodeID            *string    `json:"node_id,omitempty"`
-	AvatarURL         *string    `json:"avatar_url,omitempty"`
-	HTMLURL           *string    `json:"html_url,omitempty"`
-	GravatarID        *string    `json:"gravatar_id,omitempty"`
-	Name              *string    `json:"name,omitempty"`
-	Company           *string    `json:"company,omitempty"`
-	Blog              *string    `json:"blog,omitempty"`
-	Location          *string    `json:"location,omitempty"`
-	Email             *string    `json:"email,omitempty"`
-	Hireable          *bool      `json:"hireable,omitempty"`
-	Bio               *string    `json:"bio,omitempty"`
-	PublicRepos       *int       `json:"public_repos,omitempty"`
-	PublicGists       *int       `json:"public_gists,omitempty"`
-	Followers         *int       `json:"followers,omitempty"`
-	Following         *int       `json:"following,omitempty"`
-	CreatedAt         *Timestamp `json:"created_at,omitempty"`
-	UpdatedAt         *Timestamp `json:"updated_at,omitempty"`
-	SuspendedAt       *Timestamp `json:"suspended_at,omitempty"`
-	Type              *string    `json:"type,omitempty"`
-	SiteAdmin         *bool      `json:"site_admin,omitempty"`
-	TotalPrivateRepos *int       `json:"total_private_repos,omitempty"`
-	OwnedPrivateRepos *int       `json:"owned_private_repos,omitempty"`
-	PrivateGists      *int       `json:"private_gists,omitempty"`
-	DiskUsage         *int       `json:"disk_usage,omitempty"`
-	Collaborators     *int       `json:"collaborators,omitempty"`
-	Plan              *Plan      `json:"plan,omitempty"`
+	Login                   *string    `json:"login,omitempty"`
+	ID                      *int64     `json:"id,omitempty"`
+	NodeID                  *string    `json:"node_id,omitempty"`
+	AvatarURL               *string    `json:"avatar_url,omitempty"`
+	HTMLURL                 *string    `json:"html_url,omitempty"`
+	GravatarID              *string    `json:"gravatar_id,omitempty"`
+	Name                    *string    `json:"name,omitempty"`
+	Company                 *string    `json:"company,omitempty"`
+	Blog                    *string    `json:"blog,omitempty"`
+	Location                *string    `json:"location,omitempty"`
+	Email                   *string    `json:"email,omitempty"`
+	Hireable                *bool      `json:"hireable,omitempty"`
+	Bio                     *string    `json:"bio,omitempty"`
+	PublicRepos             *int       `json:"public_repos,omitempty"`
+	PublicGists             *int       `json:"public_gists,omitempty"`
+	Followers               *int       `json:"followers,omitempty"`
+	Following               *int       `json:"following,omitempty"`
+	CreatedAt               *Timestamp `json:"created_at,omitempty"`
+	UpdatedAt               *Timestamp `json:"updated_at,omitempty"`
+	SuspendedAt             *Timestamp `json:"suspended_at,omitempty"`
+	Type                    *string    `json:"type,omitempty"`
+	SiteAdmin               *bool      `json:"site_admin,omitempty"`
+	TotalPrivateRepos       *int       `json:"total_private_repos,omitempty"`
+	OwnedPrivateRepos       *int       `json:"owned_private_repos,omitempty"`
+	PrivateGists            *int       `json:"private_gists,omitempty"`
+	DiskUsage               *int       `json:"disk_usage,omitempty"`
+	Collaborators           *int       `json:"collaborators,omitempty"`
+	TwoFactorAuthentication *bool      `json:"two_factor_authentication,omitempty"`
+	Plan                    *Plan      `json:"plan,omitempty"`
 
 	// API URLs
 	URL               *string `json:"url,omitempty"`


Test patch:
diff --git a/github/apps_marketplace_test.go b/github/apps_marketplace_test.go
index 0c1f86c7..e293c83a 100644
--- a/github/apps_marketplace_test.go
+++ b/github/apps_marketplace_test.go
@@ -111,7 +111,7 @@ func TestMarketplaceService_ListPlanAccountsForAccount(t *testing.T) {
 
 	mux.HandleFunc("/marketplace_listing/accounts/1", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, "GET")
-		fmt.Fprint(w, `[{"id":1}]`)
+		fmt.Fprint(w, `[{"id":1, "marketplace_pending_change": {"id": 77}}]`)
 	})
 
 	opt := &ListOptions{Page: 1, PerPage: 2}
@@ -121,7 +121,7 @@ func TestMarketplaceService_ListPlanAccountsForAccount(t *testing.T) {
 		t.Errorf("Marketplace.ListPlanAccountsForAccount returned error: %v", err)
 	}
 
-	want := []*MarketplacePlanAccount{{ID: Int64(1)}}
+	want := []*MarketplacePlanAccount{{ID: Int64(1), MarketplacePendingChange: &MarketplacePendingChange{ID: Int64(77)}}}
 	if !reflect.DeepEqual(accounts, want) {
 		t.Errorf("Marketplace.ListPlanAccountsForAccount returned %+v, want %+v", accounts, want)
 	}
diff --git a/github/repos_test.go b/github/repos_test.go
index 08d64412..4109eda9 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -1055,6 +1055,72 @@ func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
 	}
 }
 
+func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`)
+	})
+
+	signature, _, err := client.Repositories.GetSignaturesProtectedBranch(context.Background(), "o", "r", "b")
+	if err != nil {
+		t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err)
+	}
+
+	want := &SignaturesProtectedBranch{
+		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
+		Enabled: Bool(false),
+	}
+
+	if !reflect.DeepEqual(signature, want) {
+		t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want)
+	}
+}
+
+func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`)
+	})
+
+	signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(context.Background(), "o", "r", "b")
+	if err != nil {
+		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err)
+	}
+
+	want := &SignaturesProtectedBranch{
+		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
+		Enabled: Bool(true),
+	}
+
+	if !reflect.DeepEqual(signature, want) {
+		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want)
+	}
+}
+
+func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	_, err := client.Repositories.OptionalSignaturesOnProtectedBranch(context.Background(), "o", "r", "b")
+	if err != nil {
+		t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err)
+	}
+}
+
 func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
 	req := PullRequestReviewsEnforcementRequest{}